OSDN Git Service

Update Go library to r60.
[pf3gnuchains/gcc-fork.git] / libgo / go / http / serve_test.go
1 // Copyright 2010 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.
4
5 // End-to-end serving tests
6
7 package http_test
8
9 import (
10         "bufio"
11         "bytes"
12         "fmt"
13         . "http"
14         "http/httptest"
15         "io"
16         "io/ioutil"
17         "log"
18         "os"
19         "net"
20         "reflect"
21         "strings"
22         "syscall"
23         "testing"
24         "time"
25         "url"
26 )
27
28 type dummyAddr string
29 type oneConnListener struct {
30         conn net.Conn
31 }
32
33 func (l *oneConnListener) Accept() (c net.Conn, err os.Error) {
34         c = l.conn
35         if c == nil {
36                 err = os.EOF
37                 return
38         }
39         err = nil
40         l.conn = nil
41         return
42 }
43
44 func (l *oneConnListener) Close() os.Error {
45         return nil
46 }
47
48 func (l *oneConnListener) Addr() net.Addr {
49         return dummyAddr("test-address")
50 }
51
52 func (a dummyAddr) Network() string {
53         return string(a)
54 }
55
56 func (a dummyAddr) String() string {
57         return string(a)
58 }
59
60 type testConn struct {
61         readBuf  bytes.Buffer
62         writeBuf bytes.Buffer
63 }
64
65 func (c *testConn) Read(b []byte) (int, os.Error) {
66         return c.readBuf.Read(b)
67 }
68
69 func (c *testConn) Write(b []byte) (int, os.Error) {
70         return c.writeBuf.Write(b)
71 }
72
73 func (c *testConn) Close() os.Error {
74         return nil
75 }
76
77 func (c *testConn) LocalAddr() net.Addr {
78         return dummyAddr("local-addr")
79 }
80
81 func (c *testConn) RemoteAddr() net.Addr {
82         return dummyAddr("remote-addr")
83 }
84
85 func (c *testConn) SetTimeout(nsec int64) os.Error {
86         return nil
87 }
88
89 func (c *testConn) SetReadTimeout(nsec int64) os.Error {
90         return nil
91 }
92
93 func (c *testConn) SetWriteTimeout(nsec int64) os.Error {
94         return nil
95 }
96
97 func TestConsumingBodyOnNextConn(t *testing.T) {
98         conn := new(testConn)
99         for i := 0; i < 2; i++ {
100                 conn.readBuf.Write([]byte(
101                         "POST / HTTP/1.1\r\n" +
102                                 "Host: test\r\n" +
103                                 "Content-Length: 11\r\n" +
104                                 "\r\n" +
105                                 "foo=1&bar=1"))
106         }
107
108         reqNum := 0
109         ch := make(chan *Request)
110         servech := make(chan os.Error)
111         listener := &oneConnListener{conn}
112         handler := func(res ResponseWriter, req *Request) {
113                 reqNum++
114                 ch <- req
115         }
116
117         go func() {
118                 servech <- Serve(listener, HandlerFunc(handler))
119         }()
120
121         var req *Request
122         req = <-ch
123         if req == nil {
124                 t.Fatal("Got nil first request.")
125         }
126         if req.Method != "POST" {
127                 t.Errorf("For request #1's method, got %q; expected %q",
128                         req.Method, "POST")
129         }
130
131         req = <-ch
132         if req == nil {
133                 t.Fatal("Got nil first request.")
134         }
135         if req.Method != "POST" {
136                 t.Errorf("For request #2's method, got %q; expected %q",
137                         req.Method, "POST")
138         }
139
140         if serveerr := <-servech; serveerr != os.EOF {
141                 t.Errorf("Serve returned %q; expected EOF", serveerr)
142         }
143 }
144
145 type stringHandler string
146
147 func (s stringHandler) ServeHTTP(w ResponseWriter, r *Request) {
148         w.Header().Set("Result", string(s))
149 }
150
151 var handlers = []struct {
152         pattern string
153         msg     string
154 }{
155         {"/", "Default"},
156         {"/someDir/", "someDir"},
157         {"someHost.com/someDir/", "someHost.com/someDir"},
158 }
159
160 var vtests = []struct {
161         url      string
162         expected string
163 }{
164         {"http://localhost/someDir/apage", "someDir"},
165         {"http://localhost/otherDir/apage", "Default"},
166         {"http://someHost.com/someDir/apage", "someHost.com/someDir"},
167         {"http://otherHost.com/someDir/apage", "someDir"},
168         {"http://otherHost.com/aDir/apage", "Default"},
169 }
170
171 func TestHostHandlers(t *testing.T) {
172         for _, h := range handlers {
173                 Handle(h.pattern, stringHandler(h.msg))
174         }
175         ts := httptest.NewServer(nil)
176         defer ts.Close()
177
178         conn, err := net.Dial("tcp", ts.Listener.Addr().String())
179         if err != nil {
180                 t.Fatal(err)
181         }
182         defer conn.Close()
183         cc := NewClientConn(conn, nil)
184         for _, vt := range vtests {
185                 var r *Response
186                 var req Request
187                 if req.URL, err = url.Parse(vt.url); err != nil {
188                         t.Errorf("cannot parse url: %v", err)
189                         continue
190                 }
191                 if err := cc.Write(&req); err != nil {
192                         t.Errorf("writing request: %v", err)
193                         continue
194                 }
195                 r, err := cc.Read(&req)
196                 if err != nil {
197                         t.Errorf("reading response: %v", err)
198                         continue
199                 }
200                 s := r.Header.Get("Result")
201                 if s != vt.expected {
202                         t.Errorf("Get(%q) = %q, want %q", vt.url, s, vt.expected)
203                 }
204         }
205 }
206
207 // Tests for http://code.google.com/p/go/issues/detail?id=900
208 func TestMuxRedirectLeadingSlashes(t *testing.T) {
209         paths := []string{"//foo.txt", "///foo.txt", "/../../foo.txt"}
210         for _, path := range paths {
211                 req, err := ReadRequest(bufio.NewReader(bytes.NewBufferString("GET " + path + " HTTP/1.1\r\nHost: test\r\n\r\n")))
212                 if err != nil {
213                         t.Errorf("%s", err)
214                 }
215                 mux := NewServeMux()
216                 resp := httptest.NewRecorder()
217
218                 mux.ServeHTTP(resp, req)
219
220                 if loc, expected := resp.Header().Get("Location"), "/foo.txt"; loc != expected {
221                         t.Errorf("Expected Location header set to %q; got %q", expected, loc)
222                         return
223                 }
224
225                 if code, expected := resp.Code, StatusMovedPermanently; code != expected {
226                         t.Errorf("Expected response code of StatusMovedPermanently; got %d", code)
227                         return
228                 }
229         }
230 }
231
232 func TestServerTimeouts(t *testing.T) {
233         // TODO(bradfitz): convert this to use httptest.Server
234         l, err := net.Listen("tcp", "127.0.0.1:0")
235         if err != nil {
236                 t.Fatalf("listen error: %v", err)
237         }
238         addr, _ := l.Addr().(*net.TCPAddr)
239
240         reqNum := 0
241         handler := HandlerFunc(func(res ResponseWriter, req *Request) {
242                 reqNum++
243                 fmt.Fprintf(res, "req=%d", reqNum)
244         })
245
246         const second = 1000000000 /* nanos */
247         server := &Server{Handler: handler, ReadTimeout: 0.25 * second, WriteTimeout: 0.25 * second}
248         go server.Serve(l)
249
250         url := fmt.Sprintf("http://%s/", addr)
251
252         // Hit the HTTP server successfully.
253         tr := &Transport{DisableKeepAlives: true} // they interfere with this test
254         c := &Client{Transport: tr}
255         r, err := c.Get(url)
256         if err != nil {
257                 t.Fatalf("http Get #1: %v", err)
258         }
259         got, _ := ioutil.ReadAll(r.Body)
260         expected := "req=1"
261         if string(got) != expected {
262                 t.Errorf("Unexpected response for request #1; got %q; expected %q",
263                         string(got), expected)
264         }
265
266         // Slow client that should timeout.
267         t1 := time.Nanoseconds()
268         conn, err := net.Dial("tcp", addr.String())
269         if err != nil {
270                 t.Fatalf("Dial: %v", err)
271         }
272         buf := make([]byte, 1)
273         n, err := conn.Read(buf)
274         latency := time.Nanoseconds() - t1
275         if n != 0 || err != os.EOF {
276                 t.Errorf("Read = %v, %v, wanted %v, %v", n, err, 0, os.EOF)
277         }
278         if latency < second*0.20 /* fudge from 0.25 above */ {
279                 t.Errorf("got EOF after %d ns, want >= %d", latency, second*0.20)
280         }
281
282         // Hit the HTTP server successfully again, verifying that the
283         // previous slow connection didn't run our handler.  (that we
284         // get "req=2", not "req=3")
285         r, err = Get(url)
286         if err != nil {
287                 t.Fatalf("http Get #2: %v", err)
288         }
289         got, _ = ioutil.ReadAll(r.Body)
290         expected = "req=2"
291         if string(got) != expected {
292                 t.Errorf("Get #2 got %q, want %q", string(got), expected)
293         }
294
295         l.Close()
296 }
297
298 // TestIdentityResponse verifies that a handler can unset 
299 func TestIdentityResponse(t *testing.T) {
300         handler := HandlerFunc(func(rw ResponseWriter, req *Request) {
301                 rw.Header().Set("Content-Length", "3")
302                 rw.Header().Set("Transfer-Encoding", req.FormValue("te"))
303                 switch {
304                 case req.FormValue("overwrite") == "1":
305                         _, err := rw.Write([]byte("foo TOO LONG"))
306                         if err != ErrContentLength {
307                                 t.Errorf("expected ErrContentLength; got %v", err)
308                         }
309                 case req.FormValue("underwrite") == "1":
310                         rw.Header().Set("Content-Length", "500")
311                         rw.Write([]byte("too short"))
312                 default:
313                         rw.Write([]byte("foo"))
314                 }
315         })
316
317         ts := httptest.NewServer(handler)
318         defer ts.Close()
319
320         // Note: this relies on the assumption (which is true) that
321         // Get sends HTTP/1.1 or greater requests.  Otherwise the
322         // server wouldn't have the choice to send back chunked
323         // responses.
324         for _, te := range []string{"", "identity"} {
325                 url := ts.URL + "/?te=" + te
326                 res, err := Get(url)
327                 if err != nil {
328                         t.Fatalf("error with Get of %s: %v", url, err)
329                 }
330                 if cl, expected := res.ContentLength, int64(3); cl != expected {
331                         t.Errorf("for %s expected res.ContentLength of %d; got %d", url, expected, cl)
332                 }
333                 if cl, expected := res.Header.Get("Content-Length"), "3"; cl != expected {
334                         t.Errorf("for %s expected Content-Length header of %q; got %q", url, expected, cl)
335                 }
336                 if tl, expected := len(res.TransferEncoding), 0; tl != expected {
337                         t.Errorf("for %s expected len(res.TransferEncoding) of %d; got %d (%v)",
338                                 url, expected, tl, res.TransferEncoding)
339                 }
340                 res.Body.Close()
341         }
342
343         // Verify that ErrContentLength is returned
344         url := ts.URL + "/?overwrite=1"
345         _, err := Get(url)
346         if err != nil {
347                 t.Fatalf("error with Get of %s: %v", url, err)
348         }
349         // Verify that the connection is closed when the declared Content-Length
350         // is larger than what the handler wrote.
351         conn, err := net.Dial("tcp", ts.Listener.Addr().String())
352         if err != nil {
353                 t.Fatalf("error dialing: %v", err)
354         }
355         _, err = conn.Write([]byte("GET /?underwrite=1 HTTP/1.1\r\nHost: foo\r\n\r\n"))
356         if err != nil {
357                 t.Fatalf("error writing: %v", err)
358         }
359         // The next ReadAll will hang for a failing test, so use a Timer instead
360         // to fail more traditionally
361         timer := time.AfterFunc(2e9, func() {
362                 t.Fatalf("Timeout expired in ReadAll.")
363         })
364         defer timer.Stop()
365         got, _ := ioutil.ReadAll(conn)
366         expectedSuffix := "\r\n\r\ntoo short"
367         if !strings.HasSuffix(string(got), expectedSuffix) {
368                 t.Fatalf("Expected output to end with %q; got response body %q",
369                         expectedSuffix, string(got))
370         }
371 }
372
373 func testTcpConnectionCloses(t *testing.T, req string, h Handler) {
374         s := httptest.NewServer(h)
375         defer s.Close()
376
377         conn, err := net.Dial("tcp", s.Listener.Addr().String())
378         if err != nil {
379                 t.Fatal("dial error:", err)
380         }
381         defer conn.Close()
382
383         _, err = fmt.Fprint(conn, req)
384         if err != nil {
385                 t.Fatal("print error:", err)
386         }
387
388         r := bufio.NewReader(conn)
389         _, err = ReadResponse(r, &Request{Method: "GET"})
390         if err != nil {
391                 t.Fatal("ReadResponse error:", err)
392         }
393
394         success := make(chan bool)
395         go func() {
396                 select {
397                 case <-time.After(5e9):
398                         t.Fatal("body not closed after 5s")
399                 case <-success:
400                 }
401         }()
402
403         _, err = ioutil.ReadAll(r)
404         if err != nil {
405                 t.Fatal("read error:", err)
406         }
407
408         success <- true
409 }
410
411 // TestServeHTTP10Close verifies that HTTP/1.0 requests won't be kept alive.
412 func TestServeHTTP10Close(t *testing.T) {
413         testTcpConnectionCloses(t, "GET / HTTP/1.0\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
414                 ServeFile(w, r, "testdata/file")
415         }))
416 }
417
418 // TestHandlersCanSetConnectionClose verifies that handlers can force a connection to close,
419 // even for HTTP/1.1 requests.
420 func TestHandlersCanSetConnectionClose11(t *testing.T) {
421         testTcpConnectionCloses(t, "GET / HTTP/1.1\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
422                 w.Header().Set("Connection", "close")
423         }))
424 }
425
426 func TestHandlersCanSetConnectionClose10(t *testing.T) {
427         testTcpConnectionCloses(t, "GET / HTTP/1.0\r\nConnection: keep-alive\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
428                 w.Header().Set("Connection", "close")
429         }))
430 }
431
432 func TestSetsRemoteAddr(t *testing.T) {
433         ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
434                 fmt.Fprintf(w, "%s", r.RemoteAddr)
435         }))
436         defer ts.Close()
437
438         res, err := Get(ts.URL)
439         if err != nil {
440                 t.Fatalf("Get error: %v", err)
441         }
442         body, err := ioutil.ReadAll(res.Body)
443         if err != nil {
444                 t.Fatalf("ReadAll error: %v", err)
445         }
446         ip := string(body)
447         if !strings.HasPrefix(ip, "127.0.0.1:") && !strings.HasPrefix(ip, "[::1]:") {
448                 t.Fatalf("Expected local addr; got %q", ip)
449         }
450 }
451
452 func TestChunkedResponseHeaders(t *testing.T) {
453         log.SetOutput(ioutil.Discard) // is noisy otherwise
454         defer log.SetOutput(os.Stderr)
455
456         ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
457                 w.Header().Set("Content-Length", "intentional gibberish") // we check that this is deleted
458                 fmt.Fprintf(w, "I am a chunked response.")
459         }))
460         defer ts.Close()
461
462         res, err := Get(ts.URL)
463         if err != nil {
464                 t.Fatalf("Get error: %v", err)
465         }
466         if g, e := res.ContentLength, int64(-1); g != e {
467                 t.Errorf("expected ContentLength of %d; got %d", e, g)
468         }
469         if g, e := res.TransferEncoding, []string{"chunked"}; !reflect.DeepEqual(g, e) {
470                 t.Errorf("expected TransferEncoding of %v; got %v", e, g)
471         }
472         if _, haveCL := res.Header["Content-Length"]; haveCL {
473                 t.Errorf("Unexpected Content-Length")
474         }
475 }
476
477 // Test304Responses verifies that 304s don't declare that they're
478 // chunking in their response headers and aren't allowed to produce
479 // output.
480 func Test304Responses(t *testing.T) {
481         ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
482                 w.WriteHeader(StatusNotModified)
483                 _, err := w.Write([]byte("illegal body"))
484                 if err != ErrBodyNotAllowed {
485                         t.Errorf("on Write, expected ErrBodyNotAllowed, got %v", err)
486                 }
487         }))
488         defer ts.Close()
489         res, err := Get(ts.URL)
490         if err != nil {
491                 t.Error(err)
492         }
493         if len(res.TransferEncoding) > 0 {
494                 t.Errorf("expected no TransferEncoding; got %v", res.TransferEncoding)
495         }
496         body, err := ioutil.ReadAll(res.Body)
497         if err != nil {
498                 t.Error(err)
499         }
500         if len(body) > 0 {
501                 t.Errorf("got unexpected body %q", string(body))
502         }
503 }
504
505 // TestHeadResponses verifies that responses to HEAD requests don't
506 // declare that they're chunking in their response headers and aren't
507 // allowed to produce output.
508 func TestHeadResponses(t *testing.T) {
509         ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
510                 _, err := w.Write([]byte("Ignored body"))
511                 if err != ErrBodyNotAllowed {
512                         t.Errorf("on Write, expected ErrBodyNotAllowed, got %v", err)
513                 }
514
515                 // Also exercise the ReaderFrom path
516                 _, err = io.Copy(w, strings.NewReader("Ignored body"))
517                 if err != ErrBodyNotAllowed {
518                         t.Errorf("on Copy, expected ErrBodyNotAllowed, got %v", err)
519                 }
520         }))
521         defer ts.Close()
522         res, err := Head(ts.URL)
523         if err != nil {
524                 t.Error(err)
525         }
526         if len(res.TransferEncoding) > 0 {
527                 t.Errorf("expected no TransferEncoding; got %v", res.TransferEncoding)
528         }
529         body, err := ioutil.ReadAll(res.Body)
530         if err != nil {
531                 t.Error(err)
532         }
533         if len(body) > 0 {
534                 t.Errorf("got unexpected body %q", string(body))
535         }
536 }
537
538 func TestTLSServer(t *testing.T) {
539         ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {
540                 if r.TLS != nil {
541                         w.Header().Set("X-TLS-Set", "true")
542                         if r.TLS.HandshakeComplete {
543                                 w.Header().Set("X-TLS-HandshakeComplete", "true")
544                         }
545                 }
546         }))
547         defer ts.Close()
548         if !strings.HasPrefix(ts.URL, "https://") {
549                 t.Fatalf("expected test TLS server to start with https://, got %q", ts.URL)
550         }
551         res, err := Get(ts.URL)
552         if err != nil {
553                 t.Fatal(err)
554         }
555         if res == nil {
556                 t.Fatalf("got nil Response")
557         }
558         defer res.Body.Close()
559         if res.Header.Get("X-TLS-Set") != "true" {
560                 t.Errorf("expected X-TLS-Set response header")
561         }
562         if res.Header.Get("X-TLS-HandshakeComplete") != "true" {
563                 t.Errorf("expected X-TLS-HandshakeComplete header")
564         }
565 }
566
567 type serverExpectTest struct {
568         contentLength    int    // of request body
569         expectation      string // e.g. "100-continue"
570         readBody         bool   // whether handler should read the body (if false, sends StatusUnauthorized)
571         expectedResponse string // expected substring in first line of http response
572 }
573
574 var serverExpectTests = []serverExpectTest{
575         // Normal 100-continues, case-insensitive.
576         {100, "100-continue", true, "100 Continue"},
577         {100, "100-cOntInUE", true, "100 Continue"},
578
579         // No 100-continue.
580         {100, "", true, "200 OK"},
581
582         // 100-continue but requesting client to deny us,
583         // so it never reads the body.
584         {100, "100-continue", false, "401 Unauthorized"},
585         // Likewise without 100-continue:
586         {100, "", false, "401 Unauthorized"},
587
588         // Non-standard expectations are failures
589         {0, "a-pony", false, "417 Expectation Failed"},
590
591         // Expect-100 requested but no body
592         {0, "100-continue", true, "400 Bad Request"},
593 }
594
595 // Tests that the server responds to the "Expect" request header
596 // correctly.
597 func TestServerExpect(t *testing.T) {
598         ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
599                 // Note using r.FormValue("readbody") because for POST
600                 // requests that would read from r.Body, which we only
601                 // conditionally want to do.
602                 if strings.Contains(r.URL.RawPath, "readbody=true") {
603                         ioutil.ReadAll(r.Body)
604                         w.Write([]byte("Hi"))
605                 } else {
606                         w.WriteHeader(StatusUnauthorized)
607                 }
608         }))
609         defer ts.Close()
610
611         runTest := func(test serverExpectTest) {
612                 conn, err := net.Dial("tcp", ts.Listener.Addr().String())
613                 if err != nil {
614                         t.Fatalf("Dial: %v", err)
615                 }
616                 defer conn.Close()
617                 sendf := func(format string, args ...interface{}) {
618                         _, err := fmt.Fprintf(conn, format, args...)
619                         if err != nil {
620                                 t.Fatalf("On test %#v, error writing %q: %v", test, format, err)
621                         }
622                 }
623                 go func() {
624                         sendf("POST /?readbody=%v HTTP/1.1\r\n"+
625                                 "Connection: close\r\n"+
626                                 "Content-Length: %d\r\n"+
627                                 "Expect: %s\r\nHost: foo\r\n\r\n",
628                                 test.readBody, test.contentLength, test.expectation)
629                         if test.contentLength > 0 && strings.ToLower(test.expectation) != "100-continue" {
630                                 body := strings.Repeat("A", test.contentLength)
631                                 sendf(body)
632                         }
633                 }()
634                 bufr := bufio.NewReader(conn)
635                 line, err := bufr.ReadString('\n')
636                 if err != nil {
637                         t.Fatalf("ReadString: %v", err)
638                 }
639                 if !strings.Contains(line, test.expectedResponse) {
640                         t.Errorf("for test %#v got first line=%q", test, line)
641                 }
642         }
643
644         for _, test := range serverExpectTests {
645                 runTest(test)
646         }
647 }
648
649 func TestServerConsumesRequestBody(t *testing.T) {
650         conn := new(testConn)
651         body := strings.Repeat("x", 1<<20)
652         conn.readBuf.Write([]byte(fmt.Sprintf(
653                 "POST / HTTP/1.1\r\n"+
654                         "Host: test\r\n"+
655                         "Content-Length: %d\r\n"+
656                         "\r\n", len(body))))
657         conn.readBuf.Write([]byte(body))
658
659         done := make(chan bool)
660
661         ls := &oneConnListener{conn}
662         go Serve(ls, HandlerFunc(func(rw ResponseWriter, req *Request) {
663                 if conn.readBuf.Len() < len(body)/2 {
664                         t.Errorf("on request, read buffer length is %d; expected about 1MB", conn.readBuf.Len())
665                 }
666                 rw.WriteHeader(200)
667                 if g, e := conn.readBuf.Len(), 0; g != e {
668                         t.Errorf("after WriteHeader, read buffer length is %d; want %d", g, e)
669                 }
670                 done <- true
671         }))
672         <-done
673 }
674
675 func TestTimeoutHandler(t *testing.T) {
676         sendHi := make(chan bool, 1)
677         writeErrors := make(chan os.Error, 1)
678         sayHi := HandlerFunc(func(w ResponseWriter, r *Request) {
679                 <-sendHi
680                 _, werr := w.Write([]byte("hi"))
681                 writeErrors <- werr
682         })
683         timeout := make(chan int64, 1) // write to this to force timeouts
684         ts := httptest.NewServer(NewTestTimeoutHandler(sayHi, timeout))
685         defer ts.Close()
686
687         // Succeed without timing out:
688         sendHi <- true
689         res, err := Get(ts.URL)
690         if err != nil {
691                 t.Error(err)
692         }
693         if g, e := res.StatusCode, StatusOK; g != e {
694                 t.Errorf("got res.StatusCode %d; expected %d", g, e)
695         }
696         body, _ := ioutil.ReadAll(res.Body)
697         if g, e := string(body), "hi"; g != e {
698                 t.Errorf("got body %q; expected %q", g, e)
699         }
700         if g := <-writeErrors; g != nil {
701                 t.Errorf("got unexpected Write error on first request: %v", g)
702         }
703
704         // Times out:
705         timeout <- 1
706         res, err = Get(ts.URL)
707         if err != nil {
708                 t.Error(err)
709         }
710         if g, e := res.StatusCode, StatusServiceUnavailable; g != e {
711                 t.Errorf("got res.StatusCode %d; expected %d", g, e)
712         }
713         body, _ = ioutil.ReadAll(res.Body)
714         if !strings.Contains(string(body), "<title>Timeout</title>") {
715                 t.Errorf("expected timeout body; got %q", string(body))
716         }
717
718         // Now make the previously-timed out handler speak again,
719         // which verifies the panic is handled:
720         sendHi <- true
721         if g, e := <-writeErrors, ErrHandlerTimeout; g != e {
722                 t.Errorf("expected Write error of %v; got %v", e, g)
723         }
724 }
725
726 // Verifies we don't path.Clean() on the wrong parts in redirects.
727 func TestRedirectMunging(t *testing.T) {
728         req, _ := NewRequest("GET", "http://example.com/", nil)
729
730         resp := httptest.NewRecorder()
731         Redirect(resp, req, "/foo?next=http://bar.com/", 302)
732         if g, e := resp.Header().Get("Location"), "/foo?next=http://bar.com/"; g != e {
733                 t.Errorf("Location header was %q; want %q", g, e)
734         }
735
736         resp = httptest.NewRecorder()
737         Redirect(resp, req, "http://localhost:8080/_ah/login?continue=http://localhost:8080/", 302)
738         if g, e := resp.Header().Get("Location"), "http://localhost:8080/_ah/login?continue=http://localhost:8080/"; g != e {
739                 t.Errorf("Location header was %q; want %q", g, e)
740         }
741 }
742
743 // TestZeroLengthPostAndResponse exercises an optimization done by the Transport:
744 // when there is no body (either because the method doesn't permit a body, or an
745 // explicit Content-Length of zero is present), then the transport can re-use the
746 // connection immediately. But when it re-uses the connection, it typically closes
747 // the previous request's body, which is not optimal for zero-lengthed bodies,
748 // as the client would then see http.ErrBodyReadAfterClose and not 0, os.EOF.
749 func TestZeroLengthPostAndResponse(t *testing.T) {
750         ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, r *Request) {
751                 all, err := ioutil.ReadAll(r.Body)
752                 if err != nil {
753                         t.Fatalf("handler ReadAll: %v", err)
754                 }
755                 if len(all) != 0 {
756                         t.Errorf("handler got %d bytes; expected 0", len(all))
757                 }
758                 rw.Header().Set("Content-Length", "0")
759         }))
760         defer ts.Close()
761
762         req, err := NewRequest("POST", ts.URL, strings.NewReader(""))
763         if err != nil {
764                 t.Fatal(err)
765         }
766         req.ContentLength = 0
767
768         var resp [5]*Response
769         for i := range resp {
770                 resp[i], err = DefaultClient.Do(req)
771                 if err != nil {
772                         t.Fatalf("client post #%d: %v", i, err)
773                 }
774         }
775
776         for i := range resp {
777                 all, err := ioutil.ReadAll(resp[i].Body)
778                 if err != nil {
779                         t.Fatalf("req #%d: client ReadAll: %v", i, err)
780                 }
781                 if len(all) != 0 {
782                         t.Errorf("req #%d: client got %d bytes; expected 0", i, len(all))
783                 }
784         }
785 }
786
787 func TestHandlerPanic(t *testing.T) {
788         // Unlike the other tests that set the log output to ioutil.Discard
789         // to quiet the output, this test uses a pipe.  The pipe serves three
790         // purposes:
791         //
792         //   1) The log.Print from the http server (generated by the caught
793         //      panic) will go to the pipe instead of stderr, making the
794         //      output quiet.
795         //
796         //   2) We read from the pipe to verify that the handler
797         //      actually caught the panic and logged something.
798         //
799         //   3) The blocking Read call prevents this TestHandlerPanic
800         //      function from exiting before the HTTP server handler
801         //      finishes crashing. If this text function exited too
802         //      early (and its defer log.SetOutput(os.Stderr) ran),
803         //      then the crash output could spill into the next test.
804         pr, pw := io.Pipe()
805         log.SetOutput(pw)
806         defer log.SetOutput(os.Stderr)
807
808         ts := httptest.NewServer(HandlerFunc(func(ResponseWriter, *Request) {
809                 panic("intentional death for testing")
810         }))
811         defer ts.Close()
812         _, err := Get(ts.URL)
813         if err == nil {
814                 t.Logf("expected an error")
815         }
816
817         // Do a blocking read on the log output pipe so its logging
818         // doesn't bleed into the next test.  But wait only 5 seconds
819         // for it.
820         done := make(chan bool)
821         go func() {
822                 buf := make([]byte, 1024)
823                 _, err := pr.Read(buf)
824                 pr.Close()
825                 if err != nil {
826                         t.Fatal(err)
827                 }
828                 done <- true
829         }()
830         select {
831         case <-done:
832                 return
833         case <-time.After(5e9):
834                 t.Fatal("expected server handler to log an error")
835         }
836 }
837
838 func TestNoDate(t *testing.T) {
839         ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
840                 w.Header()["Date"] = nil
841         }))
842         defer ts.Close()
843         res, err := Get(ts.URL)
844         if err != nil {
845                 t.Fatal(err)
846         }
847         _, present := res.Header["Date"]
848         if present {
849                 t.Fatalf("Expected no Date header; got %v", res.Header["Date"])
850         }
851 }
852
853 func TestStripPrefix(t *testing.T) {
854         h := HandlerFunc(func(w ResponseWriter, r *Request) {
855                 w.Header().Set("X-Path", r.URL.Path)
856         })
857         ts := httptest.NewServer(StripPrefix("/foo", h))
858         defer ts.Close()
859
860         res, err := Get(ts.URL + "/foo/bar")
861         if err != nil {
862                 t.Fatal(err)
863         }
864         if g, e := res.Header.Get("X-Path"), "/bar"; g != e {
865                 t.Errorf("test 1: got %s, want %s", g, e)
866         }
867
868         res, err = Get(ts.URL + "/bar")
869         if err != nil {
870                 t.Fatal(err)
871         }
872         if g, e := res.StatusCode, 404; g != e {
873                 t.Errorf("test 2: got status %v, want %v", g, e)
874         }
875 }
876
877 func TestRequestLimit(t *testing.T) {
878         ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
879                 t.Fatalf("didn't expect to get request in Handler")
880         }))
881         defer ts.Close()
882         req, _ := NewRequest("GET", ts.URL, nil)
883         var bytesPerHeader = len("header12345: val12345\r\n")
884         for i := 0; i < ((DefaultMaxHeaderBytes+4096)/bytesPerHeader)+1; i++ {
885                 req.Header.Set(fmt.Sprintf("header%05d", i), fmt.Sprintf("val%05d", i))
886         }
887         res, err := DefaultClient.Do(req)
888         if err != nil {
889                 // Some HTTP clients may fail on this undefined behavior (server replying and
890                 // closing the connection while the request is still being written), but
891                 // we do support it (at least currently), so we expect a response below.
892                 t.Fatalf("Do: %v", err)
893         }
894         if res.StatusCode != 400 {
895                 t.Fatalf("expected 400 response status; got: %d %s", res.StatusCode, res.Status)
896         }
897 }
898
899 type errorListener struct {
900         errs []os.Error
901 }
902
903 func (l *errorListener) Accept() (c net.Conn, err os.Error) {
904         if len(l.errs) == 0 {
905                 return nil, os.EOF
906         }
907         err = l.errs[0]
908         l.errs = l.errs[1:]
909         return
910 }
911
912 func (l *errorListener) Close() os.Error {
913         return nil
914 }
915
916 func (l *errorListener) Addr() net.Addr {
917         return dummyAddr("test-address")
918 }
919
920 func TestAcceptMaxFds(t *testing.T) {
921         log.SetOutput(ioutil.Discard) // is noisy otherwise
922         defer log.SetOutput(os.Stderr)
923
924         ln := &errorListener{[]os.Error{
925                 &net.OpError{
926                         Op:    "accept",
927                         Error: os.Errno(syscall.EMFILE),
928                 }}}
929         err := Serve(ln, HandlerFunc(HandlerFunc(func(ResponseWriter, *Request) {})))
930         if err != os.EOF {
931                 t.Errorf("got error %v, want EOF", err)
932         }
933 }
934
935 func BenchmarkClientServer(b *testing.B) {
936         b.StopTimer()
937         ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, r *Request) {
938                 fmt.Fprintf(rw, "Hello world.\n")
939         }))
940         defer ts.Close()
941         b.StartTimer()
942
943         for i := 0; i < b.N; i++ {
944                 res, err := Get(ts.URL)
945                 if err != nil {
946                         panic("Get: " + err.String())
947                 }
948                 all, err := ioutil.ReadAll(res.Body)
949                 if err != nil {
950                         panic("ReadAll: " + err.String())
951                 }
952                 body := string(all)
953                 if body != "Hello world.\n" {
954                         panic("Got body: " + body)
955                 }
956         }
957
958         b.StopTimer()
959 }