github.com/anthropics/anthropic-sdk-go@v1.70.1/option/middleware.go (about) 1 // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 3 package option 4 5 import ( 6 "log" 7 "net/http" 8 "net/http/httputil" 9 ) 10 11 // sensitiveLogHeaders are redacted before request and response content is 12 // written to the debug logger. 13 var sensitiveLogHeaders = []string{"authorization", "api-key", "x-api-key", "cookie", "set-cookie"} 14 15 // WithDebugLog logs the HTTP request and response content. 16 // If the logger parameter is nil, it uses the default logger. 17 // 18 // WithDebugLog is for debugging and development purposes only. 19 // It should not be used in production code. The behavior and interface 20 // of WithDebugLog is not guaranteed to be stable. 21 func WithDebugLog(logger *log.Logger) RequestOption { 22 return WithMiddleware(func(req *http.Request, nxt MiddlewareNext) (*http.Response, error) { 23 if logger == nil { 24 logger = log.Default() 25 } 26 27 if reqBytes, err := dumpRedactedRequest(req); err == nil { 28 logger.Printf("Request Content:\n%s\n", reqBytes) 29 } 30 31 resp, err := nxt(req) 32 if err != nil { 33 return resp, err 34 } 35 36 if respBytes, err := dumpRedactedResponse(resp); err == nil { 37 logger.Printf("Response Content:\n%s\n", respBytes) 38 } 39 40 return resp, err 41 }) 42 } 43 44 // dumpRedactedRequest dumps req with sensitive headers replaced. The 45 // original headers are restored via defer so a panic in DumpRequest cannot 46 // leak the placeholder map into the live request sent downstream. 47 func dumpRedactedRequest(req *http.Request) ([]byte, error) { 48 origHeaders := req.Header 49 req.Header = redactDebugHeaders(origHeaders) 50 defer func() { req.Header = origHeaders }() 51 return httputil.DumpRequest(req, true) 52 } 53 54 func dumpRedactedResponse(resp *http.Response) ([]byte, error) { 55 origHeaders := resp.Header 56 resp.Header = redactDebugHeaders(origHeaders) 57 defer func() { resp.Header = origHeaders }() 58 return httputil.DumpResponse(resp, true) 59 } 60 61 func redactDebugHeaders(headers http.Header) http.Header { 62 var redacted http.Header 63 for _, name := range sensitiveLogHeaders { 64 values := headers.Values(name) 65 if len(values) == 0 { 66 continue 67 } 68 if redacted == nil { 69 redacted = headers.Clone() 70 } 71 redacted.Del(name) 72 for range values { 73 redacted.Add(name, "***") 74 } 75 } 76 if redacted == nil { 77 return headers 78 } 79 return redacted 80 }