github.com/qiniu/go-sdk/v7@v7.27.0/internal/clientv2/interceptor_debug.go (about) 1 package clientv2 2 3 import ( 4 "crypto/tls" 5 "fmt" 6 "net/http" 7 "net/http/httptrace" 8 "net/http/httputil" 9 10 clientV1 "github.com/qiniu/go-sdk/v7/client" 11 "github.com/qiniu/go-sdk/v7/conf" 12 "github.com/qiniu/go-sdk/v7/internal/log" 13 ) 14 15 type DebugLevel int 16 17 const ( 18 DebugLevelPrintNone DebugLevel = 0 19 DebugLevelPrintNormal DebugLevel = 1 20 DebugLevelPrintDetail DebugLevel = 2 21 ) 22 23 var ( 24 printRequestTrace = false 25 printRequestLevel *DebugLevel = nil 26 printResponseLevel *DebugLevel = nil 27 ) 28 29 func PrintRequestTrace(isPrint bool) { 30 printRequestTrace = isPrint 31 } 32 33 func IsPrintRequestTrace() bool { 34 return printRequestTrace 35 } 36 37 func PrintRequest(level DebugLevel) { 38 printRequestLevel = &level 39 } 40 41 func IsPrintRequest() bool { 42 if printRequestLevel != nil { 43 return *printRequestLevel == DebugLevelPrintNormal || *printRequestLevel == DebugLevelPrintDetail 44 } 45 return clientV1.DebugMode 46 } 47 48 func IsPrintRequestBody() bool { 49 if printRequestLevel != nil { 50 return *printRequestLevel == DebugLevelPrintDetail 51 } 52 return clientV1.DeepDebugInfo 53 } 54 55 func PrintResponse(level DebugLevel) { 56 printResponseLevel = &level 57 } 58 59 func IsPrintResponse() bool { 60 if printResponseLevel != nil { 61 return *printResponseLevel == DebugLevelPrintNormal || *printResponseLevel == DebugLevelPrintDetail 62 } 63 return clientV1.DebugMode 64 } 65 66 func IsPrintResponseBody() bool { 67 if printResponseLevel != nil { 68 return *printResponseLevel == DebugLevelPrintDetail 69 } 70 return clientV1.DeepDebugInfo 71 } 72 73 type debugInterceptor struct{} 74 75 func newDebugInterceptor() Interceptor { 76 return &debugInterceptor{} 77 } 78 79 func (interceptor *debugInterceptor) Priority() InterceptorPriority { 80 return InterceptorPriorityDebug 81 } 82 83 func (interceptor *debugInterceptor) Intercept(req *http.Request, handler Handler) (*http.Response, error) { 84 if interceptor == nil { 85 return handler(req) 86 } 87 88 label := interceptor.requestLabel(req) 89 90 if e := interceptor.printRequest(label, req); e != nil { 91 return nil, e 92 } 93 94 req = interceptor.printRequestTrace(label, req) 95 96 resp, err := handler(req) 97 98 if e := interceptor.printResponse(label, resp); e != nil { 99 return nil, e 100 } 101 102 return resp, err 103 } 104 105 func (interceptor *debugInterceptor) requestLabel(req *http.Request) string { 106 if req == nil || req.URL == nil { 107 return "" 108 } 109 return fmt.Sprintf("Url:%s", req.URL.String()) 110 } 111 112 func (interceptor *debugInterceptor) printRequest(label string, req *http.Request) error { 113 if req == nil { 114 return nil 115 } 116 117 printReq := IsPrintRequest() 118 if !printReq { 119 return nil 120 } 121 122 info := label + " request:\n" 123 124 var ( 125 hasBody = IsPrintRequestBody() 126 contentType = req.Header.Get("Content-Type") 127 ) 128 if contentType != conf.CONTENT_TYPE_JSON && contentType != conf.CONTENT_TYPE_FORM { 129 hasBody = false 130 } 131 132 d, dErr := httputil.DumpRequest(req, hasBody) 133 if dErr != nil { 134 return dErr 135 } 136 info += string(d) + "\n" 137 138 log.Debug(info) 139 return nil 140 } 141 142 func (interceptor *debugInterceptor) printRequestTrace(label string, req *http.Request) *http.Request { 143 if !IsPrintRequestTrace() || req == nil { 144 return req 145 } 146 147 label += "\n" 148 trace := &httptrace.ClientTrace{ 149 GetConn: func(hostPort string) { 150 log.Debug(label + fmt.Sprintf("GetConn, %s \n", hostPort)) 151 }, 152 GotConn: func(connInfo httptrace.GotConnInfo) { 153 remoteAddr := connInfo.Conn.RemoteAddr() 154 log.Debug(label + fmt.Sprintf("GotConn, Network:%s RemoteAddr:%s \n", remoteAddr.Network(), remoteAddr.String())) 155 }, 156 PutIdleConn: func(err error) { 157 log.Debug(label + fmt.Sprintf("PutIdleConn, err:%v \n", err)) 158 }, 159 GotFirstResponseByte: func() { 160 log.Debug(label + "GotFirstResponseByte \n") 161 }, 162 Got100Continue: func() { 163 log.Debug(label + "Got100Continue \n") 164 }, 165 DNSStart: func(info httptrace.DNSStartInfo) { 166 log.Debug(label + fmt.Sprintf("DNSStart, host:%s \n", info.Host)) 167 }, 168 DNSDone: func(info httptrace.DNSDoneInfo) { 169 log.Debug(label + fmt.Sprintf("DNSDone, addr:%+v \n", info.Addrs)) 170 }, 171 ConnectStart: func(network, addr string) { 172 log.Debug(label + fmt.Sprintf("ConnectStart, network:%+v ip:%s \n", network, addr)) 173 }, 174 ConnectDone: func(network, addr string, err error) { 175 log.Debug(label + fmt.Sprintf("ConnectDone, network:%s ip:%s err:%v \n", network, addr, err)) 176 }, 177 TLSHandshakeStart: func() { 178 log.Debug(label + "TLSHandshakeStart \n") 179 }, 180 TLSHandshakeDone: func(state tls.ConnectionState, err error) { 181 log.Debug(label + fmt.Sprintf("TLSHandshakeDone, state:%+v err:%s \n", state, err)) 182 }, 183 // go1.10 不支持 184 //WroteHeaderField: func(key string, value []string) { 185 // log.Debug(label + fmt.Sprintf("WroteHeaderField, key:%s value:%s \n", key, value)) 186 //}, 187 WroteHeaders: func() { 188 log.Debug(label + "WroteHeaders \n") 189 }, 190 Wait100Continue: func() { 191 log.Debug(label + "Wait100Continue \n") 192 }, 193 WroteRequest: func(info httptrace.WroteRequestInfo) { 194 log.Debug(label + fmt.Sprintf("WroteRequest, err:%v \n", info.Err)) 195 }, 196 } 197 return req.WithContext(httptrace.WithClientTrace(req.Context(), trace)) 198 } 199 200 func (interceptor *debugInterceptor) printResponse(label string, resp *http.Response) error { 201 if resp == nil { 202 return nil 203 } 204 205 printResp := IsPrintResponse() 206 if !printResp { 207 return nil 208 } 209 210 info := label + " response:\n" 211 212 hasBody := IsPrintResponseBody() 213 switch { 214 case 215 resp.Header.Get("Content-Type") == "application/octet-stream", 216 resp.ContentLength <= 0 || resp.ContentLength > 1024*1024: 217 hasBody = false 218 } 219 220 d, dErr := httputil.DumpResponse(resp, hasBody) 221 if dErr != nil { 222 return dErr 223 } 224 info += string(d) + "\n" 225 226 log.Debug(info) 227 return nil 228 }