You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

70 lines
1.6 KiB

package debug
import (
"fmt"
"io"
"net/http"
"net/http/httputil"
"os"
)
// DebugRequestTransport 会打印请求和响应信息, 方便调试.
type DebugRequestTransport struct {
RequestHeader bool
RequestBody bool // RequestHeader 为 true 时,这个选项才会生效
ResponseHeader bool
ResponseBody bool // ResponseHeader 为 true 时,这个选项才会生效
// debug 信息输出到 Writer 中, 默认是 os.Stderr
Writer io.Writer
Transport http.RoundTripper
}
// RoundTrip implements the RoundTripper interface.
func (t *DebugRequestTransport) RoundTrip(req *http.Request) (*http.Response, error) {
req = cloneRequest(req) // per RoundTrip contract
w := t.Writer
if w == nil {
w = os.Stderr
}
if t.RequestHeader {
a, _ := httputil.DumpRequest(req, t.RequestBody)
fmt.Fprintf(w, "%s\n\n", string(a))
}
resp, err := t.transport().RoundTrip(req)
if err != nil {
return resp, err
}
if t.ResponseHeader {
b, _ := httputil.DumpResponse(resp, t.ResponseBody)
fmt.Fprintf(w, "%s\n", string(b))
}
return resp, err
}
func (t *DebugRequestTransport) transport() http.RoundTripper {
if t.Transport != nil {
return t.Transport
}
return http.DefaultTransport
}
// cloneRequest returns a clone of the provided *http.Request. The clone is a
// shallow copy of the struct and its Header map.
func cloneRequest(r *http.Request) *http.Request {
// shallow copy of the struct
r2 := new(http.Request)
*r2 = *r
// deep copy of the Header
r2.Header = make(http.Header, len(r.Header))
for k, s := range r.Header {
r2.Header[k] = append([]string(nil), s...)
}
return r2
}