]> Cypherpunks repositories - gostls13.git/commitdiff
net/http: update HandlerWritesTooMuch test to allow different h1/h2 behavior
authorDamien Neil <dneil@google.com>
Mon, 8 Apr 2024 18:43:03 +0000 (11:43 -0700)
committerDamien Neil <dneil@google.com>
Mon, 8 Apr 2024 20:33:30 +0000 (20:33 +0000)
Rather than requiring that HTTP/1 and HTTP/2 servers behave identically
when a misbehaving handler writes too many bytes, check only that both
behave reasonably.

In particular, allow the handler to defer detection of a write overrun
until flush time, and permit the HTTP/2 handler to reset the stream
rather than requring it to return a truncated body as HTTP/1 must.

For #56019

Change-Id: I0838e550c4fc202dcbb8bf39ce0fa4a367ca7e71
Reviewed-on: https://go-review.googlesource.com/c/go/+/577415
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
src/net/http/clientserver_test.go

index 32948f3aed4abe0dc5739d13f3ca43f611eacecb..1fe4eed3f7123419b0d75c118b04a029b0848675 100644 (file)
@@ -510,19 +510,35 @@ func TestH12_HandlerWritesTooLittle(t *testing.T) {
 // doesn't make it possible to send bogus data. For those tests, see
 // transport_test.go (for HTTP/1) or x/net/http2/transport_test.go
 // (for HTTP/2).
-func TestH12_HandlerWritesTooMuch(t *testing.T) {
-       h12Compare{
-               Handler: func(w ResponseWriter, r *Request) {
-                       w.Header().Set("Content-Length", "3")
-                       w.(Flusher).Flush()
-                       io.WriteString(w, "123")
-                       w.(Flusher).Flush()
-                       n, err := io.WriteString(w, "x") // too many
-                       if n > 0 || err == nil {
-                               t.Errorf("for proto %q, final write = %v, %v; want 0, some error", r.Proto, n, err)
-                       }
-               },
-       }.run(t)
+func TestHandlerWritesTooMuch(t *testing.T) { run(t, testHandlerWritesTooMuch) }
+func testHandlerWritesTooMuch(t *testing.T, mode testMode) {
+       wantBody := []byte("123")
+       cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
+               rc := NewResponseController(w)
+               w.Header().Set("Content-Length", fmt.Sprintf("%v", len(wantBody)))
+               rc.Flush()
+               w.Write(wantBody)
+               rc.Flush()
+               n, err := io.WriteString(w, "x") // too many
+               if err == nil {
+                       err = rc.Flush()
+               }
+               // TODO: Check that this is ErrContentLength, not just any error.
+               if err == nil {
+                       t.Errorf("for proto %q, final write = %v, %v; want _, some error", r.Proto, n, err)
+               }
+       }))
+
+       res, err := cst.c.Get(cst.ts.URL)
+       if err != nil {
+               t.Fatal(err)
+       }
+       defer res.Body.Close()
+
+       gotBody, _ := io.ReadAll(res.Body)
+       if !bytes.Equal(gotBody, wantBody) {
+               t.Fatalf("got response body: %q; want %q", gotBody, wantBody)
+       }
 }
 
 // Verify that both our HTTP/1 and HTTP/2 request and auto-decompress gzip.