@@ -21,6 +21,7 @@ import (
2121 "context"
2222 "encoding/json"
2323 "errors"
24+ "fmt"
2425 "io"
2526 "math"
2627 "net/http"
@@ -106,12 +107,12 @@ func (s *SnykCodeHTTPClient) GetFilters(ctx context.Context) (
106107 span := s .instrumentor .StartSpan (ctx , method )
107108 defer s .instrumentor .Finish (span )
108109
109- responseBody , err := s .doCall (span .Context (), "GET" , "/filters" , nil )
110+ body , _ , err := s .doCall (span .Context (), "GET" , "/filters" , nil )
110111 if err != nil {
111112 return FiltersResponse {ConfigFiles : nil , Extensions : nil }, err
112113 }
113114
114- err = json .Unmarshal (responseBody , & filters )
115+ err = json .Unmarshal (body , & filters )
115116 if err != nil {
116117 return FiltersResponse {ConfigFiles : nil , Extensions : nil }, err
117118 }
@@ -134,53 +135,50 @@ func (s *SnykCodeHTTPClient) CreateBundle(
134135 return "" , nil , err
135136 }
136137
137- responseBody , err := s .doCall (span .Context (), "POST" , "/bundle" , requestBody )
138+ body , _ , err := s .doCall (span .Context (), "POST" , "/bundle" , requestBody )
138139 if err != nil {
139140 return "" , nil , err
140141 }
141142
142143 var bundle bundleResponse
143- err = json .Unmarshal (responseBody , & bundle )
144+ err = json .Unmarshal (body , & bundle )
144145 if err != nil {
145146 return "" , nil , err
146147 }
147148 s .c .Logger ().Debug ().Str ("method" , method ).Msg ("API: Create done" )
148149 return bundle .BundleHash , bundle .MissingFiles , nil
149150}
150151
151- func (s * SnykCodeHTTPClient ) doCall (ctx context.Context ,
152- method string ,
153- path string ,
154- requestBody []byte ,
155- ) (responseBody []byte , _ error ) {
152+ func (s * SnykCodeHTTPClient ) doCall (ctx context.Context , method string , path string , requestBody []byte ) ([]byte , int , error ) {
156153 span := s .instrumentor .StartSpan (ctx , "code.doCall" )
157154 defer s .instrumentor .Finish (span )
158155
159156 const retryCount = 3
157+
158+ // we only retry, if we get a retryable http status code
160159 for i := 0 ; i < retryCount ; i ++ {
161160 requestId , err := performance2 .GetTraceId (span .Context ())
162161 if err != nil {
163- return nil , errors .New ("Code request id was not provided. " + err .Error ())
162+ return nil , 0 , errors .New ("Code request id was not provided. " + err .Error ())
164163 }
165164
166165 bodyBuffer , err := s .encodeIfNeeded (method , requestBody )
167166 if err != nil {
168- return nil , err
167+ return nil , 0 , err
169168 }
170169
171170 c := config .CurrentConfig ()
172171 req , err := s .newRequest (c , method , path , bodyBuffer , requestId )
173172 if err != nil {
174- return nil , err
173+ return nil , 0 , err
175174 }
176175
177176 s .c .Logger ().Trace ().Str ("requestBody" , string (requestBody )).Str ("snyk-request-id" , requestId ).Msg ("SEND TO REMOTE" )
178177
179- response , body , err := s .httpCall (req ) //nolint:bodyclose // false positive
180- responseBody = body
178+ responseBody , httpStatusCode , err := s .httpCall (req )
181179
182- if response != nil && responseBody != nil {
183- s .c .Logger ().Trace ().Str ("response.Status" , response . Status ).
180+ if responseBody != nil {
181+ s .c .Logger ().Trace ().Int ("response.Status" , httpStatusCode ).
184182 Str ("responseBody" , string (responseBody )).
185183 Str ("snyk-request-id" , requestId ).
186184 Msg ("RECEIVED FROM REMOTE" )
@@ -191,51 +189,58 @@ func (s *SnykCodeHTTPClient) doCall(ctx context.Context,
191189 }
192190
193191 if err != nil {
194- return nil , err // no retries for errors
192+ return nil , 0 , err // no retries for errors
195193 }
196194
197- err = s .checkResponseCode (response )
195+ err = s .checkResponseCode (httpStatusCode )
198196 if err != nil {
199- if retryErrorCodes [response . StatusCode ] {
197+ if retryErrorCodes [httpStatusCode ] {
200198 s .c .Logger ().Debug ().Err (err ).Str ("method" , method ).Int ("attempts done" , i + 1 ).Msgf ("retrying" )
201199 if i < retryCount - 1 {
202200 time .Sleep (5 * time .Second )
203201 continue
204202 }
205203 // return the error on last try
206- return nil , err
204+ return nil , httpStatusCode , err
207205 }
208- return nil , err
206+ return nil , httpStatusCode , err
209207 }
210208 // no error, we can break the retry loop
211- break
209+ return responseBody , httpStatusCode , nil
212210 }
213- return responseBody , nil
211+ return nil , 0 , nil
214212}
215213
216- func (s * SnykCodeHTTPClient ) httpCall (req * http.Request ) (* http. Response , []byte , error ) {
214+ func (s * SnykCodeHTTPClient ) httpCall (req * http.Request ) ([]byte , int , error ) {
217215 method := "code.httpCall"
216+ logger := s .c .Logger ().With ().Str ("method" , method ).Logger ()
217+ statusCode := 0
218+
218219 response , err := s .client ().Do (req )
219220 if err != nil {
220- s .c .Logger ().Err (err ).Str ("method" , method ).Msgf ("got http error" )
221- s .errorReporter .CaptureError (err , codeClientObservability.ErrorReporterOptions {ErrorDiagnosticPath : req .RequestURI })
222- return nil , nil , err
221+ logger .Err (err ).Msgf ("got http error" )
222+ return nil , statusCode , err
223+ }
224+
225+ if response == nil {
226+ return nil , 0 , nil
223227 }
224228
225229 defer func () {
226- closeErr := response .Body .Close ()
227- if closeErr != nil {
228- s . c . Logger (). Err (closeErr ).Msg ("Couldn't close response body in call to Snyk Code " )
230+ bodyCloseErr := response .Body .Close ()
231+ if bodyCloseErr != nil {
232+ logger . Err (bodyCloseErr ).Msg ("failed to close response body" )
229233 }
230234 }()
231- responseBody , err := io .ReadAll (response .Body )
232235
233- if err != nil {
234- s .c .Logger ().Err (err ).Str ("method" , method ).Msgf ("error reading response body" )
235- s .errorReporter .CaptureError (err , codeClientObservability.ErrorReporterOptions {ErrorDiagnosticPath : req .RequestURI })
236- return nil , nil , err
236+ statusCode = response .StatusCode
237+ responseBody , readErr := io .ReadAll (response .Body )
238+
239+ if readErr != nil {
240+ logger .Err (readErr ).Msg ("failed to read response body" )
241+ return responseBody , statusCode , err
237242 }
238- return response , responseBody , nil
243+ return responseBody , statusCode , nil
239244}
240245
241246func (s * SnykCodeHTTPClient ) newRequest (
@@ -313,11 +318,16 @@ func (s *SnykCodeHTTPClient) ExtendBundle(
313318 removedFiles []string ,
314319) (string , []string , error ) {
315320 method := "code.ExtendBundle"
316- s .c .Logger ().Debug ().Str ("method" , method ).Msg ("API: Extending bundle for " + strconv .Itoa (len (files )) + " files" )
317- defer s .c .Logger ().Debug ().Str ("method" , method ).Msg ("API: Extend done" )
318-
319321 span := s .instrumentor .StartSpan (ctx , method )
320322 defer s .instrumentor .Finish (span )
323+ requestId , err := performance2 .GetTraceId (span .Context ())
324+ logger := s .c .Logger ().With ().Str ("method" , method ).Str ("requestId" , requestId ).Logger ()
325+ if err != nil {
326+ logger .Err (err ).Msg ("failed to get request id" )
327+ }
328+
329+ logger .Debug ().Msg ("API: Extending bundle for " + strconv .Itoa (len (files )) + " files" )
330+ defer logger .Debug ().Msg ("API: Extend done" )
321331
322332 requestBody , err := json .Marshal (extendBundleRequest {
323333 Files : files ,
@@ -327,7 +337,12 @@ func (s *SnykCodeHTTPClient) ExtendBundle(
327337 return "" , nil , err
328338 }
329339
330- responseBody , err := s .doCall (span .Context (), "PUT" , "/bundle/" + bundleHash , requestBody )
340+ responseBody , httpStatus , err := s .doCall (span .Context (), "PUT" , "/bundle/" + bundleHash , requestBody )
341+ if httpStatus == http .StatusBadRequest {
342+ logger .Err (err ).Msg ("got an HTTP 400 Bad Request, dumping bundle infos for analysis" )
343+ logger .Error ().Any ("fileHashes" , files ).Send ()
344+ logger .Error ().Any ("removedFiles" , removedFiles ).Send ()
345+ }
331346 if err != nil {
332347 return "" , nil , err
333348 }
@@ -364,7 +379,7 @@ func (s *SnykCodeHTTPClient) RunAnalysis(
364379 return nil , AnalysisStatus {}, err
365380 }
366381
367- responseBody , err := s .doCall (span .Context (), "POST" , "/analysis" , requestBody )
382+ responseBody , _ , err := s .doCall (span .Context (), "POST" , "/analysis" , requestBody )
368383 failed := AnalysisStatus {message : "FAILED" }
369384 if err != nil {
370385 s .c .Logger ().Err (err ).Str ("method" , method ).Str ("responseBody" , string (responseBody )).Msg ("error response from analysis" )
@@ -434,11 +449,11 @@ func (s *SnykCodeHTTPClient) analysisRequestBody(options *AnalysisOptions) ([]by
434449 return requestBody , err
435450}
436451
437- func (s * SnykCodeHTTPClient ) checkResponseCode (r * http. Response ) error {
438- if r . StatusCode >= 200 && r . StatusCode <= 299 {
452+ func (s * SnykCodeHTTPClient ) checkResponseCode (statusCode int ) error {
453+ if statusCode >= 200 && statusCode <= 400 {
439454 return nil
440455 }
441- return errors . New ("Unexpected response code: " + r . Status )
456+ return fmt . Errorf ("Unexpected response code: %d" , statusCode )
442457}
443458
444459type AutofixStatus struct {
@@ -508,7 +523,7 @@ func (s *SnykCodeHTTPClient) RunAutofix(ctx context.Context, options AutofixOpti
508523 return AutofixResponse {}, err
509524 }
510525
511- responseBody , err := s .doCall (span .Context (), "POST" , "/autofix/suggestions" , requestBody )
526+ responseBody , _ , err := s .doCall (span .Context (), "POST" , "/autofix/suggestions" , requestBody )
512527
513528 if err != nil {
514529 logger .Err (err ).Str ("responseBody" , string (responseBody )).Msg ("error response from autofix" )
@@ -578,7 +593,7 @@ func (s *SnykCodeHTTPClient) SubmitAutofixFeedback(ctx context.Context, fixId st
578593 return err
579594 }
580595
581- responseBody , err := s .doCall (span .Context (), "POST" , "/autofix/event" , requestBody )
596+ responseBody , _ , err := s .doCall (span .Context (), "POST" , "/autofix/event" , requestBody )
582597 if err != nil {
583598 s .c .Logger ().Err (err ).Str ("method" , method ).Str ("responseBody" , string (responseBody )).Msg ("error response for autofix feedback" )
584599 return err
0 commit comments