diff options
author | Emmanuel T Odeke <emmanuel@orijtech.com> | 2019-10-08 00:23:08 -0700 |
---|---|---|
committer | Emmanuel Odeke <emm.odeke@gmail.com> | 2019-10-09 19:49:39 +0000 |
commit | e24a628ab1319381117a699190c7b522e57d034f (patch) | |
tree | 6445706de199fe0bb492d4dfffc23030f8ad1ab0 /src/net/http/serve_test.go | |
parent | 6cba4dbf80012c272cb04bd878dfba251d9bb05c (diff) | |
download | go-e24a628ab1319381117a699190c7b522e57d034f.tar.gz go-e24a628ab1319381117a699190c7b522e57d034f.zip |
net/http: do not sniff response if Content-Encoding header is set
Fixes #31753
Change-Id: I32ec5906ef6714e19b094f67cb0f10a211a9c500
Reviewed-on: https://go-review.googlesource.com/c/go/+/199799
Run-TryBot: Emmanuel Odeke <emm.odeke@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Diffstat (limited to 'src/net/http/serve_test.go')
-rw-r--r-- | src/net/http/serve_test.go | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go index 1d1449aa65..e1f8d2ddb7 100644 --- a/src/net/http/serve_test.go +++ b/src/net/http/serve_test.go @@ -10,6 +10,7 @@ import ( "bufio" "bytes" "compress/gzip" + "compress/zlib" "context" "crypto/tls" "encoding/json" @@ -6161,6 +6162,111 @@ func TestUnsupportedTransferEncodingsReturn501(t *testing.T) { } } +func TestContentEncodingNoSniffing_h1(t *testing.T) { + testContentEncodingNoSniffing(t, h1Mode) +} + +func TestContentEncodingNoSniffing_h2(t *testing.T) { + t.Skip("Waiting for h2_bundle.go update after https://golang.org/issue/31753") + testContentEncodingNoSniffing(t, h2Mode) +} + +// Issue 31753: don't sniff when Content-Encoding is set +func testContentEncodingNoSniffing(t *testing.T, h2 bool) { + setParallel(t) + defer afterTest(t) + + type setting struct { + name string + body []byte + + // setting contentEncoding as an interface instead of a string + // directly, so as to differentiate between 3 states: + // unset, empty string "" and set string "foo/bar". + contentEncoding interface{} + wantContentType string + } + + settings := []*setting{ + { + name: "gzip content-encoding, gzipped", // don't sniff. + contentEncoding: "application/gzip", + wantContentType: "", + body: func() []byte { + buf := new(bytes.Buffer) + gzw := gzip.NewWriter(buf) + gzw.Write([]byte("doctype html><p>Hello</p>")) + gzw.Close() + return buf.Bytes() + }(), + }, + { + name: "zlib content-encoding, zlibbed", // don't sniff. + contentEncoding: "application/zlib", + wantContentType: "", + body: func() []byte { + buf := new(bytes.Buffer) + zw := zlib.NewWriter(buf) + zw.Write([]byte("doctype html><p>Hello</p>")) + zw.Close() + return buf.Bytes() + }(), + }, + { + name: "no content-encoding", // must sniff. + wantContentType: "application/x-gzip", + body: func() []byte { + buf := new(bytes.Buffer) + gzw := gzip.NewWriter(buf) + gzw.Write([]byte("doctype html><p>Hello</p>")) + gzw.Close() + return buf.Bytes() + }(), + }, + { + name: "phony content-encoding", // don't sniff. + contentEncoding: "foo/bar", + body: []byte("doctype html><p>Hello</p>"), + }, + { + name: "empty but set content-encoding", + contentEncoding: "", + wantContentType: "audio/mpeg", + body: []byte("ID3"), + }, + } + + for _, tt := range settings { + t.Run(tt.name, func(t *testing.T) { + cst := newClientServerTest(t, h2, HandlerFunc(func(rw ResponseWriter, r *Request) { + if tt.contentEncoding != nil { + rw.Header().Set("Content-Encoding", tt.contentEncoding.(string)) + } + rw.Write(tt.body) + })) + defer cst.close() + + res, err := cst.c.Get(cst.ts.URL) + if err != nil { + t.Fatalf("Failed to fetch URL: %v", err) + } + defer res.Body.Close() + + if g, w := res.Header.Get("Content-Encoding"), tt.contentEncoding; g != w { + if w != nil { // The case where contentEncoding was set explicitly. + t.Errorf("Content-Encoding mismatch\n\tgot: %q\n\twant: %q", g, w) + } else if g != "" { // "" should be the equivalent when the contentEncoding is unset. + t.Errorf("Unexpected Content-Encoding %q", g) + } + } + + if g, w := res.Header.Get("Content-Type"), tt.wantContentType; g != w { + t.Errorf("Content-Type mismatch\n\tgot: %q\n\twant: %q", g, w) + } + }) + } +} + // fetchWireResponse is a helper for dialing to host, // sending http1ReqBody as the payload and retrieving // the response as it was sent on the wire. |