summaryrefslogtreecommitdiff
path: root/libgo/go/net/http
diff options
context:
space:
mode:
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2012-02-09 08:19:58 +0000
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2012-02-09 08:19:58 +0000
commit2da6f72bb78de6e6ca3d387d970cb21bf36684be (patch)
tree7ca86535c5a6b99d4cc432ba5cfddabc5ee4ea16 /libgo/go/net/http
parent98ea39f2b59cc0a4a0a32b095e8f0faa84fd7882 (diff)
downloadgcc-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.go2
-rw-r--r--libgo/go/net/http/client.go12
-rw-r--r--libgo/go/net/http/fcgi/fcgi.go2
-rw-r--r--libgo/go/net/http/fs_test.go2
-rw-r--r--libgo/go/net/http/httputil/dump.go55
-rw-r--r--libgo/go/net/http/httputil/persist.go4
-rw-r--r--libgo/go/net/http/httputil/reverseproxy.go7
-rw-r--r--libgo/go/net/http/httputil/reverseproxy_test.go38
-rw-r--r--libgo/go/net/http/request.go16
-rw-r--r--libgo/go/net/http/response.go24
-rw-r--r--libgo/go/net/http/serve_test.go9
-rw-r--r--libgo/go/net/http/server.go8
-rw-r--r--libgo/go/net/http/transport.go4
-rw-r--r--libgo/go/net/http/transport_test.go12
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 {