@kontent-ai/core-sdk 10.12.5 → 10.12.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.npmignore +14 -14
- package/LICENSE.md +9 -9
- package/README.md +30 -30
- package/dist/cjs/http/http.functions.js +109 -23
- package/dist/cjs/http/http.functions.js.map +1 -1
- package/dist/cjs/sdk-info.generated.js +1 -1
- package/dist/es6/http/http.functions.js +109 -23
- package/dist/es6/http/http.functions.js.map +1 -1
- package/dist/es6/sdk-info.generated.js +1 -1
- package/dist/esnext/http/http.functions.js +109 -23
- package/dist/esnext/http/http.functions.js.map +1 -1
- package/dist/esnext/sdk-info.generated.js +1 -1
- package/dist/umd/kontent-core.umd.js +646 -147
- package/dist/umd/kontent-core.umd.js.map +1 -1
- package/dist/umd/kontent-core.umd.min.js +1 -1
- package/dist/umd/kontent-core.umd.min.js.LICENSE.txt +1 -1
- package/dist/umd/kontent-core.umd.min.js.map +1 -1
- package/dist/umd/report.json +1 -1
- package/dist/umd/report.min.json +1 -1
- package/dist/umd/stats.json +441 -441
- package/dist/umd/stats.min.json +449 -449
- package/lib/helpers/header.helper.ts +23 -23
- package/lib/helpers/headers-helper.ts +15 -15
- package/lib/helpers/index.ts +4 -4
- package/lib/helpers/retry-helper.ts +204 -204
- package/lib/helpers/url.helper.ts +26 -26
- package/lib/http/http.debugger.ts +21 -21
- package/lib/http/http.functions.ts +416 -314
- package/lib/http/http.models.ts +83 -83
- package/lib/http/http.service.ts +91 -91
- package/lib/http/ihttp.service.ts +20 -20
- package/lib/http/index.ts +6 -6
- package/lib/http/test-http.service.ts +70 -70
- package/lib/index.ts +4 -4
- package/lib/models/index.ts +3 -3
- package/lib/models/isdk-info.ts +15 -15
- package/lib/models/parameters.ts +25 -25
- package/lib/models/url.models.ts +3 -3
- package/lib/sdk-info.generated.ts +1 -1
- package/package.json +93 -93
|
@@ -1,314 +1,416 @@
|
|
|
1
|
-
import axios, { AxiosInstance, Canceler, CancelToken } from 'axios';
|
|
2
|
-
import { extractHeadersFromAxiosResponse } from '../helpers/headers-helper';
|
|
3
|
-
|
|
4
|
-
import { httpDebugger } from './http.debugger';
|
|
5
|
-
import {
|
|
6
|
-
IHttpCancelRequestToken,
|
|
7
|
-
IHeader,
|
|
8
|
-
IHttpDeleteQueryCall,
|
|
9
|
-
IHttpGetQueryCall,
|
|
10
|
-
IHttpPatchQueryCall,
|
|
11
|
-
IHttpPostQueryCall,
|
|
12
|
-
IHttpPutQueryCall,
|
|
13
|
-
IHttpQueryOptions,
|
|
14
|
-
IResponse,
|
|
15
|
-
IRetryStrategyOptions
|
|
16
|
-
} from './http.models';
|
|
17
|
-
import { retryHelper } from '../helpers/retry-helper';
|
|
18
|
-
|
|
19
|
-
export interface IHttpFunctionsConfig {
|
|
20
|
-
logErrorsToConsole: boolean;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export async function getWithRetryAsync<TRawData>(
|
|
24
|
-
instance: AxiosInstance,
|
|
25
|
-
call: IHttpGetQueryCall,
|
|
26
|
-
functionsConfig: IHttpFunctionsConfig,
|
|
27
|
-
options?: IHttpQueryOptions<CancelToken>
|
|
28
|
-
): Promise<IResponse<TRawData>> {
|
|
29
|
-
const retryStrategyOptions = options?.retryStrategy ?? retryHelper.defaultRetryStrategy;
|
|
30
|
-
|
|
31
|
-
return await runWithRetryAsync<TRawData>({
|
|
32
|
-
retryAttempt: 0,
|
|
33
|
-
url: call.url,
|
|
34
|
-
retryStrategy: retryStrategyOptions,
|
|
35
|
-
functionsConfig: functionsConfig,
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
cancel
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
1
|
+
import axios, { AxiosInstance, Canceler, CancelToken } from 'axios';
|
|
2
|
+
import { extractHeadersFromAxiosResponse } from '../helpers/headers-helper';
|
|
3
|
+
|
|
4
|
+
import { httpDebugger } from './http.debugger';
|
|
5
|
+
import {
|
|
6
|
+
IHttpCancelRequestToken,
|
|
7
|
+
IHeader,
|
|
8
|
+
IHttpDeleteQueryCall,
|
|
9
|
+
IHttpGetQueryCall,
|
|
10
|
+
IHttpPatchQueryCall,
|
|
11
|
+
IHttpPostQueryCall,
|
|
12
|
+
IHttpPutQueryCall,
|
|
13
|
+
IHttpQueryOptions,
|
|
14
|
+
IResponse,
|
|
15
|
+
IRetryStrategyOptions
|
|
16
|
+
} from './http.models';
|
|
17
|
+
import { retryHelper } from '../helpers/retry-helper';
|
|
18
|
+
|
|
19
|
+
export interface IHttpFunctionsConfig {
|
|
20
|
+
logErrorsToConsole: boolean;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export async function getWithRetryAsync<TRawData>(
|
|
24
|
+
instance: AxiosInstance,
|
|
25
|
+
call: IHttpGetQueryCall,
|
|
26
|
+
functionsConfig: IHttpFunctionsConfig,
|
|
27
|
+
options?: IHttpQueryOptions<CancelToken>
|
|
28
|
+
): Promise<IResponse<TRawData>> {
|
|
29
|
+
const retryStrategyOptions = options?.retryStrategy ?? retryHelper.defaultRetryStrategy;
|
|
30
|
+
|
|
31
|
+
return await runWithRetryAsync<TRawData>({
|
|
32
|
+
retryAttempt: 0,
|
|
33
|
+
url: call.url,
|
|
34
|
+
retryStrategy: retryStrategyOptions,
|
|
35
|
+
functionsConfig: functionsConfig,
|
|
36
|
+
headers: options?.headers ?? [],
|
|
37
|
+
call: async (retryAttempt) => {
|
|
38
|
+
httpDebugger.debugStartHttpRequest();
|
|
39
|
+
|
|
40
|
+
const axiosResponse = await instance.get<TRawData>(call.url, {
|
|
41
|
+
headers: getHeadersJson(options?.headers ?? [], false),
|
|
42
|
+
responseType: options?.responseType,
|
|
43
|
+
cancelToken: options?.cancelToken?.token
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
const response: IResponse<TRawData> = {
|
|
47
|
+
data: axiosResponse.data,
|
|
48
|
+
rawResponse: axiosResponse,
|
|
49
|
+
headers: extractHeadersFromAxiosResponse(axiosResponse),
|
|
50
|
+
status: axiosResponse.status,
|
|
51
|
+
retryStrategy: {
|
|
52
|
+
options: retryStrategyOptions,
|
|
53
|
+
retryAttempts: retryAttempt
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
httpDebugger.debugSuccessHttpRequest();
|
|
58
|
+
return response;
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export async function postWithRetryAsync<TRawData>(
|
|
64
|
+
instance: AxiosInstance,
|
|
65
|
+
call: IHttpPostQueryCall,
|
|
66
|
+
functionsConfig: IHttpFunctionsConfig,
|
|
67
|
+
options?: IHttpQueryOptions<CancelToken>
|
|
68
|
+
): Promise<IResponse<TRawData>> {
|
|
69
|
+
const retryStrategyOptions = options?.retryStrategy ?? retryHelper.defaultRetryStrategy;
|
|
70
|
+
|
|
71
|
+
return await runWithRetryAsync<TRawData>({
|
|
72
|
+
retryAttempt: 0,
|
|
73
|
+
url: call.url,
|
|
74
|
+
retryStrategy: retryStrategyOptions,
|
|
75
|
+
functionsConfig: functionsConfig,
|
|
76
|
+
headers: options?.headers ?? [],
|
|
77
|
+
call: async (retryAttempt) => {
|
|
78
|
+
httpDebugger.debugStartHttpRequest();
|
|
79
|
+
|
|
80
|
+
const axiosResponse = await instance.post<TRawData>(call.url, call.body, {
|
|
81
|
+
headers: getHeadersJson(options?.headers ?? [], false),
|
|
82
|
+
responseType: options?.responseType,
|
|
83
|
+
// required for uploading large files
|
|
84
|
+
// https://github.com/axios/axios/issues/1362
|
|
85
|
+
maxContentLength: 'Infinity' as any,
|
|
86
|
+
maxBodyLength: 'Infinity' as any,
|
|
87
|
+
cancelToken: options?.cancelToken?.token
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
const response: IResponse<TRawData> = {
|
|
91
|
+
data: axiosResponse.data,
|
|
92
|
+
rawResponse: axiosResponse,
|
|
93
|
+
headers: extractHeadersFromAxiosResponse(axiosResponse),
|
|
94
|
+
status: axiosResponse.status,
|
|
95
|
+
retryStrategy: {
|
|
96
|
+
options: retryStrategyOptions,
|
|
97
|
+
retryAttempts: retryAttempt
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
httpDebugger.debugSuccessHttpRequest();
|
|
102
|
+
return response;
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export async function putWithRetryAsync<TRawData>(
|
|
108
|
+
instance: AxiosInstance,
|
|
109
|
+
call: IHttpPutQueryCall,
|
|
110
|
+
functionsConfig: IHttpFunctionsConfig,
|
|
111
|
+
options?: IHttpQueryOptions<CancelToken>
|
|
112
|
+
): Promise<IResponse<TRawData>> {
|
|
113
|
+
const retryStrategyOptions = options?.retryStrategy ?? retryHelper.defaultRetryStrategy;
|
|
114
|
+
|
|
115
|
+
return await runWithRetryAsync<TRawData>({
|
|
116
|
+
retryAttempt: 0,
|
|
117
|
+
url: call.url,
|
|
118
|
+
retryStrategy: retryStrategyOptions,
|
|
119
|
+
functionsConfig: functionsConfig,
|
|
120
|
+
headers: options?.headers ?? [],
|
|
121
|
+
call: async (retryAttempt) => {
|
|
122
|
+
httpDebugger.debugStartHttpRequest();
|
|
123
|
+
|
|
124
|
+
const axiosResponse = await instance.put<TRawData>(call.url, call.body, {
|
|
125
|
+
headers: getHeadersJson(options?.headers ?? [], false),
|
|
126
|
+
responseType: options?.responseType,
|
|
127
|
+
// required for uploading large files
|
|
128
|
+
// https://github.com/axios/axios/issues/1362
|
|
129
|
+
maxContentLength: 'Infinity' as any,
|
|
130
|
+
maxBodyLength: 'Infinity' as any,
|
|
131
|
+
cancelToken: options?.cancelToken?.token
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
const response: IResponse<TRawData> = {
|
|
135
|
+
data: axiosResponse.data,
|
|
136
|
+
rawResponse: axiosResponse,
|
|
137
|
+
headers: extractHeadersFromAxiosResponse(axiosResponse),
|
|
138
|
+
status: axiosResponse.status,
|
|
139
|
+
retryStrategy: {
|
|
140
|
+
options: retryStrategyOptions,
|
|
141
|
+
retryAttempts: retryAttempt
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
httpDebugger.debugSuccessHttpRequest();
|
|
146
|
+
return response;
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export async function patchWithRetryAsync<TRawData>(
|
|
152
|
+
instance: AxiosInstance,
|
|
153
|
+
call: IHttpPatchQueryCall,
|
|
154
|
+
functionsConfig: IHttpFunctionsConfig,
|
|
155
|
+
options?: IHttpQueryOptions<CancelToken>
|
|
156
|
+
): Promise<IResponse<TRawData>> {
|
|
157
|
+
const retryStrategyOptions = options?.retryStrategy ?? retryHelper.defaultRetryStrategy;
|
|
158
|
+
|
|
159
|
+
return await runWithRetryAsync<TRawData>({
|
|
160
|
+
retryAttempt: 0,
|
|
161
|
+
url: call.url,
|
|
162
|
+
retryStrategy: retryStrategyOptions,
|
|
163
|
+
functionsConfig: functionsConfig,
|
|
164
|
+
headers: options?.headers ?? [],
|
|
165
|
+
call: async (retryAttempt) => {
|
|
166
|
+
httpDebugger.debugStartHttpRequest();
|
|
167
|
+
|
|
168
|
+
const axiosResponse = await instance.patch<TRawData>(call.url, call.body, {
|
|
169
|
+
headers: getHeadersJson(options?.headers ?? [], false),
|
|
170
|
+
responseType: options?.responseType,
|
|
171
|
+
// required for uploading large files
|
|
172
|
+
// https://github.com/axios/axios/issues/1362
|
|
173
|
+
maxContentLength: 'Infinity' as any,
|
|
174
|
+
maxBodyLength: 'Infinity' as any,
|
|
175
|
+
cancelToken: options?.cancelToken?.token
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
const response: IResponse<TRawData> = {
|
|
179
|
+
data: axiosResponse.data,
|
|
180
|
+
rawResponse: axiosResponse,
|
|
181
|
+
headers: extractHeadersFromAxiosResponse(axiosResponse),
|
|
182
|
+
status: axiosResponse.status,
|
|
183
|
+
retryStrategy: {
|
|
184
|
+
options: retryStrategyOptions,
|
|
185
|
+
retryAttempts: retryAttempt
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
httpDebugger.debugSuccessHttpRequest();
|
|
190
|
+
return response;
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export async function deleteWithRetryAsync<TRawData>(
|
|
196
|
+
instance: AxiosInstance,
|
|
197
|
+
call: IHttpDeleteQueryCall,
|
|
198
|
+
functionsConfig: IHttpFunctionsConfig,
|
|
199
|
+
options?: IHttpQueryOptions<CancelToken>
|
|
200
|
+
): Promise<IResponse<TRawData>> {
|
|
201
|
+
const retryStrategyOptions = options?.retryStrategy ?? retryHelper.defaultRetryStrategy;
|
|
202
|
+
|
|
203
|
+
return await runWithRetryAsync<TRawData>({
|
|
204
|
+
retryAttempt: 0,
|
|
205
|
+
url: call.url,
|
|
206
|
+
retryStrategy: retryStrategyOptions,
|
|
207
|
+
functionsConfig: functionsConfig,
|
|
208
|
+
headers: options?.headers ?? [],
|
|
209
|
+
call: async (retryAttempt) => {
|
|
210
|
+
httpDebugger.debugStartHttpRequest();
|
|
211
|
+
|
|
212
|
+
const axiosResponse = await instance.delete<TRawData>(call.url, {
|
|
213
|
+
headers: getHeadersJson(options?.headers ?? [], false),
|
|
214
|
+
responseType: options?.responseType,
|
|
215
|
+
// required for uploading large files
|
|
216
|
+
// https://github.com/axios/axios/issues/1362
|
|
217
|
+
maxContentLength: 'Infinity' as any,
|
|
218
|
+
maxBodyLength: 'Infinity' as any,
|
|
219
|
+
cancelToken: options?.cancelToken?.token
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
const response: IResponse<TRawData> = {
|
|
223
|
+
data: axiosResponse.data,
|
|
224
|
+
rawResponse: axiosResponse,
|
|
225
|
+
headers: extractHeadersFromAxiosResponse(axiosResponse),
|
|
226
|
+
status: axiosResponse.status,
|
|
227
|
+
retryStrategy: {
|
|
228
|
+
options: retryStrategyOptions,
|
|
229
|
+
retryAttempts: retryAttempt
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
httpDebugger.debugSuccessHttpRequest();
|
|
234
|
+
return response;
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export function createCancelToken(): IHttpCancelRequestToken<CancelToken> {
|
|
240
|
+
let canceler: Canceler;
|
|
241
|
+
|
|
242
|
+
const token = new axios.CancelToken((c) => {
|
|
243
|
+
// An executor function receives a cancel function as a parameter
|
|
244
|
+
canceler = c;
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
return {
|
|
248
|
+
cancel: (cancelMessage) =>
|
|
249
|
+
canceler(`${retryHelper.requestCancelledMessagePrefix}: ${cancelMessage ?? 'User cancel'}`),
|
|
250
|
+
token: token
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
async function runWithRetryAsync<TRawData>(data: {
|
|
255
|
+
url: string;
|
|
256
|
+
retryAttempt: number;
|
|
257
|
+
call: (retryAttempt: number) => Promise<IResponse<TRawData>>;
|
|
258
|
+
retryStrategy: IRetryStrategyOptions;
|
|
259
|
+
functionsConfig: IHttpFunctionsConfig;
|
|
260
|
+
headers: IHeader[];
|
|
261
|
+
}): Promise<IResponse<TRawData>> {
|
|
262
|
+
try {
|
|
263
|
+
return await data.call(data.retryAttempt);
|
|
264
|
+
} catch (error) {
|
|
265
|
+
const retryResult = retryHelper.getRetryErrorResult({
|
|
266
|
+
error: error,
|
|
267
|
+
retryAttempt: data.retryAttempt,
|
|
268
|
+
retryStrategy: data.retryStrategy
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
if (retryResult.canRetry) {
|
|
272
|
+
httpDebugger.debugRetryHttpRequest();
|
|
273
|
+
|
|
274
|
+
// wait time before retrying
|
|
275
|
+
await new Promise((resolve) => setTimeout(resolve, retryResult.retryInMs));
|
|
276
|
+
|
|
277
|
+
if (data.functionsConfig.logErrorsToConsole) {
|
|
278
|
+
console.warn(
|
|
279
|
+
`Retry attempt '${data.retryAttempt + 1}' from a maximum of '${
|
|
280
|
+
retryResult.maxRetries
|
|
281
|
+
}' retries. Request url: '${data.url}'`
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// retry request
|
|
286
|
+
return await runWithRetryAsync({
|
|
287
|
+
call: data.call,
|
|
288
|
+
retryStrategy: data.retryStrategy,
|
|
289
|
+
retryAttempt: data.retryAttempt + 1,
|
|
290
|
+
url: data.url,
|
|
291
|
+
functionsConfig: data.functionsConfig,
|
|
292
|
+
headers: data.headers
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// sanitize the error before logging / re-throwing so the authorization token is not leaked
|
|
297
|
+
const sanitizedError = sanitizeError(error, data.headers);
|
|
298
|
+
|
|
299
|
+
if (data.functionsConfig.logErrorsToConsole) {
|
|
300
|
+
console.error(
|
|
301
|
+
`Executing '${data.url}' failed. Request was retried '${data.retryAttempt}' times.`,
|
|
302
|
+
sanitizedError
|
|
303
|
+
);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
throw sanitizedError;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
const redactedValue = 'redacted';
|
|
311
|
+
const maxRedactionDepth = 10;
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Returns the caller-supplied 'authorization' header value(s), which are the secret token(s) to
|
|
315
|
+
* scrub from errors. Note: if a consumer sets the authorization token on the axios instance defaults
|
|
316
|
+
* instead of passing it via 'options.headers', it is not known here and cannot be redacted.
|
|
317
|
+
*/
|
|
318
|
+
function getSecretHeaderValues(headers: IHeader[]): string[] {
|
|
319
|
+
return headers
|
|
320
|
+
.filter((header) => header.header.toLowerCase() === 'authorization')
|
|
321
|
+
.map((header) => header.value)
|
|
322
|
+
// skip empty values - splitting on an empty string would corrupt every string
|
|
323
|
+
.filter((value) => typeof value === 'string' && value.length > 0);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
function redactStringValue(value: string, secrets: string[]): string {
|
|
327
|
+
let result = value;
|
|
328
|
+
|
|
329
|
+
for (const secret of secrets) {
|
|
330
|
+
if (result.includes(secret)) {
|
|
331
|
+
result = result.split(secret).join(redactedValue);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
return result;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Walks the object graph (cycle- and depth-guarded) replacing every occurrence of a secret with the
|
|
340
|
+
* redacted placeholder in place.
|
|
341
|
+
*/
|
|
342
|
+
function redactSecretsInPlace(target: unknown, secrets: string[], seen: WeakSet<object>, depth: number): void {
|
|
343
|
+
if (depth > maxRedactionDepth || target === null || typeof target !== 'object') {
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
if (seen.has(target)) {
|
|
348
|
+
// break cycles (config.headers, request.socket, response.request, ...)
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
seen.add(target);
|
|
352
|
+
|
|
353
|
+
for (const key of Object.keys(target as Record<string, unknown>)) {
|
|
354
|
+
let value: unknown;
|
|
355
|
+
|
|
356
|
+
try {
|
|
357
|
+
value = (target as Record<string, unknown>)[key];
|
|
358
|
+
} catch {
|
|
359
|
+
// accessing the property threw (e.g. a getter) - skip it
|
|
360
|
+
continue;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
if (typeof value === 'string') {
|
|
364
|
+
const redacted = redactStringValue(value, secrets);
|
|
365
|
+
|
|
366
|
+
if (redacted !== value) {
|
|
367
|
+
try {
|
|
368
|
+
(target as Record<string, unknown>)[key] = redacted;
|
|
369
|
+
} catch {
|
|
370
|
+
// property is read-only - skip it
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
} else if (value && typeof value === 'object') {
|
|
374
|
+
redactSecretsInPlace(value, secrets, seen, depth + 1);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* If 'error' is an axios error, redacts every occurrence of the caller's authorization token (taken
|
|
381
|
+
* from 'headers') throughout the error, replacing it with a redacted placeholder. Non-axios errors
|
|
382
|
+
* and errors with no known token are returned unchanged. This prevents the authorization token from
|
|
383
|
+
* leaking via console logs or the re-thrown error. All other axios properties are preserved.
|
|
384
|
+
*/
|
|
385
|
+
function sanitizeError(error: unknown, headers: IHeader[]): unknown {
|
|
386
|
+
if (!axios.isAxiosError(error)) {
|
|
387
|
+
return error;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
const secrets = getSecretHeaderValues(headers);
|
|
391
|
+
if (secrets.length === 0) {
|
|
392
|
+
return error;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
redactSecretsInPlace(error, secrets, new WeakSet<object>(), 0);
|
|
396
|
+
return error;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
function getHeadersJson(headers: IHeader[], addContentTypeHeader: boolean): { [header: string]: string } {
|
|
400
|
+
const headerJson: { [header: string]: string } = {};
|
|
401
|
+
|
|
402
|
+
headers.forEach((header) => {
|
|
403
|
+
headerJson[header.header] = header.value;
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
if (addContentTypeHeader) {
|
|
407
|
+
// add default content type header if not present
|
|
408
|
+
const contentTypeHeader = headers.find((m) => m.header.toLowerCase() === 'Content-Type'.toLowerCase());
|
|
409
|
+
|
|
410
|
+
if (!contentTypeHeader) {
|
|
411
|
+
headerJson['Content-Type'] = 'application/json';
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
return headerJson;
|
|
416
|
+
}
|