1
0
mirror of https://github.com/golang/go synced 2024-11-15 03:00:36 -07:00

net/http: update HandlerWritesTooMuch test to allow different h1/h2 behavior

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>
This commit is contained in:
Damien Neil 2024-04-08 11:43:03 -07:00
parent e8f5c04c1b
commit 50a5059056

View 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.