...
1
2
3
4
5 package main
6
7 import (
8 "bytes"
9 "fmt"
10 "io"
11 "net/http"
12 "os"
13 )
14
15 type logTransport struct {
16 rt http.RoundTripper
17 }
18
19 func (t *logTransport) RoundTrip(req *http.Request) (*http.Response, error) {
20 var buf bytes.Buffer
21
22 os.Stdout.Write([]byte("\n[request]\n"))
23 if req.Body != nil {
24 req.Body = io.NopCloser(&readButCopy{req.Body, &buf})
25 }
26 req.Write(os.Stdout)
27 if req.Body != nil {
28 req.Body = io.NopCloser(&buf)
29 }
30 os.Stdout.Write([]byte("\n[/request]\n"))
31
32 res, err := t.rt.RoundTrip(req)
33
34 fmt.Printf("[response]\n")
35 if err != nil {
36 fmt.Printf("ERROR: %v", err)
37 } else {
38 body := res.Body
39 res.Body = nil
40 res.Write(os.Stdout)
41 if body != nil {
42 res.Body = io.NopCloser(&echoAsRead{body})
43 }
44 }
45
46 return res, err
47 }
48
49 type echoAsRead struct {
50 src io.Reader
51 }
52
53 func (r *echoAsRead) Read(p []byte) (int, error) {
54 n, err := r.src.Read(p)
55 if n > 0 {
56 os.Stdout.Write(p[:n])
57 }
58 if err == io.EOF {
59 fmt.Printf("\n[/response]\n")
60 }
61 return n, err
62 }
63
64 type readButCopy struct {
65 src io.Reader
66 dst io.Writer
67 }
68
69 func (r *readButCopy) Read(p []byte) (int, error) {
70 n, err := r.src.Read(p)
71 if n > 0 {
72 r.dst.Write(p[:n])
73 }
74 return n, err
75 }
76
View as plain text