@@ -22,9 +22,9 @@ export default class httpClient {
22
22
23
23
let proxyUrl = null ;
24
24
try {
25
- // Handle URL with or without protocol
26
- const urlStr = SMARTUI_API_PROXY ?. startsWith ( 'http' ) ?
27
- SMARTUI_API_PROXY : `http://${ SMARTUI_API_PROXY } ` ;
25
+ // Handle URL with or without protocol
26
+ const urlStr = SMARTUI_API_PROXY ?. startsWith ( 'http' ) ?
27
+ SMARTUI_API_PROXY : `http://${ SMARTUI_API_PROXY } ` ;
28
28
proxyUrl = SMARTUI_API_PROXY ? new URL ( urlStr ) : null ;
29
29
} catch ( error ) {
30
30
console . error ( 'Invalid proxy URL:' , error ) ;
@@ -36,7 +36,7 @@ export default class httpClient {
36
36
port : proxyUrl . port ? Number ( proxyUrl . port ) : 80
37
37
} : false
38
38
} ;
39
-
39
+
40
40
if ( SMARTUI_API_SKIP_CERTIFICATES ) {
41
41
axiosConfig . httpsAgent = new https . Agent ( {
42
42
rejectUnauthorized : false
@@ -45,29 +45,63 @@ export default class httpClient {
45
45
46
46
this . axiosInstance = axios . create ( axiosConfig ) ;
47
47
48
-
48
+
49
49
this . axiosInstance . interceptors . request . use ( ( config ) => {
50
50
config . headers [ 'projectToken' ] = this . projectToken ;
51
51
config . headers [ 'projectName' ] = this . projectName ;
52
52
config . headers [ 'username' ] = this . username ;
53
53
config . headers [ 'accessKey' ] = this . accessKey ;
54
54
return config ;
55
55
} ) ;
56
+
57
+ // Add a request interceptor for retry logic
58
+ this . axiosInstance . interceptors . response . use (
59
+ ( response ) => response ,
60
+ async ( error ) => {
61
+ const { config } = error ;
62
+ if ( config && config . url === '/screenshot' && config . method === 'post' ) {
63
+ // Set default retry count and delay if not already defined
64
+ if ( ! config . retryCount ) {
65
+ config . retryCount = 0 ;
66
+ config . retry = 2 ;
67
+ config . retryDelay = 5000 ;
68
+ }
69
+
70
+ // Check if we should retry the request
71
+ if ( config . retryCount < config . retry ) {
72
+ config . retryCount += 1 ;
73
+ await new Promise ( resolve => setTimeout ( resolve , config . retryDelay ) ) ;
74
+ config . timeout = 30000 ;
75
+ return this . axiosInstance ( config ) ;
76
+ }
77
+
78
+ // If we've reached max retries, reject with the error
79
+ return Promise . reject ( error ) ;
80
+ }
81
+ }
82
+ ) ;
56
83
}
57
84
85
+
86
+
58
87
async request ( config : AxiosRequestConfig , log : Logger ) : Promise < Record < string , any > > {
59
88
log . debug ( `http request: ${ config . method } ${ config . url } ` ) ;
60
- if ( config && config . data && ! config . data . name ) {
89
+ if ( config && config . data && ! config . data . name ) {
61
90
log . debug ( config . data ) ;
62
91
}
63
92
return this . axiosInstance . request ( config )
64
93
. then ( resp => {
65
- log . debug ( `http response: ${ JSON . stringify ( {
66
- status : resp . status ,
67
- headers : resp . headers ,
68
- body : resp . data
69
- } ) } `)
70
- return resp . data ;
94
+ if ( resp ) {
95
+ log . debug ( `http response: ${ JSON . stringify ( {
96
+ status : resp . status ,
97
+ headers : resp . headers ,
98
+ body : resp . data
99
+ } ) } `)
100
+ return resp . data ;
101
+ } else {
102
+ log . debug ( `empty response: ${ JSON . stringify ( resp ) } ` )
103
+ return { } ;
104
+ }
71
105
} )
72
106
. catch ( error => {
73
107
if ( error . response ) {
@@ -107,7 +141,7 @@ export default class httpClient {
107
141
throw new Error ( 'Authentication failed, project token not received' ) ;
108
142
}
109
143
}
110
-
144
+
111
145
createBuild ( git : Git , config : any , log : Logger , buildName : string , isStartExec : boolean ) {
112
146
return this . request ( {
113
147
url : '/build' ,
@@ -128,7 +162,7 @@ export default class httpClient {
128
162
params : { buildId, baseline }
129
163
} , log ) ;
130
164
}
131
-
165
+
132
166
ping ( buildId : string , log : Logger ) {
133
167
return this . request ( {
134
168
url : '/build/ping' ,
@@ -138,10 +172,10 @@ export default class httpClient {
138
172
}
139
173
} , log ) ;
140
174
}
141
-
175
+
142
176
143
177
finalizeBuild ( buildId : string , totalSnapshots : number , log : Logger ) {
144
- let params : Record < string , string | number > = { buildId} ;
178
+ let params : Record < string , string | number > = { buildId } ;
145
179
if ( totalSnapshots > - 1 ) params . totalSnapshots = totalSnapshots ;
146
180
147
181
return this . request ( {
@@ -156,7 +190,7 @@ export default class httpClient {
156
190
url : `/builds/${ ctx . build . id } /snapshot` ,
157
191
method : 'POST' ,
158
192
headers : { 'Content-Type' : 'application/json' } ,
159
- data : {
193
+ data : {
160
194
snapshot,
161
195
test : {
162
196
type : ctx . testType ,
@@ -171,7 +205,7 @@ export default class httpClient {
171
205
url : `/build/${ ctx . build . id } /snapshot` ,
172
206
method : 'POST' ,
173
207
headers : { 'Content-Type' : 'application/json' } ,
174
- data : {
208
+ data : {
175
209
name : snapshot . name ,
176
210
url : snapshot . url ,
177
211
snapshotUuid : snapshotUuid ,
@@ -185,13 +219,13 @@ export default class httpClient {
185
219
}
186
220
187
221
uploadScreenshot (
188
- { id : buildId , name : buildName , baseline } : Build ,
189
- ssPath : string , ssName : string , browserName : string , viewport : string , log : Logger
222
+ { id : buildId , name : buildName , baseline } : Build ,
223
+ ssPath : string , ssName : string , browserName : string , viewport : string , log : Logger
190
224
) {
191
225
browserName = browserName === constants . SAFARI ? constants . WEBKIT : browserName ;
192
226
const file = fs . readFileSync ( ssPath ) ;
193
227
const form = new FormData ( ) ;
194
- form . append ( 'screenshot' , file , { filename : `${ ssName } .png` , contentType : 'image/png' } ) ;
228
+ form . append ( 'screenshot' , file , { filename : `${ ssName } .png` , contentType : 'image/png' } ) ;
195
229
form . append ( 'browser' , browserName ) ;
196
230
form . append ( 'viewport' , viewport ) ;
197
231
form . append ( 'buildId' , buildId ) ;
@@ -204,19 +238,20 @@ export default class httpClient {
204
238
method : 'POST' ,
205
239
headers : form . getHeaders ( ) ,
206
240
data : form ,
241
+ timeout : 30000
207
242
} )
208
- . then ( ( ) => {
209
- log . debug ( `${ ssName } for ${ browserName } ${ viewport } uploaded successfully` ) ;
210
- } )
211
- . catch ( error => {
212
- log . error ( `Unable to upload screenshot ${ JSON . stringify ( error ) } ` )
213
- if ( error && error . response && error . response . data && error . response . data . error ) {
214
- throw new Error ( error . response . data . error . message ) ;
215
- }
216
- if ( error ) {
217
- throw new Error ( JSON . stringify ( error ) ) ;
218
- }
219
- } )
243
+ . then ( ( ) => {
244
+ log . debug ( `${ ssName } for ${ browserName } ${ viewport } uploaded successfully` ) ;
245
+ } )
246
+ . catch ( error => {
247
+ log . error ( `Unable to upload screenshot ${ JSON . stringify ( error ) } ` )
248
+ if ( error && error . response && error . response . data && error . response . data . error ) {
249
+ throw new Error ( error . response . data . error . message ) ;
250
+ }
251
+ if ( error ) {
252
+ throw new Error ( JSON . stringify ( error ) ) ;
253
+ }
254
+ } )
220
255
}
221
256
222
257
checkUpdate ( log : Logger ) {
@@ -232,15 +267,15 @@ export default class httpClient {
232
267
}
233
268
234
269
getFigmaFilesAndImages ( figmaFileToken : string , figmaToken : String | undefined , queryParams : string , authToken : string , depth : number , markBaseline : boolean , buildName : string , log : Logger ) {
235
- const requestBody = {
236
- figma_file_token : figmaFileToken ,
237
- figma_token : figmaToken ,
238
- query_params : queryParams ,
239
- auth : authToken ,
240
- depth : depth ,
241
- mark_base_line : markBaseline ,
242
- build_name : buildName
243
- } ;
270
+ const requestBody = {
271
+ figma_file_token : figmaFileToken ,
272
+ figma_token : figmaToken ,
273
+ query_params : queryParams ,
274
+ auth : authToken ,
275
+ depth : depth ,
276
+ mark_base_line : markBaseline ,
277
+ build_name : buildName
278
+ } ;
244
279
245
280
return this . request ( {
246
281
url : "/uploadfigma" ,
@@ -297,34 +332,34 @@ export default class httpClient {
297
332
return this . request ( {
298
333
url : uploadURL ,
299
334
method : 'PUT' ,
300
- headers :{
335
+ headers : {
301
336
'Content-Type' : 'application/json' ,
302
337
} ,
303
338
data : snapshot ,
304
339
maxBodyLength : Infinity , // prevent axios from limiting the body size
305
340
maxContentLength : Infinity , // prevent axios from limiting the content size
306
341
} , ctx . log )
307
342
}
308
-
343
+
309
344
processWebFigma ( requestBody : any , log : Logger ) {
310
- return this . request ( {
311
- url : "figma-web/upload" ,
312
- method : "POST" ,
313
- headers : {
314
- "Content-Type" : "application/json" ,
315
- } ,
316
- data : JSON . stringify ( requestBody )
317
- } , log ) ;
318
- }
345
+ return this . request ( {
346
+ url : "figma-web/upload" ,
347
+ method : "POST" ,
348
+ headers : {
349
+ "Content-Type" : "application/json" ,
350
+ } ,
351
+ data : JSON . stringify ( requestBody )
352
+ } , log ) ;
353
+ }
319
354
320
355
fetchWebFigma ( buildId : any , log : Logger ) {
321
- return this . request ( {
322
- url : "figma-web/fetch" ,
323
- method : "GET" ,
324
- headers : {
325
- "Content-Type" : "application/json" ,
326
- } ,
327
- params : { buildId }
328
- } , log ) ;
329
- }
356
+ return this . request ( {
357
+ url : "figma-web/fetch" ,
358
+ method : "GET" ,
359
+ headers : {
360
+ "Content-Type" : "application/json" ,
361
+ } ,
362
+ params : { buildId }
363
+ } , log ) ;
364
+ }
330
365
}
0 commit comments