Commit 8662789a authored by Jacob Vosmaer's avatar Jacob Vosmaer

Limit API failure response buffer size

parent 5f36b358
...@@ -18,10 +18,15 @@ import ( ...@@ -18,10 +18,15 @@ import (
"gitlab.com/gitlab-org/gitlab-workhorse/internal/secret" "gitlab.com/gitlab-org/gitlab-workhorse/internal/secret"
) )
// Custom content type for API responses, to catch routing / programming mistakes const (
const ResponseContentType = "application/vnd.gitlab-workhorse+json" // Custom content type for API responses, to catch routing / programming mistakes
ResponseContentType = "application/vnd.gitlab-workhorse+json"
const RequestHeader = "Gitlab-Workhorse-Api-Request" // This header carries the JWT token for gitlab-rails
RequestHeader = "Gitlab-Workhorse-Api-Request"
failureResponseLimit = 32768
)
type API struct { type API struct {
Client *http.Client Client *http.Client
...@@ -224,8 +229,7 @@ func (api *API) PreAuthorizeHandler(next HandleFunc, suffix string) http.Handler ...@@ -224,8 +229,7 @@ func (api *API) PreAuthorizeHandler(next HandleFunc, suffix string) http.Handler
// X-Accel-Buffering: no) but we still want to free up the Unicorn worker // X-Accel-Buffering: no) but we still want to free up the Unicorn worker
// that generated httpResponse as fast as possible. To do this we buffer // that generated httpResponse as fast as possible. To do this we buffer
// the entire response body in memory before sending it on. // the entire response body in memory before sending it on.
responseBody := &bytes.Buffer{} responseBody, err := bufferResponse(httpResponse.Body)
_, err := io.Copy(responseBody, httpResponse.Body)
if err != nil { if err != nil {
helper.Fail500(w, r, err) helper.Fail500(w, r, err)
} }
...@@ -262,3 +266,17 @@ func (api *API) PreAuthorizeHandler(next HandleFunc, suffix string) http.Handler ...@@ -262,3 +266,17 @@ func (api *API) PreAuthorizeHandler(next HandleFunc, suffix string) http.Handler
next(w, r, authResponse) next(w, r, authResponse)
}) })
} }
func bufferResponse(r io.Reader) (*bytes.Buffer, error) {
responseBody := &bytes.Buffer{}
n, err := io.Copy(responseBody, io.LimitReader(r, failureResponseLimit))
if err != nil {
return nil, err
}
if n == failureResponseLimit {
return nil, fmt.Errorf("response body exceeded maximum buffer size (%d bytes)", failureResponseLimit)
}
return responseBody, nil
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment