summaryrefslogtreecommitdiff
path: root/libgo/go/net/http
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2012-01-25 21:54:22 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2012-01-25 21:54:22 +0000
commitaf92e385667da3fc91ac7f9f0867a56c111110b8 (patch)
treec8e8990a2197e33f6fe50a28a16714aafe982102 /libgo/go/net/http
parentdf1304ee03f41aed179545d1e8b4684cfd22bbdf (diff)
downloadgcc-af92e385667da3fc91ac7f9f0867a56c111110b8.tar.gz
libgo: Update to weekly.2012-01-20.
From-SVN: r183540
Diffstat (limited to 'libgo/go/net/http')
-rw-r--r--libgo/go/net/http/cgi/host.go2
-rw-r--r--libgo/go/net/http/cgi/host_test.go2
-rw-r--r--libgo/go/net/http/client.go19
-rw-r--r--libgo/go/net/http/client_test.go87
-rw-r--r--libgo/go/net/http/doc.go3
-rw-r--r--libgo/go/net/http/fs_test.go12
-rw-r--r--libgo/go/net/http/httputil/dump.go25
-rw-r--r--libgo/go/net/http/httputil/reverseproxy.go5
-rw-r--r--libgo/go/net/http/readrequest_test.go30
-rw-r--r--libgo/go/net/http/request.go22
-rw-r--r--libgo/go/net/http/requestwrite_test.go16
-rw-r--r--libgo/go/net/http/serve_test.go22
-rw-r--r--libgo/go/net/http/server.go15
-rw-r--r--libgo/go/net/http/transport.go7
14 files changed, 154 insertions, 113 deletions
diff --git a/libgo/go/net/http/cgi/host.go b/libgo/go/net/http/cgi/host.go
index 615d366aedc..73a9b6ea681 100644
--- a/libgo/go/net/http/cgi/host.go
+++ b/libgo/go/net/http/cgi/host.go
@@ -124,7 +124,7 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
"GATEWAY_INTERFACE=CGI/1.1",
"REQUEST_METHOD=" + req.Method,
"QUERY_STRING=" + req.URL.RawQuery,
- "REQUEST_URI=" + req.URL.RawPath,
+ "REQUEST_URI=" + req.URL.RequestURI(),
"PATH_INFO=" + pathInfo,
"SCRIPT_NAME=" + root,
"SCRIPT_FILENAME=" + h.Path,
diff --git a/libgo/go/net/http/cgi/host_test.go b/libgo/go/net/http/cgi/host_test.go
index 849cb008b76..b8dbdb4edd2 100644
--- a/libgo/go/net/http/cgi/host_test.go
+++ b/libgo/go/net/http/cgi/host_test.go
@@ -364,7 +364,7 @@ func TestCopyError(t *testing.T) {
conn.Close()
tries := 0
- for tries < 15 && childRunning() {
+ for tries < 25 && childRunning() {
time.Sleep(50 * time.Millisecond * time.Duration(tries))
tries++
}
diff --git a/libgo/go/net/http/client.go b/libgo/go/net/http/client.go
index a4f8f19aac8..1d70672695c 100644
--- a/libgo/go/net/http/client.go
+++ b/libgo/go/net/http/client.go
@@ -24,11 +24,13 @@ import (
// The Client's Transport typically has internal state (cached
// TCP connections), so Clients should be reused instead of created as
// needed. Clients are safe for concurrent use by multiple goroutines.
-//
-// Client is not yet very configurable.
type Client struct {
- Transport RoundTripper // if nil, DefaultTransport is used
+ // Transport specifies the mechanism by which individual
+ // HTTP requests are made.
+ // If nil, DefaultTransport is used.
+ Transport RoundTripper
+ // CheckRedirect specifies the policy for handling redirects.
// If CheckRedirect is not nil, the client calls it before
// following an HTTP redirect. The arguments req and via
// are the upcoming request and the requests made already,
@@ -121,9 +123,8 @@ func send(req *Request, t RoundTripper) (resp *Response, err error) {
req.Header = make(Header)
}
- info := req.URL.RawUserinfo
- if len(info) > 0 {
- req.Header.Set("Authorization", "Basic "+base64.URLEncoding.EncodeToString([]byte(info)))
+ if u := req.URL.User; u != nil {
+ req.Header.Set("Authorization", "Basic "+base64.URLEncoding.EncodeToString([]byte(u.String())))
}
return t.RoundTrip(req)
}
@@ -213,11 +214,11 @@ func (c *Client) doFollowingRedirects(ireq *Request) (r *Response, err error) {
break
}
}
- for _, cookie := range jar.Cookies(req.URL) {
- req.AddCookie(cookie)
- }
}
+ for _, cookie := range jar.Cookies(req.URL) {
+ req.AddCookie(cookie)
+ }
urlStr = req.URL.String()
if r, err = send(req, c.Transport); err != nil {
break
diff --git a/libgo/go/net/http/client_test.go b/libgo/go/net/http/client_test.go
index 57a9dd9574d..c74611011a8 100644
--- a/libgo/go/net/http/client_test.go
+++ b/libgo/go/net/http/client_test.go
@@ -18,6 +18,7 @@ import (
"net/url"
"strconv"
"strings"
+ "sync"
"testing"
)
@@ -236,6 +237,92 @@ func TestRedirects(t *testing.T) {
}
}
+var expectedCookies = []*Cookie{
+ &Cookie{Name: "ChocolateChip", Value: "tasty"},
+ &Cookie{Name: "First", Value: "Hit"},
+ &Cookie{Name: "Second", Value: "Hit"},
+}
+
+var echoCookiesRedirectHandler = HandlerFunc(func(w ResponseWriter, r *Request) {
+ for _, cookie := range r.Cookies() {
+ SetCookie(w, cookie)
+ }
+ if r.URL.Path == "/" {
+ SetCookie(w, expectedCookies[1])
+ Redirect(w, r, "/second", StatusMovedPermanently)
+ } else {
+ SetCookie(w, expectedCookies[2])
+ w.Write([]byte("hello"))
+ }
+})
+
+// Just enough correctness for our redirect tests. Uses the URL.Host as the
+// scope of all cookies.
+type TestJar struct {
+ m sync.Mutex
+ perURL map[string][]*Cookie
+}
+
+func (j *TestJar) SetCookies(u *url.URL, cookies []*Cookie) {
+ j.m.Lock()
+ defer j.m.Unlock()
+ j.perURL[u.Host] = cookies
+}
+
+func (j *TestJar) Cookies(u *url.URL) []*Cookie {
+ j.m.Lock()
+ defer j.m.Unlock()
+ return j.perURL[u.Host]
+}
+
+func TestRedirectCookiesOnRequest(t *testing.T) {
+ var ts *httptest.Server
+ ts = httptest.NewServer(echoCookiesRedirectHandler)
+ defer ts.Close()
+ c := &Client{}
+ req, _ := NewRequest("GET", ts.URL, nil)
+ req.AddCookie(expectedCookies[0])
+ // TODO: Uncomment when an implementation of a RFC6265 cookie jar lands.
+ _ = c
+ // resp, _ := c.Do(req)
+ // matchReturnedCookies(t, expectedCookies, resp.Cookies())
+
+ req, _ = NewRequest("GET", ts.URL, nil)
+ // resp, _ = c.Do(req)
+ // matchReturnedCookies(t, expectedCookies[1:], resp.Cookies())
+}
+
+func TestRedirectCookiesJar(t *testing.T) {
+ var ts *httptest.Server
+ ts = httptest.NewServer(echoCookiesRedirectHandler)
+ defer ts.Close()
+ c := &Client{}
+ c.Jar = &TestJar{perURL: make(map[string][]*Cookie)}
+ u, _ := url.Parse(ts.URL)
+ c.Jar.SetCookies(u, []*Cookie{expectedCookies[0]})
+ resp, _ := c.Get(ts.URL)
+ matchReturnedCookies(t, expectedCookies, resp.Cookies())
+}
+
+func matchReturnedCookies(t *testing.T, expected, given []*Cookie) {
+ t.Logf("Received cookies: %v", given)
+ if len(given) != len(expected) {
+ t.Errorf("Expected %d cookies, got %d", len(expected), len(given))
+ }
+ for _, ec := range expected {
+ foundC := false
+ for _, c := range given {
+ if ec.Name == c.Name && ec.Value == c.Value {
+ foundC = true
+ break
+ }
+ }
+ if !foundC {
+ t.Errorf("Missing cookie %v", ec)
+ }
+ }
+}
+
func TestStreamingGet(t *testing.T) {
say := make(chan string)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
diff --git a/libgo/go/net/http/doc.go b/libgo/go/net/http/doc.go
index 2dbcf8dc97c..8962ed31e6a 100644
--- a/libgo/go/net/http/doc.go
+++ b/libgo/go/net/http/doc.go
@@ -34,7 +34,8 @@ settings, create a Client:
resp, err := client.Get("http://example.com")
// ...
- req := http.NewRequest("GET", "http://example.com", nil)
+ req, err := http.NewRequest("GET", "http://example.com", nil)
+ // ...
req.Header.Add("If-None-Match", `W/"wyzzy"`)
resp, err := client.Do(req)
// ...
diff --git a/libgo/go/net/http/fs_test.go b/libgo/go/net/http/fs_test.go
index 976ee75c7dd..85cad3ec71b 100644
--- a/libgo/go/net/http/fs_test.go
+++ b/libgo/go/net/http/fs_test.go
@@ -224,16 +224,15 @@ func TestEmptyDirOpenCWD(t *testing.T) {
func TestServeFileContentType(t *testing.T) {
const ctype = "icecream/chocolate"
- override := false
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
- if override {
+ if r.FormValue("override") == "1" {
w.Header().Set("Content-Type", ctype)
}
ServeFile(w, r, "testdata/file")
}))
defer ts.Close()
- get := func(want string) {
- resp, err := Get(ts.URL)
+ get := func(override, want string) {
+ resp, err := Get(ts.URL + "?override=" + override)
if err != nil {
t.Fatal(err)
}
@@ -241,9 +240,8 @@ func TestServeFileContentType(t *testing.T) {
t.Errorf("Content-Type mismatch: got %q, want %q", h, want)
}
}
- get("text/plain; charset=utf-8")
- override = true
- get(ctype)
+ get("0", "text/plain; charset=utf-8")
+ get("1", ctype)
}
func TestServeFileMimeType(t *testing.T) {
diff --git a/libgo/go/net/http/httputil/dump.go b/libgo/go/net/http/httputil/dump.go
index 31696aec86e..b8a98ee4292 100644
--- a/libgo/go/net/http/httputil/dump.go
+++ b/libgo/go/net/http/httputil/dump.go
@@ -13,6 +13,7 @@ import (
"net"
"net/http"
"strings"
+ "time"
)
// One of the copies, say from b to r2, could be avoided by using a more
@@ -36,12 +37,12 @@ type dumpConn struct {
io.Reader
}
-func (c *dumpConn) Close() error { return nil }
-func (c *dumpConn) LocalAddr() net.Addr { return nil }
-func (c *dumpConn) RemoteAddr() net.Addr { return nil }
-func (c *dumpConn) SetTimeout(nsec int64) error { return nil }
-func (c *dumpConn) SetReadTimeout(nsec int64) error { return nil }
-func (c *dumpConn) SetWriteTimeout(nsec int64) error { return nil }
+func (c *dumpConn) Close() error { return nil }
+func (c *dumpConn) LocalAddr() net.Addr { return nil }
+func (c *dumpConn) RemoteAddr() net.Addr { return nil }
+func (c *dumpConn) SetDeadline(t time.Time) error { return nil }
+func (c *dumpConn) SetReadDeadline(t time.Time) error { return nil }
+func (c *dumpConn) SetWriteDeadline(t time.Time) error { return nil }
// DumpRequestOut is like DumpRequest but includes
// headers that the standard http.Transport adds,
@@ -124,16 +125,8 @@ func DumpRequest(req *http.Request, body bool) (dump []byte, err error) {
var b bytes.Buffer
- urlStr := req.URL.Raw
- if urlStr == "" {
- urlStr = valueOrDefault(req.URL.EncodedPath(), "/")
- if req.URL.RawQuery != "" {
- urlStr += "?" + req.URL.RawQuery
- }
- }
-
- fmt.Fprintf(&b, "%s %s HTTP/%d.%d\r\n", valueOrDefault(req.Method, "GET"), urlStr,
- req.ProtoMajor, req.ProtoMinor)
+ fmt.Fprintf(&b, "%s %s HTTP/%d.%d\r\n", valueOrDefault(req.Method, "GET"),
+ req.URL.RequestURI(), req.ProtoMajor, req.ProtoMinor)
host := req.Host
if host == "" && req.URL != nil {
diff --git a/libgo/go/net/http/httputil/reverseproxy.go b/libgo/go/net/http/httputil/reverseproxy.go
index 1dc83e7d032..1072e2e3426 100644
--- a/libgo/go/net/http/httputil/reverseproxy.go
+++ b/libgo/go/net/http/httputil/reverseproxy.go
@@ -59,11 +59,6 @@ func NewSingleHostReverseProxy(target *url.URL) *ReverseProxy {
req.URL.Scheme = target.Scheme
req.URL.Host = target.Host
req.URL.Path = singleJoiningSlash(target.Path, req.URL.Path)
- if q := req.URL.RawQuery; q != "" {
- req.URL.RawPath = req.URL.Path + "?" + q
- } else {
- req.URL.RawPath = req.URL.Path
- }
req.URL.RawQuery = target.RawQuery
}
return &ReverseProxy{Director: director}
diff --git a/libgo/go/net/http/readrequest_test.go b/libgo/go/net/http/readrequest_test.go
index ad7e3c02b0c..da3e4050fe1 100644
--- a/libgo/go/net/http/readrequest_test.go
+++ b/libgo/go/net/http/readrequest_test.go
@@ -44,15 +44,9 @@ var reqTests = []reqTest{
&Request{
Method: "GET",
URL: &url.URL{
- Raw: "http://www.techcrunch.com/",
- Scheme: "http",
- RawPath: "/",
- RawAuthority: "www.techcrunch.com",
- RawUserinfo: "",
- Host: "www.techcrunch.com",
- Path: "/",
- RawQuery: "",
- Fragment: "",
+ Scheme: "http",
+ Host: "www.techcrunch.com",
+ Path: "/",
},
Proto: "HTTP/1.1",
ProtoMajor: 1,
@@ -86,9 +80,7 @@ var reqTests = []reqTest{
&Request{
Method: "GET",
URL: &url.URL{
- Raw: "/",
- Path: "/",
- RawPath: "/",
+ Path: "/",
},
Proto: "HTTP/1.1",
ProtoMajor: 1,
@@ -113,15 +105,7 @@ var reqTests = []reqTest{
&Request{
Method: "GET",
URL: &url.URL{
- Raw: "//user@host/is/actually/a/path/",
- Scheme: "",
- RawPath: "//user@host/is/actually/a/path/",
- RawAuthority: "",
- RawUserinfo: "",
- Host: "",
- Path: "//user@host/is/actually/a/path/",
- RawQuery: "",
- Fragment: "",
+ Path: "//user@host/is/actually/a/path/",
},
Proto: "HTTP/1.1",
ProtoMajor: 1,
@@ -170,9 +154,7 @@ var reqTests = []reqTest{
&Request{
Method: "POST",
URL: &url.URL{
- Raw: "/",
- Path: "/",
- RawPath: "/",
+ Path: "/",
},
TransferEncoding: []string{"chunked"},
Proto: "HTTP/1.1",
diff --git a/libgo/go/net/http/request.go b/libgo/go/net/http/request.go
index 260301005eb..5a4e739073a 100644
--- a/libgo/go/net/http/request.go
+++ b/libgo/go/net/http/request.go
@@ -302,26 +302,14 @@ func (req *Request) write(w io.Writer, usingProxy bool, extraHeaders Header) err
host = req.URL.Host
}
- urlStr := req.URL.RawPath
- if strings.HasPrefix(urlStr, "?") {
- urlStr = "/" + urlStr // Issue 2344
- }
- if urlStr == "" {
- urlStr = valueOrDefault(req.URL.RawPath, valueOrDefault(req.URL.EncodedPath(), "/"))
- if req.URL.RawQuery != "" {
- urlStr += "?" + req.URL.RawQuery
- }
- if usingProxy {
- if urlStr == "" || urlStr[0] != '/' {
- urlStr = "/" + urlStr
- }
- urlStr = req.URL.Scheme + "://" + host + urlStr
- }
+ ruri := req.URL.RequestURI()
+ if usingProxy && req.URL.Scheme != "" && req.URL.Opaque == "" {
+ ruri = req.URL.Scheme + "://" + host + ruri
}
- // TODO(bradfitz): escape at least newlines in urlStr?
+ // TODO(bradfitz): escape at least newlines in ruri?
bw := bufio.NewWriter(w)
- fmt.Fprintf(bw, "%s %s HTTP/1.1\r\n", valueOrDefault(req.Method, "GET"), urlStr)
+ fmt.Fprintf(bw, "%s %s HTTP/1.1\r\n", valueOrDefault(req.Method, "GET"), ruri)
// Header lines
fmt.Fprintf(bw, "Host: %s\r\n", host)
diff --git a/libgo/go/net/http/requestwrite_test.go b/libgo/go/net/http/requestwrite_test.go
index 8081589f5f2..fc3186f0c0c 100644
--- a/libgo/go/net/http/requestwrite_test.go
+++ b/libgo/go/net/http/requestwrite_test.go
@@ -32,15 +32,9 @@ var reqWriteTests = []reqWriteTest{
Req: Request{
Method: "GET",
URL: &url.URL{
- Raw: "http://www.techcrunch.com/",
- Scheme: "http",
- RawPath: "http://www.techcrunch.com/",
- RawAuthority: "www.techcrunch.com",
- RawUserinfo: "",
- Host: "www.techcrunch.com",
- Path: "/",
- RawQuery: "",
- Fragment: "",
+ Scheme: "http",
+ Host: "www.techcrunch.com",
+ Path: "/",
},
Proto: "HTTP/1.1",
ProtoMajor: 1,
@@ -60,7 +54,7 @@ var reqWriteTests = []reqWriteTest{
Form: map[string][]string{},
},
- WantWrite: "GET http://www.techcrunch.com/ HTTP/1.1\r\n" +
+ WantWrite: "GET / HTTP/1.1\r\n" +
"Host: www.techcrunch.com\r\n" +
"User-Agent: Fake\r\n" +
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" +
@@ -198,7 +192,7 @@ var reqWriteTests = []reqWriteTest{
"\r\n" +
"abcdef",
- WantProxy: "POST / HTTP/1.1\r\n" +
+ WantProxy: "POST http://example.com/ HTTP/1.1\r\n" +
"Host: example.com\r\n" +
"User-Agent: Go http package\r\n" +
"Content-Length: 6\r\n" +
diff --git a/libgo/go/net/http/serve_test.go b/libgo/go/net/http/serve_test.go
index 24e6b50dab8..147c216ec78 100644
--- a/libgo/go/net/http/serve_test.go
+++ b/libgo/go/net/http/serve_test.go
@@ -84,15 +84,15 @@ func (c *testConn) RemoteAddr() net.Addr {
return dummyAddr("remote-addr")
}
-func (c *testConn) SetTimeout(nsec int64) error {
+func (c *testConn) SetDeadline(t time.Time) error {
return nil
}
-func (c *testConn) SetReadTimeout(nsec int64) error {
+func (c *testConn) SetReadDeadline(t time.Time) error {
return nil
}
-func (c *testConn) SetWriteTimeout(nsec int64) error {
+func (c *testConn) SetWriteDeadline(t time.Time) error {
return nil
}
@@ -642,7 +642,7 @@ func TestServerExpect(t *testing.T) {
// Note using r.FormValue("readbody") because for POST
// requests that would read from r.Body, which we only
// conditionally want to do.
- if strings.Contains(r.URL.RawPath, "readbody=true") {
+ if strings.Contains(r.URL.RawQuery, "readbody=true") {
ioutil.ReadAll(r.Body)
w.Write([]byte("Hi"))
} else {
@@ -904,17 +904,13 @@ func testHandlerPanic(t *testing.T, withHijack bool) {
panic("intentional death for testing")
}))
defer ts.Close()
- _, err := Get(ts.URL)
- if err == nil {
- t.Logf("expected an error")
- }
// Do a blocking read on the log output pipe so its logging
// doesn't bleed into the next test. But wait only 5 seconds
// for it.
- done := make(chan bool)
+ done := make(chan bool, 1)
go func() {
- buf := make([]byte, 1024)
+ buf := make([]byte, 4<<10)
_, err := pr.Read(buf)
pr.Close()
if err != nil {
@@ -922,6 +918,12 @@ func testHandlerPanic(t *testing.T, withHijack bool) {
}
done <- true
}()
+
+ _, err := Get(ts.URL)
+ if err == nil {
+ t.Logf("expected an error")
+ }
+
select {
case <-done:
return
diff --git a/libgo/go/net/http/server.go b/libgo/go/net/http/server.go
index fa9009517db..bad3bcb2896 100644
--- a/libgo/go/net/http/server.go
+++ b/libgo/go/net/http/server.go
@@ -569,14 +569,15 @@ func (c *conn) serve() {
if err == nil {
return
}
- if c.rwc != nil { // may be nil if connection hijacked
- c.rwc.Close()
- }
var buf bytes.Buffer
fmt.Fprintf(&buf, "http: panic serving %v: %v\n", c.remoteAddr, err)
buf.Write(debug.Stack())
log.Print(buf.String())
+
+ if c.rwc != nil { // may be nil if connection hijacked
+ c.rwc.Close()
+ }
}()
if tlsConn, ok := c.rwc.(*tls.Conn); ok {
@@ -954,8 +955,8 @@ func Serve(l net.Listener, handler Handler) error {
type Server struct {
Addr string // TCP address to listen on, ":http" if empty
Handler Handler // handler to invoke, http.DefaultServeMux if nil
- ReadTimeout time.Duration // the net.Conn.SetReadTimeout value for new connections
- WriteTimeout time.Duration // the net.Conn.SetWriteTimeout value for new connections
+ ReadTimeout time.Duration // maximum duration before timing out read of the request
+ WriteTimeout time.Duration // maximum duration before timing out write of the response
MaxHeaderBytes int // maximum size of request headers, DefaultMaxHeaderBytes if 0
}
@@ -989,10 +990,10 @@ func (srv *Server) Serve(l net.Listener) error {
return e
}
if srv.ReadTimeout != 0 {
- rw.SetReadTimeout(srv.ReadTimeout.Nanoseconds())
+ rw.SetReadDeadline(time.Now().Add(srv.ReadTimeout))
}
if srv.WriteTimeout != 0 {
- rw.SetWriteTimeout(srv.WriteTimeout.Nanoseconds())
+ rw.SetWriteDeadline(time.Now().Add(srv.WriteTimeout))
}
c, err := srv.newConn(rw)
if err != nil {
diff --git a/libgo/go/net/http/transport.go b/libgo/go/net/http/transport.go
index 33ad32861b5..1b9ad1b85c5 100644
--- a/libgo/go/net/http/transport.go
+++ b/libgo/go/net/http/transport.go
@@ -229,9 +229,8 @@ func (cm *connectMethod) proxyAuth() string {
if cm.proxyURL == nil {
return ""
}
- proxyInfo := cm.proxyURL.RawUserinfo
- if proxyInfo != "" {
- return "Basic " + base64.URLEncoding.EncodeToString([]byte(proxyInfo))
+ if u := cm.proxyURL.User; u != nil {
+ return "Basic " + base64.URLEncoding.EncodeToString([]byte(u.String()))
}
return ""
}
@@ -332,7 +331,7 @@ func (t *Transport) getConn(cm *connectMethod) (*persistConn, error) {
case cm.targetScheme == "https":
connectReq := &Request{
Method: "CONNECT",
- URL: &url.URL{RawPath: cm.targetAddr},
+ URL: &url.URL{Opaque: cm.targetAddr},
Host: cm.targetAddr,
Header: make(Header),
}