mirror of
https://github.com/golang/net.git
synced 2026-03-31 18:37:08 +09:00
http2: do not sniff body if Content-Encoding is set
Updates golang/go#31753 Change-Id: I2481ffcff6626c08ef32a02cffb3f108737fa87e Reviewed-on: https://go-review.googlesource.com/c/net/+/199841 Run-TryBot: Emmanuel Odeke <emm.odeke@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
committed by
Emmanuel Odeke
parent
72f9393749
commit
d66e71096f
@@ -2415,7 +2415,11 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
|
||||
clen = strconv.Itoa(len(p))
|
||||
}
|
||||
_, hasContentType := rws.snapHeader["Content-Type"]
|
||||
if !hasContentType && bodyAllowedForStatus(rws.status) && len(p) > 0 {
|
||||
// If the Content-Encoding is non-blank, we shouldn't
|
||||
// sniff the body. See Issue golang.org/issue/31753.
|
||||
ce := rws.snapHeader.Get("Content-Encoding")
|
||||
hasCE := len(ce) > 0
|
||||
if !hasCE && !hasContentType && bodyAllowedForStatus(rws.status) && len(p) > 0 {
|
||||
ctype = http.DetectContentType(p)
|
||||
}
|
||||
var date string
|
||||
|
||||
@@ -6,6 +6,8 @@ package http2
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"compress/zlib"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
@@ -3966,3 +3968,97 @@ func TestServerGracefulShutdown(t *testing.T) {
|
||||
t.Errorf("Read = %v, %v; want 0, non-nil", n, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Issue 31753: don't sniff when Content-Encoding is set
|
||||
func TestContentEncodingNoSniffing(t *testing.T) {
|
||||
type resp struct {
|
||||
name string
|
||||
body []byte
|
||||
// setting Content-Encoding 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
|
||||
}
|
||||
|
||||
resps := []*resp{
|
||||
{
|
||||
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"),
|
||||
},
|
||||
}
|
||||
|
||||
tr := &Transport{TLSClientConfig: tlsConfigInsecure}
|
||||
defer tr.CloseIdleConnections()
|
||||
|
||||
for _, tt := range resps {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
|
||||
if tt.contentEncoding != nil {
|
||||
w.Header().Set("Content-Encoding", tt.contentEncoding.(string))
|
||||
}
|
||||
w.Write(tt.body)
|
||||
}, optOnlyServer)
|
||||
defer st.Close()
|
||||
|
||||
req, _ := http.NewRequest("GET", st.ts.URL, nil)
|
||||
res, err := tr.RoundTrip(req)
|
||||
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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user