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  }