From 9e4e1b6ae33991bcfecfc3f0b34021f5457dfc1b Mon Sep 17 00:00:00 2001 From: Will McCutchen <will@mccutch.org> Date: Fri, 16 Jun 2017 17:32:37 -0700 Subject: [PATCH] Use middleware to limit request body size --- httpbin/handlers.go | 2 +- httpbin/helpers.go | 15 +++++++++------ httpbin/httpbin.go | 8 +++++++- httpbin/middleware.go | 9 +++++++++ 4 files changed, 26 insertions(+), 8 deletions(-) diff --git a/httpbin/handlers.go b/httpbin/handlers.go index 159e403..d987dbb 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 2fa7a92..f513e39 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 1c2a462..93d2690 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 ec04086..5e896a0 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) + }) +} -- GitLab