package main import ( "bytes" "fmt" "io" "io/ioutil" "net/http" "os" ) type logTransport struct { rt http.RoundTripper } func (t *logTransport) RoundTrip(req *http.Request) (*http.Response, error) { var buf bytes.Buffer os.Stdout.Write([]byte("\n[request]\n")) if req.Body != nil { req.Body = ioutil.NopCloser(&readButCopy{req.Body, &buf}) } req.Write(os.Stdout) if req.Body != nil { req.Body = ioutil.NopCloser(&buf) } os.Stdout.Write([]byte("\n[/request]\n")) res, err := t.rt.RoundTrip(req) fmt.Printf("[response]\n") if err != nil { fmt.Printf("ERROR: %v", err) } else { body := res.Body res.Body = nil res.Write(os.Stdout) if body != nil { res.Body = ioutil.NopCloser(&echoAsRead{body}) } } return res, err } type echoAsRead struct { src io.Reader } func (r *echoAsRead) Read(p []byte) (int, error) { n, err := r.src.Read(p) if n > 0 { os.Stdout.Write(p[:n]) } if err == io.EOF { fmt.Printf("\n[/response]\n") } return n, err } type readButCopy struct { src io.Reader dst io.Writer } func (r *readButCopy) Read(p []byte) (int, error) { n, err := r.src.Read(p) if n > 0 { r.dst.Write(p[:n]) } return n, err }