@@ -6,6 +6,8 @@ package http2
6
6
7
7
import (
8
8
"bytes"
9
+ "compress/gzip"
10
+ "compress/zlib"
9
11
"context"
10
12
"crypto/tls"
11
13
"errors"
@@ -3966,3 +3968,97 @@ func TestServerGracefulShutdown(t *testing.T) {
3966
3968
t .Errorf ("Read = %v, %v; want 0, non-nil" , n , err )
3967
3969
}
3968
3970
}
3971
+
3972
+ // Issue 31753: don't sniff when Content-Encoding is set
3973
+ func TestContentEncodingNoSniffing (t * testing.T ) {
3974
+ type resp struct {
3975
+ name string
3976
+ body []byte
3977
+ // setting Content-Encoding as an interface instead of a string
3978
+ // directly, so as to differentiate between 3 states:
3979
+ // unset, empty string "" and set string "foo/bar".
3980
+ contentEncoding interface {}
3981
+ wantContentType string
3982
+ }
3983
+
3984
+ resps := []* resp {
3985
+ {
3986
+ name : "gzip content-encoding, gzipped" , // don't sniff.
3987
+ contentEncoding : "application/gzip" ,
3988
+ wantContentType : "" ,
3989
+ body : func () []byte {
3990
+ buf := new (bytes.Buffer )
3991
+ gzw := gzip .NewWriter (buf )
3992
+ gzw .Write ([]byte ("doctype html><p>Hello</p>" ))
3993
+ gzw .Close ()
3994
+ return buf .Bytes ()
3995
+ }(),
3996
+ },
3997
+ {
3998
+ name : "zlib content-encoding, zlibbed" , // don't sniff.
3999
+ contentEncoding : "application/zlib" ,
4000
+ wantContentType : "" ,
4001
+ body : func () []byte {
4002
+ buf := new (bytes.Buffer )
4003
+ zw := zlib .NewWriter (buf )
4004
+ zw .Write ([]byte ("doctype html><p>Hello</p>" ))
4005
+ zw .Close ()
4006
+ return buf .Bytes ()
4007
+ }(),
4008
+ },
4009
+ {
4010
+ name : "no content-encoding" , // must sniff.
4011
+ wantContentType : "application/x-gzip" ,
4012
+ body : func () []byte {
4013
+ buf := new (bytes.Buffer )
4014
+ gzw := gzip .NewWriter (buf )
4015
+ gzw .Write ([]byte ("doctype html><p>Hello</p>" ))
4016
+ gzw .Close ()
4017
+ return buf .Bytes ()
4018
+ }(),
4019
+ },
4020
+ {
4021
+ name : "phony content-encoding" , // don't sniff.
4022
+ contentEncoding : "foo/bar" ,
4023
+ body : []byte ("doctype html><p>Hello</p>" ),
4024
+ },
4025
+ {
4026
+ name : "empty but set content-encoding" ,
4027
+ contentEncoding : "" ,
4028
+ wantContentType : "audio/mpeg" ,
4029
+ body : []byte ("ID3" ),
4030
+ },
4031
+ }
4032
+
4033
+ tr := & Transport {TLSClientConfig : tlsConfigInsecure }
4034
+ defer tr .CloseIdleConnections ()
4035
+
4036
+ for _ , tt := range resps {
4037
+ t .Run (tt .name , func (t * testing.T ) {
4038
+ st := newServerTester (t , func (w http.ResponseWriter , r * http.Request ) {
4039
+ if tt .contentEncoding != nil {
4040
+ w .Header ().Set ("Content-Encoding" , tt .contentEncoding .(string ))
4041
+ }
4042
+ w .Write (tt .body )
4043
+ }, optOnlyServer )
4044
+ defer st .Close ()
4045
+
4046
+ req , _ := http .NewRequest ("GET" , st .ts .URL , nil )
4047
+ res , err := tr .RoundTrip (req )
4048
+ if err != nil {
4049
+ t .Fatalf ("Failed to fetch URL: %v" , err )
4050
+ }
4051
+ defer res .Body .Close ()
4052
+ if g , w := res .Header .Get ("Content-Encoding" ), tt .contentEncoding ; g != w {
4053
+ if w != nil { // The case where contentEncoding was set explicitly.
4054
+ t .Errorf ("Content-Encoding mismatch\n \t got: %q\n \t want: %q" , g , w )
4055
+ } else if g != "" { // "" should be the equivalent when the contentEncoding is unset.
4056
+ t .Errorf ("Unexpected Content-Encoding %q" , g )
4057
+ }
4058
+ }
4059
+ if g , w := res .Header .Get ("Content-Type" ), tt .wantContentType ; g != w {
4060
+ t .Errorf ("Content-Type mismatch\n \t got: %q\n \t want: %q" , g , w )
4061
+ }
4062
+ })
4063
+ }
4064
+ }
0 commit comments