Go HTTP server resets connection on multipart form with file and text

100 views Asked by At

I've been trying to set up an HTTP server in Go that allows users to upload files via HTML forms. This form would also have a text input for other reasons. However, upon submitting the form, my browser reports the connection has reset (I've tried with Firefox and Chromium), and inspection shows that the server doesn't even get to the handler function of the upload end point before this reset, though it doesn't crash. Strangely, this does not happen when the only inputs in the form are the file and submit.

Here is a minimal reproduction:

package main

import (
    "fmt"
    "net/http"
)

func showPage(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w,
`<!DOCTYPE html>
<html>
    <body>
    <form enctype="multipart/form-data" action="/upload">
        <input type="file" name="file" />
        <input type="text" name="lol" />
        <input type="submit" value="upload" />
    </form>
</body>
</html>`)
}

func uploadHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Println("yay!")
    fmt.Fprint(w, "yay!")
}

func main() {
    http.HandleFunc("/", showPage)
    http.HandleFunc("/upload/", uploadHandler)

    http.ListenAndServe(":8080", nil)
}

Running the above code and submitting a file in the form at http://localhost:8080/ should show a "yay!" page and print "yay!" on the server's console. Instead, upon submitting a large enough file (very small files don't cause the problem), the connection resets and nothing is printed on the console. This 5MB audio sample is large enough to cause the issue for me.

If the only input in the form is the file, for some reason, everything runs fine.

1

There are 1 answers

3
Maristela Vasco On

The handler does not read any of the request body.

On return from the handler, the net/http server closes the connection when the size of the unread request body is greater than 262,144 bytes.

The client receives a connection reset while attempting to write the request body. The client errors out before reading the response.

Fix by reading the request body. Given that you expect a multipart form, a call to ParseMultipartForm is the easiest way to read the request body.

func uploadHandler(w http.ResponseWriter, r *http.Request) {
    if err := r.ParseMultipartForm(65535); err != nil {
        http.Error(w, "bad request", 400)
        return
    }
    fmt.Println("yay!")
    fmt.Fprint(w, "yay!")
}