diff options
Diffstat (limited to 'libgo/go/net/http/client_test.go')
-rw-r--r-- | libgo/go/net/http/client_test.go | 209 |
1 files changed, 98 insertions, 111 deletions
diff --git a/libgo/go/net/http/client_test.go b/libgo/go/net/http/client_test.go index 7b524d3..8939dc8 100644 --- a/libgo/go/net/http/client_test.go +++ b/libgo/go/net/http/client_test.go @@ -20,8 +20,6 @@ import ( . "net/http" "net/http/httptest" "net/url" - "reflect" - "sort" "strconv" "strings" "sync" @@ -83,12 +81,15 @@ func TestClient(t *testing.T) { } } -func TestClientHead(t *testing.T) { +func TestClientHead_h1(t *testing.T) { testClientHead(t, h1Mode) } +func TestClientHead_h2(t *testing.T) { testClientHead(t, h2Mode) } + +func testClientHead(t *testing.T, h2 bool) { defer afterTest(t) - ts := httptest.NewServer(robotsTxtHandler) - defer ts.Close() + cst := newClientServerTest(t, h2, robotsTxtHandler) + defer cst.close() - r, err := Head(ts.URL) + r, err := cst.c.Head(cst.ts.URL) if err != nil { t.Fatal(err) } @@ -230,9 +231,18 @@ func TestClientRedirects(t *testing.T) { t.Errorf("with default client Do, expected error %q, got %q", e, g) } + // Requests with an empty Method should also redirect (Issue 12705) + greq.Method = "" + _, err = c.Do(greq) + if e, g := "Get /?n=10: stopped after 10 redirects", fmt.Sprintf("%v", err); e != g { + t.Errorf("with default client Do and empty Method, expected error %q, got %q", e, g) + } + var checkErr error var lastVia []*Request - c = &Client{CheckRedirect: func(_ *Request, via []*Request) error { + var lastReq *Request + c = &Client{CheckRedirect: func(req *Request, via []*Request) error { + lastReq = req lastVia = via return checkErr }} @@ -252,6 +262,20 @@ func TestClientRedirects(t *testing.T) { t.Errorf("expected lastVia to have contained %d elements; got %d", e, g) } + // Test that Request.Cancel is propagated between requests (Issue 14053) + creq, _ := NewRequest("HEAD", ts.URL, nil) + cancel := make(chan struct{}) + creq.Cancel = cancel + if _, err := c.Do(creq); err != nil { + t.Fatal(err) + } + if lastReq == nil { + t.Fatal("didn't see redirect") + } + if lastReq.Cancel != cancel { + t.Errorf("expected lastReq to have the cancel channel set on the inital req") + } + checkErr = errors.New("no redirects allowed") res, err = c.Get(ts.URL) if urlError, ok := err.(*url.Error); !ok || urlError.Err != checkErr { @@ -486,20 +510,23 @@ func (j *RecordingJar) logf(format string, args ...interface{}) { fmt.Fprintf(&j.log, format, args...) } -func TestStreamingGet(t *testing.T) { +func TestStreamingGet_h1(t *testing.T) { testStreamingGet(t, h1Mode) } +func TestStreamingGet_h2(t *testing.T) { testStreamingGet(t, h2Mode) } + +func testStreamingGet(t *testing.T, h2 bool) { defer afterTest(t) say := make(chan string) - ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { + cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { w.(Flusher).Flush() for str := range say { w.Write([]byte(str)) w.(Flusher).Flush() } })) - defer ts.Close() + defer cst.close() - c := &Client{} - res, err := c.Get(ts.URL) + c := cst.c + res, err := c.Get(cst.ts.URL) if err != nil { t.Fatal(err) } @@ -642,14 +669,18 @@ func newTLSTransport(t *testing.T, ts *httptest.Server) *Transport { func TestClientWithCorrectTLSServerName(t *testing.T) { defer afterTest(t) + + const serverName = "example.com" ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) { - if r.TLS.ServerName != "127.0.0.1" { - t.Errorf("expected client to set ServerName 127.0.0.1, got: %q", r.TLS.ServerName) + if r.TLS.ServerName != serverName { + t.Errorf("expected client to set ServerName %q, got: %q", serverName, r.TLS.ServerName) } })) defer ts.Close() - c := &Client{Transport: newTLSTransport(t, ts)} + trans := newTLSTransport(t, ts) + trans.TLSClientConfig.ServerName = serverName + c := &Client{Transport: trans} if _, err := c.Get(ts.URL); err != nil { t.Fatalf("expected successful TLS connection, got error: %v", err) } @@ -739,15 +770,37 @@ func TestResponseSetsTLSConnectionState(t *testing.T) { } } +// Check that an HTTPS client can interpret a particular TLS error +// to determine that the server is speaking HTTP. +// See golang.org/issue/11111. +func TestHTTPSClientDetectsHTTPServer(t *testing.T) { + defer afterTest(t) + ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {})) + defer ts.Close() + + _, err := Get(strings.Replace(ts.URL, "http", "https", 1)) + if got := err.Error(); !strings.Contains(got, "HTTP response to HTTPS client") { + t.Fatalf("error = %q; want error indicating HTTP response to HTTPS request", got) + } +} + // Verify Response.ContentLength is populated. https://golang.org/issue/4126 -func TestClientHeadContentLength(t *testing.T) { +func TestClientHeadContentLength_h1(t *testing.T) { + testClientHeadContentLength(t, h1Mode) +} + +func TestClientHeadContentLength_h2(t *testing.T) { + testClientHeadContentLength(t, h2Mode) +} + +func testClientHeadContentLength(t *testing.T, h2 bool) { defer afterTest(t) - ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { + cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { if v := r.FormValue("cl"); v != "" { w.Header().Set("Content-Length", v) } })) - defer ts.Close() + defer cst.close() tests := []struct { suffix string want int64 @@ -757,8 +810,8 @@ func TestClientHeadContentLength(t *testing.T) { {"", -1}, } for _, tt := range tests { - req, _ := NewRequest("HEAD", ts.URL+tt.suffix, nil) - res, err := DefaultClient.Do(req) + req, _ := NewRequest("HEAD", cst.ts.URL+tt.suffix, nil) + res, err := cst.c.Do(req) if err != nil { t.Fatal(err) } @@ -884,14 +937,17 @@ func TestBasicAuthHeadersPreserved(t *testing.T) { } -func TestClientTimeout(t *testing.T) { +func TestClientTimeout_h1(t *testing.T) { testClientTimeout(t, h1Mode) } +func TestClientTimeout_h2(t *testing.T) { testClientTimeout(t, h2Mode) } + +func testClientTimeout(t *testing.T, h2 bool) { if testing.Short() { t.Skip("skipping in short mode") } defer afterTest(t) sawRoot := make(chan bool, 1) sawSlow := make(chan bool, 1) - ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { + cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { if r.URL.Path == "/" { sawRoot <- true Redirect(w, r, "/slow", StatusFound) @@ -905,13 +961,11 @@ func TestClientTimeout(t *testing.T) { return } })) - defer ts.Close() + defer cst.close() const timeout = 500 * time.Millisecond - c := &Client{ - Timeout: timeout, - } + cst.c.Timeout = timeout - res, err := c.Get(ts.URL) + res, err := cst.c.Get(cst.ts.URL) if err != nil { t.Fatal(err) } @@ -957,17 +1011,20 @@ func TestClientTimeout(t *testing.T) { } } +func TestClientTimeout_Headers_h1(t *testing.T) { testClientTimeout_Headers(t, h1Mode) } +func TestClientTimeout_Headers_h2(t *testing.T) { testClientTimeout_Headers(t, h2Mode) } + // Client.Timeout firing before getting to the body -func TestClientTimeout_Headers(t *testing.T) { +func testClientTimeout_Headers(t *testing.T, h2 bool) { if testing.Short() { t.Skip("skipping in short mode") } defer afterTest(t) donec := make(chan bool) - ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { + cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { <-donec })) - defer ts.Close() + defer cst.close() // Note that we use a channel send here and not a close. // The race detector doesn't know that we're waiting for a timeout // and thinks that the waitgroup inside httptest.Server is added to concurrently @@ -977,19 +1034,17 @@ func TestClientTimeout_Headers(t *testing.T) { // doesn't know this, so synchronize explicitly. defer func() { donec <- true }() - c := &Client{Timeout: 500 * time.Millisecond} - - _, err := c.Get(ts.URL) + cst.c.Timeout = 500 * time.Millisecond + _, err := cst.c.Get(cst.ts.URL) if err == nil { t.Fatal("got response from Get; expected error") } - ue, ok := err.(*url.Error) - if !ok { + if _, ok := err.(*url.Error); !ok { t.Fatalf("Got error of type %T; want *url.Error", err) } - ne, ok := ue.Err.(net.Error) + ne, ok := err.(net.Error) if !ok { - t.Fatalf("Got url.Error.Err of type %T; want some net.Error", err) + t.Fatalf("Got error of type %T; want some net.Error", err) } if !ne.Timeout() { t.Error("net.Error.Timeout = false; want true") @@ -999,18 +1054,20 @@ func TestClientTimeout_Headers(t *testing.T) { } } -func TestClientRedirectEatsBody(t *testing.T) { +func TestClientRedirectEatsBody_h1(t *testing.T) { testClientRedirectEatsBody(t, h1Mode) } +func TestClientRedirectEatsBody_h2(t *testing.T) { testClientRedirectEatsBody(t, h2Mode) } +func testClientRedirectEatsBody(t *testing.T, h2 bool) { defer afterTest(t) saw := make(chan string, 2) - ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { + cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { saw <- r.RemoteAddr if r.URL.Path == "/" { Redirect(w, r, "/foo", StatusFound) // which includes a body } })) - defer ts.Close() + defer cst.close() - res, err := Get(ts.URL) + res, err := cst.c.Get(cst.ts.URL) if err != nil { t.Fatal(err) } @@ -1047,76 +1104,6 @@ func (f eofReaderFunc) Read(p []byte) (n int, err error) { return 0, io.EOF } -func TestClientTrailers(t *testing.T) { - defer afterTest(t) - ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { - w.Header().Set("Connection", "close") - w.Header().Set("Trailer", "Server-Trailer-A, Server-Trailer-B") - w.Header().Add("Trailer", "Server-Trailer-C") - - var decl []string - for k := range r.Trailer { - decl = append(decl, k) - } - sort.Strings(decl) - - slurp, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Errorf("Server reading request body: %v", err) - } - if string(slurp) != "foo" { - t.Errorf("Server read request body %q; want foo", slurp) - } - if r.Trailer == nil { - io.WriteString(w, "nil Trailer") - } else { - fmt.Fprintf(w, "decl: %v, vals: %s, %s", - decl, - r.Trailer.Get("Client-Trailer-A"), - r.Trailer.Get("Client-Trailer-B")) - } - - // How handlers set Trailers: declare it ahead of time - // with the Trailer header, and then mutate the - // Header() of those values later, after the response - // has been written (we wrote to w above). - w.Header().Set("Server-Trailer-A", "valuea") - w.Header().Set("Server-Trailer-C", "valuec") // skipping B - })) - defer ts.Close() - - var req *Request - req, _ = NewRequest("POST", ts.URL, io.MultiReader( - eofReaderFunc(func() { - req.Trailer["Client-Trailer-A"] = []string{"valuea"} - }), - strings.NewReader("foo"), - eofReaderFunc(func() { - req.Trailer["Client-Trailer-B"] = []string{"valueb"} - }), - )) - req.Trailer = Header{ - "Client-Trailer-A": nil, // to be set later - "Client-Trailer-B": nil, // to be set later - } - req.ContentLength = -1 - res, err := DefaultClient.Do(req) - if err != nil { - t.Fatal(err) - } - if err := wantBody(res, err, "decl: [Client-Trailer-A Client-Trailer-B], vals: valuea, valueb"); err != nil { - t.Error(err) - } - want := Header{ - "Server-Trailer-A": []string{"valuea"}, - "Server-Trailer-B": nil, - "Server-Trailer-C": []string{"valuec"}, - } - if !reflect.DeepEqual(res.Trailer, want) { - t.Errorf("Response trailers = %#v; want %#v", res.Trailer, want) - } -} - func TestReferer(t *testing.T) { tests := []struct { lastReq, newReq string // from -> to URLs |