aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/net/http/httputil/dump.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/net/http/httputil/dump.go')
-rw-r--r--libgo/go/net/http/httputil/dump.go63
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)