gogo-http

How to determine if I've reached the size limit via Go's MaxBytesReader


I am new to Go, and using Mux to accept HTTP POST data. I would like to use the MaxBytesReader to ensure a client does not overwhelm my server. According to the code, there is a requestBodyLimit boolean which indicates whether that limit has been hit.

My question is: when using MaxBytesReader, how can I determine whether I have actually hit the maximum when processing a request?

Here is my code:

package main

import (
        "fmt"
        "log"
        "html/template"
        "net/http"

        "github.com/gorilla/mux"
)

func main() {
        r := mux.NewRouter()
        r.HandleFunc("/handle", maxBytes(PostHandler)).Methods("POST")
        http.ListenAndServe(":8080", r)
}

// Middleware to enforce the maximum post body size
func maxBytes(f http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
            // As an example, limit post body to 10 bytes
            r.Body = http.MaxBytesReader(w, r.Body, 10)
            f(w, r)
    }
}

func PostHandler(w http.ResponseWriter, r *http.Request) {
    // How do I know if the form data has been truncated?
    book := r.FormValue("email")
    fmt.Fprintf(w, "You've requested the book: %s\n", book)
}

How can I:


Solution

  • Call ParseForm at the beginning of the handler. If this method returns an error, then the size limit was breached or the request body was invalid in some way. Write an error status and return from the handler.

    There's not an easy way to detect if the error is a result of the size limit breach or some other error.

    func PostHandler(w http.ResponseWriter, r *http.Request) {
        if err := r.ParseForm(); err != nil {
            http.Error(w, "Bad Request", http.StatusBadRequest)
            return
        }
    
        book := r.FormValue("email")
        fmt.Fprintf(w, "You've requested the book: %s\n", book)
    }
    

    Depending on your needs, it may be better to place the check in the middleware:

    func maxBytes(f http.HandlerFunc) http.HandlerFunc {
        return func(w http.ResponseWriter, r *http.Request) {
                r.Body = http.MaxBytesReader(w, r.Body, 10)
                if err := r.ParseForm(); err != nil {
                    http.Error(w, "Bad Request", http.StatusBadRequest)
                    return
                }
                f(w, r)
        }
    }