github.com/IBM-Cloud/bluemix-go@v0.0.0-20240314082800-4e02a69b84b2/http/transport.go (about) 1 package http 2 3 import ( 4 "net/http" 5 "net/http/httputil" 6 "strings" 7 "time" 8 9 "github.com/IBM-Cloud/bluemix-go/trace" 10 ) 11 12 // TraceLoggingTransport is a thin wrapper around Transport. It dumps HTTP 13 // request and response using trace logger, based on the "BLUEMIX_TRACE" 14 // environment variable. Sensitive user data will be replaced by text 15 // "[PRIVATE DATA HIDDEN]". 16 type TraceLoggingTransport struct { 17 rt http.RoundTripper 18 } 19 20 // NewTraceLoggingTransport returns a TraceLoggingTransport wrapping around 21 // the passed RoundTripper. If the passed RoundTripper is nil, HTTP 22 // DefaultTransport is used. 23 func NewTraceLoggingTransport(rt http.RoundTripper) *TraceLoggingTransport { 24 if rt == nil { 25 return &TraceLoggingTransport{ 26 rt: http.DefaultTransport, 27 } 28 } 29 return &TraceLoggingTransport{ 30 rt: rt, 31 } 32 } 33 34 //RoundTrip ... 35 func (r *TraceLoggingTransport) RoundTrip(req *http.Request) (resp *http.Response, err error) { 36 start := time.Now() 37 r.dumpRequest(req, start) 38 resp, err = r.rt.RoundTrip(req) 39 if err != nil { 40 return 41 } 42 r.dumpResponse(resp, start) 43 return 44 } 45 46 func (r *TraceLoggingTransport) dumpRequest(req *http.Request, start time.Time) { 47 shouldDisplayBody := !strings.Contains(req.Header.Get("Content-Type"), "multipart/form-data") 48 49 dumpedRequest, err := httputil.DumpRequest(req, shouldDisplayBody) 50 if err != nil { 51 trace.Logger.Printf("[ERROR] An error occurred while dumping request: %v", err) 52 return 53 } 54 55 trace.Logger.Printf("[DEBUG] %s [%s] %s", 56 "REQUEST:", 57 start.Format(time.RFC3339), 58 trace.Sanitize(string(dumpedRequest))) 59 60 if !shouldDisplayBody { 61 trace.Logger.Println("[DEBUG] [MULTIPART/FORM-DATA CONTENT HIDDEN]") 62 } 63 } 64 65 func (r *TraceLoggingTransport) dumpResponse(res *http.Response, start time.Time) { 66 end := time.Now() 67 68 shouldDisplayBody := !strings.Contains(res.Header.Get("Content-Type"), "application/zip") 69 dumpedResponse, err := httputil.DumpResponse(res, shouldDisplayBody) 70 if err != nil { 71 trace.Logger.Printf("[ERROR] An error occurred while dumping response: %v", err) 72 return 73 } 74 75 trace.Logger.Printf("[DEBUG] %s [%s] %s %.0fms %s", 76 "RESPONSE:", 77 end.Format(time.RFC3339), 78 "Elapsed:", 79 end.Sub(start).Seconds()*1000, 80 trace.Sanitize(string(dumpedResponse))) 81 }