diff options
author | ian <ian@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-02-09 08:19:58 +0000 |
---|---|---|
committer | ian <ian@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-02-09 08:19:58 +0000 |
commit | 2da6f72bb78de6e6ca3d387d970cb21bf36684be (patch) | |
tree | 7ca86535c5a6b99d4cc432ba5cfddabc5ee4ea16 /libgo/go/net/http | |
parent | 98ea39f2b59cc0a4a0a32b095e8f0faa84fd7882 (diff) | |
download | gcc-2da6f72bb78de6e6ca3d387d970cb21bf36684be.tar.gz |
libgo: Update to weekly.2012-02-07.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@184034 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgo/go/net/http')
-rw-r--r-- | libgo/go/net/http/cgi/host.go | 2 | ||||
-rw-r--r-- | libgo/go/net/http/client.go | 12 | ||||
-rw-r--r-- | libgo/go/net/http/fcgi/fcgi.go | 2 | ||||
-rw-r--r-- | libgo/go/net/http/fs_test.go | 2 | ||||
-rw-r--r-- | libgo/go/net/http/httputil/dump.go | 55 | ||||
-rw-r--r-- | libgo/go/net/http/httputil/persist.go | 4 | ||||
-rw-r--r-- | libgo/go/net/http/httputil/reverseproxy.go | 7 | ||||
-rw-r--r-- | libgo/go/net/http/httputil/reverseproxy_test.go | 38 | ||||
-rw-r--r-- | libgo/go/net/http/request.go | 16 | ||||
-rw-r--r-- | libgo/go/net/http/response.go | 24 | ||||
-rw-r--r-- | libgo/go/net/http/serve_test.go | 9 | ||||
-rw-r--r-- | libgo/go/net/http/server.go | 8 | ||||
-rw-r--r-- | libgo/go/net/http/transport.go | 4 | ||||
-rw-r--r-- | libgo/go/net/http/transport_test.go | 12 |
14 files changed, 140 insertions, 55 deletions
diff --git a/libgo/go/net/http/cgi/host.go b/libgo/go/net/http/cgi/host.go index 73a9b6ea681..d27cc4dc9a8 100644 --- a/libgo/go/net/http/cgi/host.go +++ b/libgo/go/net/http/cgi/host.go @@ -217,7 +217,7 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) { defer cmd.Wait() defer stdoutRead.Close() - linebody, _ := bufio.NewReaderSize(stdoutRead, 1024) + linebody := bufio.NewReaderSize(stdoutRead, 1024) headers := make(http.Header) statusCode := 0 for { diff --git a/libgo/go/net/http/client.go b/libgo/go/net/http/client.go index c9f02401757..5d450258bd3 100644 --- a/libgo/go/net/http/client.go +++ b/libgo/go/net/http/client.go @@ -245,7 +245,11 @@ func (c *Client) doFollowingRedirects(ireq *Request) (r *Response, err error) { } method := ireq.Method - err = &url.Error{method[0:1] + strings.ToLower(method[1:]), urlStr, err} + err = &url.Error{ + Op: method[0:1] + strings.ToLower(method[1:]), + URL: urlStr, + Err: err, + } return } @@ -274,7 +278,11 @@ func (c *Client) Post(url string, bodyType string, body io.Reader) (r *Response, return nil, err } req.Header.Set("Content-Type", bodyType) - return send(req, c.Transport) + r, err = send(req, c.Transport) + if err == nil && c.Jar != nil { + c.Jar.SetCookies(req.URL, r.Cookies()) + } + return r, err } // PostForm issues a POST to the specified URL, diff --git a/libgo/go/net/http/fcgi/fcgi.go b/libgo/go/net/http/fcgi/fcgi.go index d35aa84d229..06bba0488a2 100644 --- a/libgo/go/net/http/fcgi/fcgi.go +++ b/libgo/go/net/http/fcgi/fcgi.go @@ -240,7 +240,7 @@ func (w *bufWriter) Close() error { func newWriter(c *conn, recType recType, reqId uint16) *bufWriter { s := &streamWriter{c: c, recType: recType, reqId: reqId} - w, _ := bufio.NewWriterSize(s, maxWrite) + w := bufio.NewWriterSize(s, maxWrite) return &bufWriter{s, w} } diff --git a/libgo/go/net/http/fs_test.go b/libgo/go/net/http/fs_test.go index 85cad3ec71b..feea9209e6a 100644 --- a/libgo/go/net/http/fs_test.go +++ b/libgo/go/net/http/fs_test.go @@ -190,7 +190,7 @@ func TestDirJoin(t *testing.T) { if err != nil { t.Fatalf("stat of %s: %v", name, err) } - if !gfi.(*os.FileStat).SameFile(wfi.(*os.FileStat)) { + if !os.SameFile(gfi, wfi) { t.Errorf("%s got different file", name) } } diff --git a/libgo/go/net/http/httputil/dump.go b/libgo/go/net/http/httputil/dump.go index b8a98ee4292..c853066f1cf 100644 --- a/libgo/go/net/http/httputil/dump.go +++ b/libgo/go/net/http/httputil/dump.go @@ -5,8 +5,8 @@ package httputil import ( + "bufio" "bytes" - "errors" "fmt" "io" "io/ioutil" @@ -47,40 +47,59 @@ func (c *dumpConn) SetWriteDeadline(t time.Time) error { return nil } // DumpRequestOut is like DumpRequest but includes // headers that the standard http.Transport adds, // such as User-Agent. -func DumpRequestOut(req *http.Request, body bool) (dump []byte, err error) { +func DumpRequestOut(req *http.Request, body bool) ([]byte, error) { save := req.Body if !body || req.Body == nil { req.Body = nil } else { + var err error save, req.Body, err = drainBody(req.Body) if err != nil { - return + return nil, err } } - var b bytes.Buffer - dialed := false + // Use the actual Transport code to record what we would send + // on the wire, but not using TCP. Use a Transport with a + // customer dialer that returns a fake net.Conn that waits + // for the full input (and recording it), and then responds + // with a dummy response. + var buf bytes.Buffer // records the output + pr, pw := io.Pipe() + dr := &delegateReader{c: make(chan io.Reader)} + // Wait for the request before replying with a dummy response: + go func() { + http.ReadRequest(bufio.NewReader(pr)) + dr.c <- strings.NewReader("HTTP/1.1 204 No Content\r\n\r\n") + }() + t := &http.Transport{ - Dial: func(net, addr string) (c net.Conn, err error) { - if dialed { - return nil, errors.New("unexpected second dial") - } - c = &dumpConn{ - Writer: &b, - Reader: strings.NewReader("HTTP/1.1 500 Fake Error\r\n\r\n"), - } - return + Dial: func(net, addr string) (net.Conn, error) { + return &dumpConn{io.MultiWriter(pw, &buf), dr}, nil }, } - _, err = t.RoundTrip(req) + _, err := t.RoundTrip(req) req.Body = save if err != nil { - return + return nil, err } - dump = b.Bytes() - return + return buf.Bytes(), nil +} + +// delegateReader is a reader that delegates to another reader, +// once it arrives on a channel. +type delegateReader struct { + c chan io.Reader + r io.Reader // nil until received from c +} + +func (r *delegateReader) Read(p []byte) (int, error) { + if r.r == nil { + r.r = <-r.c + } + return r.r.Read(p) } // Return value if nonempty, def otherwise. diff --git a/libgo/go/net/http/httputil/persist.go b/libgo/go/net/http/httputil/persist.go index 1266bd3ad22..c065ccfb499 100644 --- a/libgo/go/net/http/httputil/persist.go +++ b/libgo/go/net/http/httputil/persist.go @@ -18,8 +18,8 @@ import ( ) var ( - ErrPersistEOF = &http.ProtocolError{"persistent connection closed"} - ErrPipeline = &http.ProtocolError{"pipeline error"} + ErrPersistEOF = &http.ProtocolError{ErrorString: "persistent connection closed"} + ErrPipeline = &http.ProtocolError{ErrorString: "pipeline error"} ) // This is an API usage error - the local side is closed. diff --git a/libgo/go/net/http/httputil/reverseproxy.go b/libgo/go/net/http/httputil/reverseproxy.go index 1072e2e3426..9c4bd6e09a5 100644 --- a/libgo/go/net/http/httputil/reverseproxy.go +++ b/libgo/go/net/http/httputil/reverseproxy.go @@ -55,11 +55,16 @@ func singleJoiningSlash(a, b string) string { // target's path is "/base" and the incoming request was for "/dir", // the target request will be for /base/dir. func NewSingleHostReverseProxy(target *url.URL) *ReverseProxy { + targetQuery := target.RawQuery director := func(req *http.Request) { req.URL.Scheme = target.Scheme req.URL.Host = target.Host req.URL.Path = singleJoiningSlash(target.Path, req.URL.Path) - req.URL.RawQuery = target.RawQuery + if targetQuery == "" || req.URL.RawQuery == "" { + req.URL.RawQuery = targetQuery + req.URL.RawQuery + } else { + req.URL.RawQuery = targetQuery + "&" + req.URL.RawQuery + } } return &ReverseProxy{Director: director} } diff --git a/libgo/go/net/http/httputil/reverseproxy_test.go b/libgo/go/net/http/httputil/reverseproxy_test.go index 655784b30d5..28e9c90ad36 100644 --- a/libgo/go/net/http/httputil/reverseproxy_test.go +++ b/libgo/go/net/http/httputil/reverseproxy_test.go @@ -69,3 +69,41 @@ func TestReverseProxy(t *testing.T) { t.Errorf("got body %q; expected %q", g, e) } } + +var proxyQueryTests = []struct { + baseSuffix string // suffix to add to backend URL + reqSuffix string // suffix to add to frontend's request URL + want string // what backend should see for final request URL (without ?) +}{ + {"", "", ""}, + {"?sta=tic", "?us=er", "sta=tic&us=er"}, + {"", "?us=er", "us=er"}, + {"?sta=tic", "", "sta=tic"}, +} + +func TestReverseProxyQuery(t *testing.T) { + backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("X-Got-Query", r.URL.RawQuery) + w.Write([]byte("hi")) + })) + defer backend.Close() + + for i, tt := range proxyQueryTests { + backendURL, err := url.Parse(backend.URL + tt.baseSuffix) + if err != nil { + t.Fatal(err) + } + frontend := httptest.NewServer(NewSingleHostReverseProxy(backendURL)) + req, _ := http.NewRequest("GET", frontend.URL+tt.reqSuffix, nil) + req.Close = true + res, err := http.DefaultClient.Do(req) + if err != nil { + t.Fatalf("%d. Get: %v", i, err) + } + if g, e := res.Header.Get("X-Got-Query"), tt.want; g != e { + t.Errorf("%d. got query %q; expected %q", i, g, e) + } + res.Body.Close() + frontend.Close() + } +} diff --git a/libgo/go/net/http/request.go b/libgo/go/net/http/request.go index 5f8c00086be..0bbec53be71 100644 --- a/libgo/go/net/http/request.go +++ b/libgo/go/net/http/request.go @@ -272,7 +272,7 @@ func valueOrDefault(value, def string) string { const defaultUserAgent = "Go http package" // Write writes an HTTP/1.1 request -- header and body -- in wire format. -// This method consults the following fields of req: +// This method consults the following fields of the request: // Host // URL // Method (defaults to "GET") @@ -284,18 +284,18 @@ const defaultUserAgent = "Go http package" // If Body is present, Content-Length is <= 0 and TransferEncoding // hasn't been set to "identity", Write adds "Transfer-Encoding: // chunked" to the header. Body is closed after it is sent. -func (req *Request) Write(w io.Writer) error { - return req.write(w, false, nil) +func (r *Request) Write(w io.Writer) error { + return r.write(w, false, nil) } // WriteProxy is like Write but writes the request in the form // expected by an HTTP proxy. In particular, WriteProxy writes the // initial Request-URI line of the request with an absolute URI, per -// section 5.1.2 of RFC 2616, including the scheme and host. In -// either case, WriteProxy also writes a Host header, using either -// req.Host or req.URL.Host. -func (req *Request) WriteProxy(w io.Writer) error { - return req.write(w, true, nil) +// section 5.1.2 of RFC 2616, including the scheme and host. +// In either case, WriteProxy also writes a Host header, using +// either r.Host or r.URL.Host. +func (r *Request) WriteProxy(w io.Writer) error { + return r.write(w, true, nil) } // extraHeaders may be nil diff --git a/libgo/go/net/http/response.go b/libgo/go/net/http/response.go index ae314b5ac93..b7902209786 100644 --- a/libgo/go/net/http/response.go +++ b/libgo/go/net/http/response.go @@ -174,7 +174,7 @@ func (r *Response) ProtoAtLeast(major, minor int) bool { } // Writes the response (header, body and trailer) in wire format. This method -// consults the following fields of resp: +// consults the following fields of the response: // // StatusCode // ProtoMajor @@ -186,28 +186,28 @@ func (r *Response) ProtoAtLeast(major, minor int) bool { // ContentLength // Header, values for non-canonical keys will have unpredictable behavior // -func (resp *Response) Write(w io.Writer) error { +func (r *Response) Write(w io.Writer) error { // RequestMethod should be upper-case - if resp.Request != nil { - resp.Request.Method = strings.ToUpper(resp.Request.Method) + if r.Request != nil { + r.Request.Method = strings.ToUpper(r.Request.Method) } // Status line - text := resp.Status + text := r.Status if text == "" { var ok bool - text, ok = statusText[resp.StatusCode] + text, ok = statusText[r.StatusCode] if !ok { - text = "status code " + strconv.Itoa(resp.StatusCode) + text = "status code " + strconv.Itoa(r.StatusCode) } } - io.WriteString(w, "HTTP/"+strconv.Itoa(resp.ProtoMajor)+".") - io.WriteString(w, strconv.Itoa(resp.ProtoMinor)+" ") - io.WriteString(w, strconv.Itoa(resp.StatusCode)+" "+text+"\r\n") + io.WriteString(w, "HTTP/"+strconv.Itoa(r.ProtoMajor)+".") + io.WriteString(w, strconv.Itoa(r.ProtoMinor)+" ") + io.WriteString(w, strconv.Itoa(r.StatusCode)+" "+text+"\r\n") // Process Body,ContentLength,Close,Trailer - tw, err := newTransferWriter(resp) + tw, err := newTransferWriter(r) if err != nil { return err } @@ -217,7 +217,7 @@ func (resp *Response) Write(w io.Writer) error { } // Rest of header - err = resp.Header.WriteSubset(w, respExcludeHeader) + err = r.Header.WriteSubset(w, respExcludeHeader) if err != nil { return err } diff --git a/libgo/go/net/http/serve_test.go b/libgo/go/net/http/serve_test.go index 147c216ec78..e2860c3edcf 100644 --- a/libgo/go/net/http/serve_test.go +++ b/libgo/go/net/http/serve_test.go @@ -504,8 +504,9 @@ func Test304Responses(t *testing.T) { } // TestHeadResponses verifies that responses to HEAD requests don't -// declare that they're chunking in their response headers and aren't -// allowed to produce output. +// declare that they're chunking in their response headers, aren't +// allowed to produce output, and don't set a Content-Type since +// the real type of the body data cannot be inferred. func TestHeadResponses(t *testing.T) { ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { _, err := w.Write([]byte("Ignored body")) @@ -527,6 +528,10 @@ func TestHeadResponses(t *testing.T) { if len(res.TransferEncoding) > 0 { t.Errorf("expected no TransferEncoding; got %v", res.TransferEncoding) } + ct := res.Header.Get("Content-Type") + if ct != "" { + t.Errorf("expected no Content-Type; got %s", ct) + } body, err := ioutil.ReadAll(res.Body) if err != nil { t.Error(err) diff --git a/libgo/go/net/http/server.go b/libgo/go/net/http/server.go index bad3bcb2896..288539ba576 100644 --- a/libgo/go/net/http/server.go +++ b/libgo/go/net/http/server.go @@ -341,7 +341,7 @@ func (w *response) WriteHeader(code int) { } } else { // If no content type, apply sniffing algorithm to body. - if w.header.Get("Content-Type") == "" { + if w.header.Get("Content-Type") == "" && w.req.Method != "HEAD" { w.needSniff = true } } @@ -1078,8 +1078,8 @@ func ListenAndServeTLS(addr string, certFile string, keyFile string, handler Han // of the server's certificate followed by the CA's certificate. // // If srv.Addr is blank, ":https" is used. -func (s *Server) ListenAndServeTLS(certFile, keyFile string) error { - addr := s.Addr +func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error { + addr := srv.Addr if addr == "" { addr = ":https" } @@ -1101,7 +1101,7 @@ func (s *Server) ListenAndServeTLS(certFile, keyFile string) error { } tlsListener := tls.NewListener(conn, config) - return s.Serve(tlsListener) + return srv.Serve(tlsListener) } // TimeoutHandler returns a Handler that runs h with the given time limit. diff --git a/libgo/go/net/http/transport.go b/libgo/go/net/http/transport.go index 4de070f01f1..693215edd4f 100644 --- a/libgo/go/net/http/transport.go +++ b/libgo/go/net/http/transport.go @@ -535,7 +535,9 @@ func (pc *persistConn) readLoop() { } resp, err := ReadResponse(pc.br, rc.req) - if err == nil { + if err != nil { + pc.close() + } else { hasBody := rc.req.Method != "HEAD" && resp.ContentLength != 0 if rc.addedGzip && hasBody && resp.Header.Get("Content-Encoding") == "gzip" { resp.Header.Del("Content-Encoding") diff --git a/libgo/go/net/http/transport_test.go b/libgo/go/net/http/transport_test.go index 321da52e278..caf81d6e46b 100644 --- a/libgo/go/net/http/transport_test.go +++ b/libgo/go/net/http/transport_test.go @@ -441,7 +441,11 @@ func TestRoundTripGzip(t *testing.T) { } if accept == "gzip" { rw.Header().Set("Content-Encoding", "gzip") - gz, _ := gzip.NewWriter(rw) + gz, err := gzip.NewWriter(rw) + if err != nil { + t.Errorf("gzip NewWriter: %v", err) + return + } gz.Write([]byte(responseBody)) gz.Close() } else { @@ -460,7 +464,11 @@ func TestRoundTripGzip(t *testing.T) { res, err := DefaultTransport.RoundTrip(req) var body []byte if test.compressed { - gzip, _ := gzip.NewReader(res.Body) + gzip, err := gzip.NewReader(res.Body) + if err != nil { + t.Errorf("%d. gzip NewReader: %v", i, err) + continue + } body, err = ioutil.ReadAll(gzip) res.Body.Close() } else { |