diff --git a/httpbin/handlers.go b/httpbin/handlers.go index 159e403128d930c655f452b48a203ac5aa69e08b..d987dbbaf8c84b502094c36898e8f2f480b9e8c4 100644 --- a/httpbin/handlers.go +++ b/httpbin/handlers.go @@ -63,7 +63,7 @@ func (h *HTTPBin) RequestWithBody(w http.ResponseWriter, r *http.Request) { URL: getURL(r).String(), } - err := parseBody(w, r, resp, h.options.MaxMemory) + err := parseBody(w, r, resp) if err != nil { http.Error(w, fmt.Sprintf("error parsing request body: %s", err), http.StatusBadRequest) return diff --git a/httpbin/helpers.go b/httpbin/helpers.go index 2fa7a92a2a1bbf3b3790ca10592eb260bca17649..f513e3931a0640cc00b8ecf3f62ad2c85e786dfb 100644 --- a/httpbin/helpers.go +++ b/httpbin/helpers.go @@ -70,14 +70,14 @@ func writeHTML(w http.ResponseWriter, body []byte, status int) { // parseBody handles parsing a request body into our standard API response, // taking care to only consume the request body once based on the Content-Type -// of the request. The given Resp will be updated. -func parseBody(w http.ResponseWriter, r *http.Request, resp *bodyResponse, maxMemory int64) error { +// of the request. The given bodyResponse will be modified. +// +// Note: this function expects callers to limit the the maximum size of the +// request body. See, e.g., the limitRequestSize middleware. +func parseBody(w http.ResponseWriter, r *http.Request, resp *bodyResponse) error { if r.Body == nil { return nil } - - // Restrict size of request body - r.Body = http.MaxBytesReader(w, r.Body, maxMemory) defer r.Body.Close() ct := r.Header.Get("Content-Type") @@ -89,7 +89,10 @@ func parseBody(w http.ResponseWriter, r *http.Request, resp *bodyResponse, maxMe } resp.Form = r.PostForm case strings.HasPrefix(ct, "multipart/form-data"): - err := r.ParseMultipartForm(maxMemory) + // The memory limit here only restricts how many parts will be kept in + // memory before overflowing to disk: + // http://localhost:8080/pkg/net/http/#Request.ParseMultipartForm + err := r.ParseMultipartForm(1024 * 1024) if err != nil { return err } diff --git a/httpbin/httpbin.go b/httpbin/httpbin.go index 1c2a462752e17d82b8c103426a581077aff2c774..93d26900942a66c4eb8dda26fe353f13d3c8aadd 100644 --- a/httpbin/httpbin.go +++ b/httpbin/httpbin.go @@ -157,7 +157,13 @@ func (h *HTTPBin) Handler() http.Handler { mux.HandleFunc("/stream-bytes", http.NotFound) mux.HandleFunc("/links", http.NotFound) - return logger(cors(mux)) + // Apply global middleware + var handler http.Handler + handler = mux + handler = limitRequestSize(h.options.MaxMemory, handler) + handler = logger(handler) + handler = cors(handler) + return handler } // NewHTTPBin creates a new HTTPBin diff --git a/httpbin/middleware.go b/httpbin/middleware.go index ec040869ee9f15fb18107e88707c28e15ca2c2d3..5e896a08de26efb473acf9d2aaed07878e0af363 100644 --- a/httpbin/middleware.go +++ b/httpbin/middleware.go @@ -47,3 +47,12 @@ func methods(h http.HandlerFunc, methods ...string) http.HandlerFunc { h.ServeHTTP(w, r) } } + +func limitRequestSize(maxSize int64, h http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Body != nil { + r.Body = http.MaxBytesReader(w, r.Body, maxSize) + } + h.ServeHTTP(w, r) + }) +}