Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

go

go-http

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:

  • Determine that I have reached the max POST limit (or have access to requestBodyLimit

  • Have my code be able to branch on this condition?

like image 897
poundifdef Avatar asked Mar 06 '23 05:03

poundifdef


1 Answers

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)
    }
}
like image 107
Bayta Darell Avatar answered Mar 09 '23 06:03

Bayta Darell