diff options
Diffstat (limited to 'libgo/go/net/http/httputil/dump.go')
-rw-r--r-- | libgo/go/net/http/httputil/dump.go | 63 |
1 files changed, 43 insertions, 20 deletions
diff --git a/libgo/go/net/http/httputil/dump.go b/libgo/go/net/http/httputil/dump.go index ca2d1cd..e22cc66 100644 --- a/libgo/go/net/http/httputil/dump.go +++ b/libgo/go/net/http/httputil/dump.go @@ -25,10 +25,10 @@ import ( func drainBody(b io.ReadCloser) (r1, r2 io.ReadCloser, err error) { var buf bytes.Buffer if _, err = buf.ReadFrom(b); err != nil { - return nil, nil, err + return nil, b, err } if err = b.Close(); err != nil { - return nil, nil, err + return nil, b, err } return ioutil.NopCloser(&buf), ioutil.NopCloser(bytes.NewReader(buf.Bytes())), nil } @@ -55,9 +55,9 @@ func (b neverEnding) Read(p []byte) (n int, err error) { return len(p), nil } -// DumpRequestOut is like DumpRequest but includes -// headers that the standard http.Transport adds, -// such as User-Agent. +// DumpRequestOut is like DumpRequest but for outgoing client requests. It +// includes any headers that the standard http.Transport adds, such as +// User-Agent. func DumpRequestOut(req *http.Request, body bool) ([]byte, error) { save := req.Body dummyBody := false @@ -175,13 +175,22 @@ func dumpAsReceived(req *http.Request, w io.Writer) error { return nil } -// DumpRequest returns the as-received wire representation of req, -// optionally including the request body, for debugging. -// DumpRequest is semantically a no-op, but in order to -// dump the body, it reads the body data into memory and -// changes req.Body to refer to the in-memory copy. +// DumpRequest returns the given request in its HTTP/1.x wire +// representation. It should only be used by servers to debug client +// requests. The returned representation is an approximation only; +// some details of the initial request are lost while parsing it into +// an http.Request. In particular, the order and case of header field +// names are lost. The order of values in multi-valued headers is kept +// intact. HTTP/2 requests are dumped in HTTP/1.x form, not in their +// original binary representations. +// +// If body is true, DumpRequest also returns the body. To do so, it +// consumes req.Body and then replaces it with a new io.ReadCloser +// that yields the same bytes. If DumpRequest returns an error, +// the state of req is undefined. +// // The documentation for http.Request.Write details which fields -// of req are used. +// of req are included in the dump. func DumpRequest(req *http.Request, body bool) (dump []byte, err error) { save := req.Body if !body || req.Body == nil { @@ -189,21 +198,35 @@ func DumpRequest(req *http.Request, body bool) (dump []byte, err error) { } else { save, req.Body, err = drainBody(req.Body) if err != nil { - return + return nil, err } } var b bytes.Buffer + // By default, print out the unmodified req.RequestURI, which + // is always set for incoming server requests. But because we + // previously used req.URL.RequestURI and the docs weren't + // always so clear about when to use DumpRequest vs + // DumpRequestOut, fall back to the old way if the caller + // provides a non-server Request. + reqURI := req.RequestURI + if reqURI == "" { + reqURI = req.URL.RequestURI() + } + fmt.Fprintf(&b, "%s %s HTTP/%d.%d\r\n", valueOrDefault(req.Method, "GET"), - req.URL.RequestURI(), req.ProtoMajor, req.ProtoMinor) + reqURI, req.ProtoMajor, req.ProtoMinor) - host := req.Host - if host == "" && req.URL != nil { - host = req.URL.Host - } - if host != "" { - fmt.Fprintf(&b, "Host: %s\r\n", host) + absRequestURI := strings.HasPrefix(req.RequestURI, "http://") || strings.HasPrefix(req.RequestURI, "https://") + if !absRequestURI { + host := req.Host + if host == "" && req.URL != nil { + host = req.URL.Host + } + if host != "" { + fmt.Fprintf(&b, "Host: %s\r\n", host) + } } chunked := len(req.TransferEncoding) > 0 && req.TransferEncoding[0] == "chunked" @@ -269,7 +292,7 @@ func DumpResponse(resp *http.Response, body bool) (dump []byte, err error) { } else { save, resp.Body, err = drainBody(resp.Body) if err != nil { - return + return nil, err } } err = resp.Write(&b) |