diff options
| author | Damien Neil <dneil@google.com> | 2022-08-11 15:56:34 -0700 |
|---|---|---|
| committer | Damien Neil <dneil@google.com> | 2022-08-12 17:25:47 +0000 |
| commit | ebbf2b44c59e2c473ed4ed6b0e044f5daee75e54 (patch) | |
| tree | 722c311ee54a67b4273004546c6401d47833cd28 /src | |
| parent | f3c39a83a3076eb560c7f687cbb35eef9b506e7d (diff) | |
| download | go-ebbf2b44c59e2c473ed4ed6b0e044f5daee75e54.tar.xz | |
net/http: add a test to verify form tempfiles are deleted
The HTTP/1 server deletes multipart form tempfiles after ServeHTTP
returns, but the HTTP/2 server does not. Add a test to verify
cleanup happens in both cases, temporarily disabled for the
HTTP/2 path.
For #20253
Updates #25965
Change-Id: Ib753f2761fe73b29321d9d4337dbb5090fd193c2
Reviewed-on: https://go-review.googlesource.com/c/go/+/423194
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Damien Neil <dneil@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Diffstat (limited to 'src')
| -rw-r--r-- | src/net/http/serve_test.go | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go index cb6312d641..f956e66c44 100644 --- a/src/net/http/serve_test.go +++ b/src/net/http/serve_test.go @@ -20,6 +20,7 @@ import ( "io" "log" "math/rand" + "mime/multipart" "net" . "net/http" "net/http/httptest" @@ -6758,3 +6759,68 @@ func TestProcessing(t *testing.T) { t.Errorf("unexpected response; got %q; should start by %q", got, expected) } } + +func TestParseFormCleanup_h1(t *testing.T) { testParseFormCleanup(t, h1Mode) } +func TestParseFormCleanup_h2(t *testing.T) { + t.Skip("https://go.dev/issue/20253") + testParseFormCleanup(t, h2Mode) +} + +func testParseFormCleanup(t *testing.T, h2 bool) { + const maxMemory = 1024 + const key = "file" + + if runtime.GOOS == "windows" { + // Windows sometimes refuses to remove a file that was just closed. + t.Skip("https://go.dev/issue/25965") + } + + setParallel(t) + defer afterTest(t) + cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { + r.ParseMultipartForm(maxMemory) + f, _, err := r.FormFile(key) + if err != nil { + t.Errorf("r.FormFile(%q) = %v", key, err) + return + } + of, ok := f.(*os.File) + if !ok { + t.Errorf("r.FormFile(%q) returned type %T, want *os.File", key, f) + return + } + w.Write([]byte(of.Name())) + })) + defer cst.close() + + fBuf := new(bytes.Buffer) + mw := multipart.NewWriter(fBuf) + mf, err := mw.CreateFormFile(key, "myfile.txt") + if err != nil { + t.Fatal(err) + } + if _, err := mf.Write(bytes.Repeat([]byte("A"), maxMemory*2)); err != nil { + t.Fatal(err) + } + if err := mw.Close(); err != nil { + t.Fatal(err) + } + req, err := NewRequest("POST", cst.ts.URL, fBuf) + if err != nil { + t.Fatal(err) + } + req.Header.Set("Content-Type", mw.FormDataContentType()) + res, err := cst.c.Do(req) + if err != nil { + t.Fatal(err) + } + defer res.Body.Close() + fname, err := io.ReadAll(res.Body) + if err != nil { + t.Fatal(err) + } + cst.close() + if _, err := os.Stat(string(fname)); !errors.Is(err, os.ErrNotExist) { + t.Errorf("file %q exists after HTTP handler returned", string(fname)) + } +} |
