661
789
t.Fatalf("Dial: %v", err)
663
791
defer conn.Close()
664
sendf := func(format string, args ...interface{}) {
665
_, err := fmt.Fprintf(conn, format, args...)
667
t.Fatalf("On test %#v, error writing %q: %v", test, format, err)
793
// Only send the body immediately if we're acting like an HTTP client
794
// that doesn't send 100-continue expectations.
795
writeBody := test.contentLength > 0 && strings.ToLower(test.expectation) != "100-continue"
671
sendf("POST /?readbody=%v HTTP/1.1\r\n"+
798
_, err := fmt.Fprintf(conn, "POST /?readbody=%v HTTP/1.1\r\n"+
672
799
"Connection: close\r\n"+
673
800
"Content-Length: %d\r\n"+
674
801
"Expect: %s\r\nHost: foo\r\n\r\n",
675
802
test.readBody, test.contentLength, test.expectation)
676
if test.contentLength > 0 && strings.ToLower(test.expectation) != "100-continue" {
804
t.Errorf("On test %#v, error writing request headers: %v", test, err)
677
808
body := strings.Repeat("A", test.contentLength)
809
_, err = fmt.Fprint(conn, body)
812
// Server likely already hung up on us.
813
// See larger comment below.
814
t.Logf("On test %#v, acceptable error writing request body: %v", test, err)
817
t.Errorf("On test %#v, error writing request body: %v", test, err)
681
821
bufr := bufio.NewReader(conn)
682
822
line, err := bufr.ReadString('\n')
684
t.Fatalf("ReadString: %v", err)
824
if writeBody && !test.readBody {
825
// This is an acceptable failure due to a possible TCP race:
826
// We were still writing data and the server hung up on us. A TCP
827
// implementation may send a RST if our request body data was known
828
// to be lost, which may trigger our reads to fail.
829
// See RFC 1122 page 88.
830
t.Logf("On test %#v, acceptable error from ReadString: %v", test, err)
833
t.Fatalf("On test %#v, ReadString: %v", test, err)
686
835
if !strings.Contains(line, test.expectedResponse) {
687
t.Errorf("for test %#v got first line=%q", test, line)
836
t.Errorf("On test %#v, got first line = %q; want %q", test, line, test.expectedResponse)
1086
1256
// Tests that chunked server responses that write 1 byte at a time are
1087
1257
// buffered before chunk headers are added, not after chunk headers.
1088
1258
func TestServerBufferedChunking(t *testing.T) {
1090
t.Logf("Skipping known broken test; see Issue 2357")
1093
1259
conn := new(testConn)
1094
1260
conn.readBuf.Write([]byte("GET / HTTP/1.1\r\n\r\n"))
1095
done := make(chan bool)
1261
conn.closec = make(chan bool, 1)
1096
1262
ls := &oneConnListener{conn}
1097
1263
go Serve(ls, HandlerFunc(func(rw ResponseWriter, req *Request) {
1099
rw.Header().Set("Content-Type", "text/plain") // prevent sniffing, which buffers
1264
rw.(Flusher).Flush() // force the Header to be sent, in chunking mode, not counting the length
1100
1265
rw.Write([]byte{'x'})
1101
1266
rw.Write([]byte{'y'})
1102
1267
rw.Write([]byte{'z'})
1105
1270
if !bytes.HasSuffix(conn.writeBuf.Bytes(), []byte("\r\n\r\n3\r\nxyz\r\n0\r\n\r\n")) {
1106
1271
t.Errorf("response didn't end with a single 3 byte 'xyz' chunk; got:\n%q",
1107
1272
conn.writeBuf.Bytes())
1276
// Tests that the server flushes its response headers out when it's
1277
// ignoring the response body and waits a bit before forcefully
1278
// closing the TCP connection, causing the client to get a RST.
1279
// See http://golang.org/issue/3595
1280
func TestServerGracefulClose(t *testing.T) {
1282
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
1283
Error(w, "bye", StatusUnauthorized)
1287
conn, err := net.Dial("tcp", ts.Listener.Addr().String())
1292
const bodySize = 5 << 20
1293
req := []byte(fmt.Sprintf("POST / HTTP/1.1\r\nHost: foo.com\r\nContent-Length: %d\r\n\r\n", bodySize))
1294
for i := 0; i < bodySize; i++ {
1295
req = append(req, 'x')
1297
writeErr := make(chan error)
1299
_, err := conn.Write(req)
1302
br := bufio.NewReader(conn)
1305
line, err := br.ReadString('\n')
1310
t.Fatalf("ReadLine: %v", err)
1313
if lineNum == 1 && !strings.Contains(line, "401 Unauthorized") {
1314
t.Errorf("Response line = %q; want a 401", line)
1317
// Wait for write to finish. This is a broken pipe on both
1318
// Darwin and Linux, but checking this isn't the point of
1323
func TestCaseSensitiveMethod(t *testing.T) {
1325
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
1326
if r.Method != "get" {
1327
t.Errorf(`Got method %q; want "get"`, r.Method)
1331
req, _ := NewRequest("get", ts.URL, nil)
1332
res, err := DefaultClient.Do(req)
1340
// TestContentLengthZero tests that for both an HTTP/1.0 and HTTP/1.1
1341
// request (both keep-alive), when a Handler never writes any
1342
// response, the net/http package adds a "Content-Length: 0" response
1344
func TestContentLengthZero(t *testing.T) {
1345
ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {}))
1348
for _, version := range []string{"HTTP/1.0", "HTTP/1.1"} {
1349
conn, err := net.Dial("tcp", ts.Listener.Addr().String())
1351
t.Fatalf("error dialing: %v", err)
1353
_, err = fmt.Fprintf(conn, "GET / %v\r\nConnection: keep-alive\r\nHost: foo\r\n\r\n", version)
1355
t.Fatalf("error writing: %v", err)
1357
req, _ := NewRequest("GET", "/", nil)
1358
res, err := ReadResponse(bufio.NewReader(conn), req)
1360
t.Fatalf("error reading response: %v", err)
1362
if te := res.TransferEncoding; len(te) > 0 {
1363
t.Errorf("For version %q, Transfer-Encoding = %q; want none", version, te)
1365
if cl := res.ContentLength; cl != 0 {
1366
t.Errorf("For version %q, Content-Length = %v; want 0", version, cl)
1372
func TestCloseNotifier(t *testing.T) {
1374
gotReq := make(chan bool, 1)
1375
sawClose := make(chan bool, 1)
1376
ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
1378
cc := rw.(CloseNotifier).CloseNotify()
1382
conn, err := net.Dial("tcp", ts.Listener.Addr().String())
1384
t.Fatalf("error dialing: %v", err)
1386
diec := make(chan bool)
1388
_, err = fmt.Fprintf(conn, "GET / HTTP/1.1\r\nConnection: keep-alive\r\nHost: foo\r\n\r\n")
1402
case <-time.After(5 * time.Second):
1409
func TestCloseNotifierChanLeak(t *testing.T) {
1411
req := []byte(strings.Replace(`GET / HTTP/1.0
1414
`, "\n", "\r\n", -1))
1415
for i := 0; i < 20; i++ {
1416
var output bytes.Buffer
1417
conn := &rwTestConn{
1418
Reader: bytes.NewReader(req),
1420
closec: make(chan bool, 1),
1422
ln := &oneConnListener{conn: conn}
1423
handler := HandlerFunc(func(rw ResponseWriter, r *Request) {
1424
// Ignore the return value and never read from
1425
// it, testing that we don't leak goroutines
1426
// on the sending side:
1427
_ = rw.(CloseNotifier).CloseNotify()
1429
go Serve(ln, handler)
1434
func TestOptions(t *testing.T) {
1435
uric := make(chan string, 2) // only expect 1, but leave space for 2
1436
mux := NewServeMux()
1437
mux.HandleFunc("/", func(w ResponseWriter, r *Request) {
1438
uric <- r.RequestURI
1440
ts := httptest.NewServer(mux)
1443
conn, err := net.Dial("tcp", ts.Listener.Addr().String())
1449
// An OPTIONS * request should succeed.
1450
_, err = conn.Write([]byte("OPTIONS * HTTP/1.1\r\nHost: foo.com\r\n\r\n"))
1454
br := bufio.NewReader(conn)
1455
res, err := ReadResponse(br, &Request{Method: "OPTIONS"})
1459
if res.StatusCode != 200 {
1460
t.Errorf("Got non-200 response to OPTIONS *: %#v", res)
1463
// A GET * request on a ServeMux should fail.
1464
_, err = conn.Write([]byte("GET * HTTP/1.1\r\nHost: foo.com\r\n\r\n"))
1468
res, err = ReadResponse(br, &Request{Method: "GET"})
1472
if res.StatusCode != 400 {
1473
t.Errorf("Got non-400 response to GET *: %#v", res)
1476
res, err = Get(ts.URL + "/second")
1481
if got := <-uric; got != "/second" {
1482
t.Errorf("Handler saw request for %q; want /second", got)
1486
// Tests regarding the ordering of Write, WriteHeader, Header, and
1487
// Flush calls. In Go 1.0, rw.WriteHeader immediately flushed the
1488
// (*response).header to the wire. In Go 1.1, the actual wire flush is
1489
// delayed, so we could maybe tack on a Content-Length and better
1490
// Content-Type after we see more (or all) of the output. To preserve
1491
// compatibility with Go 1, we need to be careful to track which
1492
// headers were live at the time of WriteHeader, so we write the same
1493
// ones, even if the handler modifies them (~erroneously) after the
1495
func TestHeaderToWire(t *testing.T) {
1496
req := []byte(strings.Replace(`GET / HTTP/1.1
1499
`, "\n", "\r\n", -1))
1503
handler func(ResponseWriter, *Request)
1504
check func(output string) error
1507
name: "write without Header",
1508
handler: func(rw ResponseWriter, r *Request) {
1509
rw.Write([]byte("hello world"))
1511
check: func(got string) error {
1512
if !strings.Contains(got, "Content-Length:") {
1513
return errors.New("no content-length")
1515
if !strings.Contains(got, "Content-Type: text/plain") {
1516
return errors.New("no content-length")
1522
name: "Header mutation before write",
1523
handler: func(rw ResponseWriter, r *Request) {
1525
h.Set("Content-Type", "some/type")
1526
rw.Write([]byte("hello world"))
1527
h.Set("Too-Late", "bogus")
1529
check: func(got string) error {
1530
if !strings.Contains(got, "Content-Length:") {
1531
return errors.New("no content-length")
1533
if !strings.Contains(got, "Content-Type: some/type") {
1534
return errors.New("wrong content-type")
1536
if strings.Contains(got, "Too-Late") {
1537
return errors.New("don't want too-late header")
1543
name: "write then useless Header mutation",
1544
handler: func(rw ResponseWriter, r *Request) {
1545
rw.Write([]byte("hello world"))
1546
rw.Header().Set("Too-Late", "Write already wrote headers")
1548
check: func(got string) error {
1549
if strings.Contains(got, "Too-Late") {
1550
return errors.New("header appeared from after WriteHeader")
1556
name: "flush then write",
1557
handler: func(rw ResponseWriter, r *Request) {
1558
rw.(Flusher).Flush()
1559
rw.Write([]byte("post-flush"))
1560
rw.Header().Set("Too-Late", "Write already wrote headers")
1562
check: func(got string) error {
1563
if !strings.Contains(got, "Transfer-Encoding: chunked") {
1564
return errors.New("not chunked")
1566
if strings.Contains(got, "Too-Late") {
1567
return errors.New("header appeared from after WriteHeader")
1573
name: "header then flush",
1574
handler: func(rw ResponseWriter, r *Request) {
1575
rw.Header().Set("Content-Type", "some/type")
1576
rw.(Flusher).Flush()
1577
rw.Write([]byte("post-flush"))
1578
rw.Header().Set("Too-Late", "Write already wrote headers")
1580
check: func(got string) error {
1581
if !strings.Contains(got, "Transfer-Encoding: chunked") {
1582
return errors.New("not chunked")
1584
if strings.Contains(got, "Too-Late") {
1585
return errors.New("header appeared from after WriteHeader")
1587
if !strings.Contains(got, "Content-Type: some/type") {
1588
return errors.New("wrong content-length")
1594
name: "sniff-on-first-write content-type",
1595
handler: func(rw ResponseWriter, r *Request) {
1596
rw.Write([]byte("<html><head></head><body>some html</body></html>"))
1597
rw.Header().Set("Content-Type", "x/wrong")
1599
check: func(got string) error {
1600
if !strings.Contains(got, "Content-Type: text/html") {
1601
return errors.New("wrong content-length; want html")
1607
name: "explicit content-type wins",
1608
handler: func(rw ResponseWriter, r *Request) {
1609
rw.Header().Set("Content-Type", "some/type")
1610
rw.Write([]byte("<html><head></head><body>some html</body></html>"))
1612
check: func(got string) error {
1613
if !strings.Contains(got, "Content-Type: some/type") {
1614
return errors.New("wrong content-length; want html")
1620
name: "empty handler",
1621
handler: func(rw ResponseWriter, r *Request) {
1623
check: func(got string) error {
1624
if !strings.Contains(got, "Content-Type: text/plain") {
1625
return errors.New("wrong content-length; want text/plain")
1627
if !strings.Contains(got, "Content-Length: 0") {
1628
return errors.New("want 0 content-length")
1634
name: "only Header, no write",
1635
handler: func(rw ResponseWriter, r *Request) {
1636
rw.Header().Set("Some-Header", "some-value")
1638
check: func(got string) error {
1639
if !strings.Contains(got, "Some-Header") {
1640
return errors.New("didn't get header")
1646
name: "WriteHeader call",
1647
handler: func(rw ResponseWriter, r *Request) {
1649
rw.Header().Set("Too-Late", "some-value")
1651
check: func(got string) error {
1652
if !strings.Contains(got, "404") {
1653
return errors.New("wrong status")
1655
if strings.Contains(got, "Some-Header") {
1656
return errors.New("shouldn't have seen Too-Late")
1662
for _, tc := range tests {
1663
var output bytes.Buffer
1664
conn := &rwTestConn{
1665
Reader: bytes.NewReader(req),
1667
closec: make(chan bool, 1),
1669
ln := &oneConnListener{conn: conn}
1670
go Serve(ln, HandlerFunc(tc.handler))
1672
if err := tc.check(output.String()); err != nil {
1673
t.Errorf("%s: %v\nGot response:\n%s", tc.name, err, output.Bytes())
1111
1678
// goTimeout runs f, failing t if f takes more than ns to complete.
1112
1679
func goTimeout(t *testing.T, d time.Duration, f func()) {
1113
1680
ch := make(chan bool, 2)
1755
func BenchmarkClientServerParallel4(b *testing.B) {
1756
benchmarkClientServerParallel(b, 4)
1759
func BenchmarkClientServerParallel64(b *testing.B) {
1760
benchmarkClientServerParallel(b, 64)
1763
func benchmarkClientServerParallel(b *testing.B, conc int) {
1765
ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, r *Request) {
1766
fmt.Fprintf(rw, "Hello world.\n")
1771
numProcs := runtime.GOMAXPROCS(-1) * conc
1772
var wg sync.WaitGroup
1775
for p := 0; p < numProcs; p++ {
1777
for atomic.AddInt32(&n, -1) >= 0 {
1778
res, err := Get(ts.URL)
1780
b.Logf("Get: %v", err)
1783
all, err := ioutil.ReadAll(res.Body)
1785
b.Logf("ReadAll: %v", err)
1789
if body != "Hello world.\n" {
1790
panic("Got body: " + body)
1799
// A benchmark for profiling the server without the HTTP client code.
1800
// The client code runs in a subprocess.
1804
// $ ./http.test -test.run=XX -test.bench=BenchmarkServer -test.benchtime=15s -test.cpuprofile=http.prof
1805
// $ go tool pprof http.test http.prof
1807
func BenchmarkServer(b *testing.B) {
1808
// Child process mode;
1809
if url := os.Getenv("TEST_BENCH_SERVER_URL"); url != "" {
1810
n, err := strconv.Atoi(os.Getenv("TEST_BENCH_CLIENT_N"))
1814
for i := 0; i < n; i++ {
1815
res, err := Get(url)
1817
log.Panicf("Get: %v", err)
1819
all, err := ioutil.ReadAll(res.Body)
1821
log.Panicf("ReadAll: %v", err)
1824
if body != "Hello world.\n" {
1825
log.Panicf("Got body: %q", body)
1832
var res = []byte("Hello world.\n")
1834
ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, r *Request) {
1835
rw.Header().Set("Content-Type", "text/html; charset=utf-8")
1841
cmd := exec.Command(os.Args[0], "-test.run=XXXX", "-test.bench=BenchmarkServer")
1842
cmd.Env = append([]string{
1843
fmt.Sprintf("TEST_BENCH_CLIENT_N=%d", b.N),
1844
fmt.Sprintf("TEST_BENCH_SERVER_URL=%s", ts.URL),
1846
out, err := cmd.CombinedOutput()
1848
b.Errorf("Test failure: %v, with output: %s", err, out)
1852
func BenchmarkServerFakeConnNoKeepAlive(b *testing.B) {
1854
req := []byte(strings.Replace(`GET / HTTP/1.0
1856
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
1857
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.52 Safari/537.17
1858
Accept-Encoding: gzip,deflate,sdch
1859
Accept-Language: en-US,en;q=0.8
1860
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
1862
`, "\n", "\r\n", -1))
1863
res := []byte("Hello world!\n")
1866
// testConn.Close will not push into the channel
1868
closec: make(chan bool, 1),
1870
handler := HandlerFunc(func(rw ResponseWriter, r *Request) {
1871
rw.Header().Set("Content-Type", "text/html; charset=utf-8")
1874
ln := new(oneConnListener)
1875
for i := 0; i < b.N; i++ {
1876
conn.readBuf.Reset()
1877
conn.writeBuf.Reset()
1878
conn.readBuf.Write(req)
1885
// repeatReader reads content count times, then EOFs.
1886
type repeatReader struct {
1892
func (r *repeatReader) Read(p []byte) (n int, err error) {
1896
n = copy(p, r.content[r.off:])
1898
if r.off == len(r.content) {
1905
func BenchmarkServerFakeConnWithKeepAlive(b *testing.B) {
1908
req := []byte(strings.Replace(`GET / HTTP/1.1
1910
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
1911
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.52 Safari/537.17
1912
Accept-Encoding: gzip,deflate,sdch
1913
Accept-Language: en-US,en;q=0.8
1914
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
1916
`, "\n", "\r\n", -1))
1917
res := []byte("Hello world!\n")
1919
conn := &rwTestConn{
1920
Reader: &repeatReader{content: req, count: b.N},
1921
Writer: ioutil.Discard,
1922
closec: make(chan bool, 1),
1925
handler := HandlerFunc(func(rw ResponseWriter, r *Request) {
1927
rw.Header().Set("Content-Type", "text/html; charset=utf-8")
1930
ln := &oneConnListener{conn: conn}
1931
go Serve(ln, handler)
1934
b.Errorf("b.N=%d but handled %d", b.N, handled)
1938
// same as above, but representing the most simple possible request
1939
// and handler. Notably: the handler does not call rw.Header().
1940
func BenchmarkServerFakeConnWithKeepAliveLite(b *testing.B) {
1943
req := []byte(strings.Replace(`GET / HTTP/1.1
1946
`, "\n", "\r\n", -1))
1947
res := []byte("Hello world!\n")
1949
conn := &rwTestConn{
1950
Reader: &repeatReader{content: req, count: b.N},
1951
Writer: ioutil.Discard,
1952
closec: make(chan bool, 1),
1955
handler := HandlerFunc(func(rw ResponseWriter, r *Request) {
1959
ln := &oneConnListener{conn: conn}
1960
go Serve(ln, handler)
1963
b.Errorf("b.N=%d but handled %d", b.N, handled)
1967
const someResponse = "<html>some response</html>"
1969
// A Response that's just no bigger than 2KB, the buffer-before-chunking threshold.
1970
var response = bytes.Repeat([]byte(someResponse), 2<<10/len(someResponse))
1972
// Both Content-Type and Content-Length set. Should be no buffering.
1973
func BenchmarkServerHandlerTypeLen(b *testing.B) {
1974
benchmarkHandler(b, HandlerFunc(func(w ResponseWriter, r *Request) {
1975
w.Header().Set("Content-Type", "text/html")
1976
w.Header().Set("Content-Length", strconv.Itoa(len(response)))
1981
// A Content-Type is set, but no length. No sniffing, but will count the Content-Length.
1982
func BenchmarkServerHandlerNoLen(b *testing.B) {
1983
benchmarkHandler(b, HandlerFunc(func(w ResponseWriter, r *Request) {
1984
w.Header().Set("Content-Type", "text/html")
1989
// A Content-Length is set, but the Content-Type will be sniffed.
1990
func BenchmarkServerHandlerNoType(b *testing.B) {
1991
benchmarkHandler(b, HandlerFunc(func(w ResponseWriter, r *Request) {
1992
w.Header().Set("Content-Length", strconv.Itoa(len(response)))
1997
// Neither a Content-Type or Content-Length, so sniffed and counted.
1998
func BenchmarkServerHandlerNoHeader(b *testing.B) {
1999
benchmarkHandler(b, HandlerFunc(func(w ResponseWriter, r *Request) {
2004
func benchmarkHandler(b *testing.B, h Handler) {
2006
req := []byte(strings.Replace(`GET / HTTP/1.1
2009
`, "\n", "\r\n", -1))
2010
conn := &rwTestConn{
2011
Reader: &repeatReader{content: req, count: b.N},
2012
Writer: ioutil.Discard,
2013
closec: make(chan bool, 1),
2016
handler := HandlerFunc(func(rw ResponseWriter, r *Request) {
2020
ln := &oneConnListener{conn: conn}
2021
go Serve(ln, handler)
2024
b.Errorf("b.N=%d but handled %d", b.N, handled)