1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
20 var sniffTests
= []struct {
26 {"Empty", []byte{}, "text/plain; charset=utf-8"},
27 {"Binary", []byte{1, 2, 3}, "application/octet-stream"},
29 {"HTML document #1", []byte(`<HtMl><bOdY>blah blah blah</body></html>`), "text/html; charset=utf-8"},
30 {"HTML document #2", []byte(`<HTML></HTML>`), "text/html; charset=utf-8"},
31 {"HTML document #3 (leading whitespace)", []byte(` <!DOCTYPE HTML>...`), "text/html; charset=utf-8"},
32 {"HTML document #4 (leading CRLF)", []byte("\r\n<html>..."), "text/html; charset=utf-8"},
34 {"Plain text", []byte(`This is not HTML. It has ☃ though.`), "text/plain; charset=utf-8"},
36 {"XML", []byte("\n<?xml!"), "text/xml; charset=utf-8"},
39 {"GIF 87a", []byte(`GIF87a`), "image/gif"},
40 {"GIF 89a", []byte(`GIF89a...`), "image/gif"},
43 {"MIDI audio", []byte("MThd\x00\x00\x00\x06\x00\x01"), "audio/midi"},
44 {"MP3 audio/MPEG audio", []byte("ID3\x03\x00\x00\x00\x00\x0f"), "audio/mpeg"},
45 {"WAV audio #1", []byte("RIFFb\xb8\x00\x00WAVEfmt \x12\x00\x00\x00\x06"), "audio/wave"},
46 {"WAV audio #2", []byte("RIFF,\x00\x00\x00WAVEfmt \x12\x00\x00\x00\x06"), "audio/wave"},
47 {"AIFF audio #1", []byte("FORM\x00\x00\x00\x00AIFFCOMM\x00\x00\x00\x12\x00\x01\x00\x00\x57\x55\x00\x10\x40\x0d\xf3\x34"), "audio/aiff"},
48 {"OGG audio", []byte("OggS\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x7e\x46\x00\x00\x00\x00\x00\x00\x1f\xf6\xb4\xfc\x01\x1e\x01\x76\x6f\x72"), "application/ogg"},
51 {"MP4 video", []byte("\x00\x00\x00\x18ftypmp42\x00\x00\x00\x00mp42isom<\x06t\xbfmdat"), "video/mp4"},
52 {"AVI video #1", []byte("RIFF,O\n\x00AVI LISTÀ"), "video/avi"},
53 {"AVI video #2", []byte("RIFF,\n\x00\x00AVI LISTÀ"), "video/avi"},
56 func TestDetectContentType(t
*testing
.T
) {
57 for _
, tt
:= range sniffTests
{
58 ct
:= DetectContentType(tt
.data
)
59 if ct
!= tt
.contentType
{
60 t
.Errorf("%v: DetectContentType = %q, want %q", tt
.desc
, ct
, tt
.contentType
)
65 func TestServerContentType_h1(t
*testing
.T
) { testServerContentType(t
, h1Mode
) }
66 func TestServerContentType_h2(t
*testing
.T
) { testServerContentType(t
, h2Mode
) }
68 func testServerContentType(t
*testing
.T
, h2
bool) {
71 cst
:= newClientServerTest(t
, h2
, HandlerFunc(func(w ResponseWriter
, r
*Request
) {
72 i
, _
:= strconv
.Atoi(r
.FormValue("i"))
74 n
, err
:= w
.Write(tt
.data
)
75 if n
!= len(tt
.data
) || err
!= nil {
76 log
.Fatalf("%v: Write(%q) = %v, %v want %d, nil", tt
.desc
, tt
.data
, n
, err
, len(tt
.data
))
81 for i
, tt
:= range sniffTests
{
82 resp
, err
:= cst
.c
.Get(cst
.ts
.URL
+ "/?i=" + strconv
.Itoa(i
))
84 t
.Errorf("%v: %v", tt
.desc
, err
)
87 if ct
:= resp
.Header
.Get("Content-Type"); ct
!= tt
.contentType
{
88 t
.Errorf("%v: Content-Type = %q, want %q", tt
.desc
, ct
, tt
.contentType
)
90 data
, err
:= ioutil
.ReadAll(resp
.Body
)
92 t
.Errorf("%v: reading body: %v", tt
.desc
, err
)
93 } else if !bytes
.Equal(data
, tt
.data
) {
94 t
.Errorf("%v: data is %q, want %q", tt
.desc
, data
, tt
.data
)
100 // Issue 5953: shouldn't sniff if the handler set a Content-Type header,
101 // even if it's the empty string.
102 func TestServerIssue5953_h1(t
*testing
.T
) { testServerIssue5953(t
, h1Mode
) }
103 func TestServerIssue5953_h2(t
*testing
.T
) { testServerIssue5953(t
, h2Mode
) }
104 func testServerIssue5953(t
*testing
.T
, h2
bool) {
106 cst
:= newClientServerTest(t
, h2
, HandlerFunc(func(w ResponseWriter
, r
*Request
) {
107 w
.Header()["Content-Type"] = []string{""}
108 fmt
.Fprintf(w
, "<html><head></head><body>hi</body></html>")
112 resp
, err
:= cst
.c
.Get(cst
.ts
.URL
)
117 got
:= resp
.Header
["Content-Type"]
119 if !reflect
.DeepEqual(got
, want
) {
120 t
.Errorf("Content-Type = %q; want %q", got
, want
)
125 func TestContentTypeWithCopy_h1(t
*testing
.T
) { testContentTypeWithCopy(t
, h1Mode
) }
126 func TestContentTypeWithCopy_h2(t
*testing
.T
) { testContentTypeWithCopy(t
, h2Mode
) }
127 func testContentTypeWithCopy(t
*testing
.T
, h2
bool) {
131 input
= "\n<html>\n\t<head>\n"
132 expected
= "text/html; charset=utf-8"
135 cst
:= newClientServerTest(t
, h2
, HandlerFunc(func(w ResponseWriter
, r
*Request
) {
136 // Use io.Copy from a bytes.Buffer to trigger ReadFrom.
137 buf
:= bytes
.NewBuffer([]byte(input
))
138 n
, err
:= io
.Copy(w
, buf
)
139 if int(n
) != len(input
) || err
!= nil {
140 t
.Errorf("io.Copy(w, %q) = %v, %v want %d, nil", input
, n
, err
, len(input
))
145 resp
, err
:= cst
.c
.Get(cst
.ts
.URL
)
147 t
.Fatalf("Get: %v", err
)
149 if ct
:= resp
.Header
.Get("Content-Type"); ct
!= expected
{
150 t
.Errorf("Content-Type = %q, want %q", ct
, expected
)
152 data
, err
:= ioutil
.ReadAll(resp
.Body
)
154 t
.Errorf("reading body: %v", err
)
155 } else if !bytes
.Equal(data
, []byte(input
)) {
156 t
.Errorf("data is %q, want %q", data
, input
)
161 func TestSniffWriteSize_h1(t
*testing
.T
) { testSniffWriteSize(t
, h1Mode
) }
162 func TestSniffWriteSize_h2(t
*testing
.T
) { testSniffWriteSize(t
, h2Mode
) }
163 func testSniffWriteSize(t
*testing
.T
, h2
bool) {
166 cst
:= newClientServerTest(t
, h2
, HandlerFunc(func(w ResponseWriter
, r
*Request
) {
167 size
, _
:= strconv
.Atoi(r
.FormValue("size"))
168 written
, err
:= io
.WriteString(w
, strings
.Repeat("a", size
))
170 t
.Errorf("write of %d bytes: %v", size
, err
)
174 t
.Errorf("write of %d bytes wrote %d bytes", size
, written
)
178 for _
, size
:= range []int{0, 1, 200, 600, 999, 1000, 1023, 1024, 512 << 10, 1 << 20} {
179 res
, err
:= cst
.c
.Get(fmt
.Sprintf("%s/?size=%d", cst
.ts
.URL
, size
))
181 t
.Fatalf("size %d: %v", size
, err
)
183 if _
, err
:= io
.Copy(ioutil
.Discard
, res
.Body
); err
!= nil {
184 t
.Fatalf("size %d: io.Copy of body = %v", size
, err
)
186 if err
:= res
.Body
.Close(); err
!= nil {
187 t
.Fatalf("size %d: body Close = %v", size
, err
)