@naturalcycles/js-lib 14.121.0 → 14.122.1
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/dist/http/fetcher.d.ts +6 -0
- package/dist/http/fetcher.js +45 -16
- package/dist-esm/http/fetcher.js +53 -26
- package/package.json +1 -1
- package/src/http/fetcher.ts +53 -19
package/dist/http/fetcher.d.ts
CHANGED
|
@@ -80,6 +80,12 @@ export interface FetcherOptions {
|
|
|
80
80
|
timeoutSeconds?: number;
|
|
81
81
|
json?: any;
|
|
82
82
|
text?: string;
|
|
83
|
+
/**
|
|
84
|
+
* Supports all the types that RequestInit.body supports.
|
|
85
|
+
*
|
|
86
|
+
* Useful when you want to e.g pass FormData.
|
|
87
|
+
*/
|
|
88
|
+
body?: Blob | BufferSource | FormData | URLSearchParams | string;
|
|
83
89
|
credentials?: RequestCredentials;
|
|
84
90
|
headers?: Record<string, any>;
|
|
85
91
|
mode?: FetcherMode;
|
package/dist/http/fetcher.js
CHANGED
|
@@ -119,9 +119,15 @@ class Fetcher {
|
|
|
119
119
|
logger.log(req.init.body); // todo: check if we can _inspect it
|
|
120
120
|
}
|
|
121
121
|
}
|
|
122
|
-
|
|
122
|
+
try {
|
|
123
|
+
res.fetchResponse = await globalThis.fetch(req.url, req.init);
|
|
124
|
+
}
|
|
125
|
+
catch (err) {
|
|
126
|
+
// For example, CORS error would result in "TypeError: failed to fetch" here
|
|
127
|
+
res.err = err;
|
|
128
|
+
}
|
|
123
129
|
res.statusFamily = this.getStatusFamily(res);
|
|
124
|
-
if (res.fetchResponse
|
|
130
|
+
if (res.fetchResponse?.ok) {
|
|
125
131
|
if (mode === 'json') {
|
|
126
132
|
// if no body: set responseBody as {}
|
|
127
133
|
// do not throw a "cannot parse null as Json" error
|
|
@@ -150,14 +156,28 @@ class Fetcher {
|
|
|
150
156
|
}
|
|
151
157
|
else {
|
|
152
158
|
clearTimeout(timeout);
|
|
153
|
-
|
|
154
|
-
|
|
159
|
+
let errObj;
|
|
160
|
+
if (res.fetchResponse) {
|
|
161
|
+
const body = (0, json_util_1._jsonParseIfPossible)(await res.fetchResponse.text());
|
|
162
|
+
errObj = (0, error_util_1._anyToErrorObject)(body);
|
|
163
|
+
}
|
|
164
|
+
else if (res.err) {
|
|
165
|
+
errObj = (0, error_util_1._errorToErrorObject)(res.err);
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
errObj = {};
|
|
169
|
+
}
|
|
155
170
|
const originalMessage = errObj.message;
|
|
156
|
-
errObj.message = [
|
|
171
|
+
errObj.message = [
|
|
172
|
+
[res.fetchResponse?.status, signature].filter(Boolean).join(' '),
|
|
173
|
+
originalMessage,
|
|
174
|
+
]
|
|
175
|
+
.filter(Boolean)
|
|
176
|
+
.join('\n');
|
|
157
177
|
res.err = new http_error_1.HttpError(errObj.message, (0, object_util_1._filterNullishValues)({
|
|
158
178
|
...errObj.data,
|
|
159
179
|
originalMessage,
|
|
160
|
-
httpStatusCode: res.fetchResponse
|
|
180
|
+
httpStatusCode: res.fetchResponse?.status || 0,
|
|
161
181
|
// These properties are provided to be used in e.g custom Sentry error grouping
|
|
162
182
|
// Actually, disabled now, to avoid unnecessary error printing when both msg and data are printed
|
|
163
183
|
// Enabled, cause `data` is not printed by default when error is HttpError
|
|
@@ -201,8 +221,13 @@ class Fetcher {
|
|
|
201
221
|
if (method === 'post' && !retryPost)
|
|
202
222
|
return false;
|
|
203
223
|
const { statusFamily } = res;
|
|
224
|
+
const statusCode = res.fetchResponse?.status || 0;
|
|
204
225
|
if (statusFamily === 5 && !retry5xx)
|
|
205
226
|
return false;
|
|
227
|
+
if ([408, 429].includes(statusCode)) {
|
|
228
|
+
// these codes are always retried
|
|
229
|
+
return true;
|
|
230
|
+
}
|
|
206
231
|
if (statusFamily === 4 && !retry4xx)
|
|
207
232
|
return false;
|
|
208
233
|
return true; // default is true
|
|
@@ -254,11 +279,12 @@ class Fetcher {
|
|
|
254
279
|
logResponseBody: debug,
|
|
255
280
|
retry: { ...defRetryOptions },
|
|
256
281
|
init: {
|
|
257
|
-
method: 'get',
|
|
258
|
-
headers: {},
|
|
282
|
+
method: cfg.method || 'get',
|
|
283
|
+
headers: cfg.headers || {},
|
|
284
|
+
credentials: cfg.credentials,
|
|
259
285
|
},
|
|
260
286
|
hooks: {},
|
|
261
|
-
}, cfg);
|
|
287
|
+
}, (0, object_util_1._omit)(cfg, ['method', 'credentials', 'headers']));
|
|
262
288
|
norm.init.headers = (0, object_util_1._mapKeys)(norm.init.headers, k => k.toLowerCase());
|
|
263
289
|
return norm;
|
|
264
290
|
}
|
|
@@ -271,18 +297,18 @@ class Fetcher {
|
|
|
271
297
|
retryPost,
|
|
272
298
|
retry4xx,
|
|
273
299
|
retry5xx,
|
|
274
|
-
...(0, object_util_1._omit)(opt, ['method', 'headers']),
|
|
300
|
+
...(0, object_util_1._omit)(opt, ['method', 'headers', 'credentials']),
|
|
275
301
|
retry: {
|
|
276
302
|
...retry,
|
|
277
303
|
...(0, object_util_1._filterUndefinedValues)(opt.retry || {}),
|
|
278
304
|
},
|
|
279
|
-
init: (0, object_util_1._merge)({
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
305
|
+
init: (0, object_util_1._merge)({
|
|
306
|
+
...this.cfg.init,
|
|
307
|
+
method: opt.method || this.cfg.init.method,
|
|
308
|
+
credentials: opt.credentials || this.cfg.init.credentials,
|
|
309
|
+
}, {
|
|
284
310
|
headers: (0, object_util_1._mapKeys)(opt.headers || {}, k => k.toLowerCase()),
|
|
285
|
-
})
|
|
311
|
+
}),
|
|
286
312
|
};
|
|
287
313
|
// setup url
|
|
288
314
|
if (baseUrl) {
|
|
@@ -309,6 +335,9 @@ class Fetcher {
|
|
|
309
335
|
req.init.body = opt.text;
|
|
310
336
|
req.init.headers['content-type'] = 'text/plain';
|
|
311
337
|
}
|
|
338
|
+
else if (opt.body !== undefined) {
|
|
339
|
+
req.init.body = opt.body;
|
|
340
|
+
}
|
|
312
341
|
return req;
|
|
313
342
|
}
|
|
314
343
|
}
|
package/dist-esm/http/fetcher.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference lib="dom"/>
|
|
2
2
|
import { __asyncValues } from "tslib";
|
|
3
|
-
import { _anyToErrorObject } from '../error/error.util';
|
|
3
|
+
import { _anyToErrorObject, _errorToErrorObject } from '../error/error.util';
|
|
4
4
|
import { HttpError } from '../error/http.error';
|
|
5
5
|
import { _clamp } from '../number/number.util';
|
|
6
6
|
import { _filterNullishValues, _filterUndefinedValues, _mapKeys, _merge, _omit, } from '../object/object.util';
|
|
@@ -73,6 +73,7 @@ export class Fetcher {
|
|
|
73
73
|
}
|
|
74
74
|
async rawFetch(url, rawOpt = {}) {
|
|
75
75
|
var _a, e_1, _b, _c, _d, e_2, _e, _f;
|
|
76
|
+
var _g, _h, _j;
|
|
76
77
|
const { logger } = this.cfg;
|
|
77
78
|
const req = this.normalizeOptions(url, rawOpt);
|
|
78
79
|
const { timeoutSeconds, mode, init: { method }, } = req;
|
|
@@ -86,22 +87,22 @@ export class Fetcher {
|
|
|
86
87
|
}, timeoutSeconds * 1000);
|
|
87
88
|
}
|
|
88
89
|
try {
|
|
89
|
-
for (var
|
|
90
|
-
_c =
|
|
91
|
-
|
|
90
|
+
for (var _k = true, _l = __asyncValues(this.cfg.hooks.beforeRequest || []), _m; _m = await _l.next(), _a = _m.done, !_a;) {
|
|
91
|
+
_c = _m.value;
|
|
92
|
+
_k = false;
|
|
92
93
|
try {
|
|
93
94
|
const hook = _c;
|
|
94
95
|
await hook(req);
|
|
95
96
|
}
|
|
96
97
|
finally {
|
|
97
|
-
|
|
98
|
+
_k = true;
|
|
98
99
|
}
|
|
99
100
|
}
|
|
100
101
|
}
|
|
101
102
|
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
102
103
|
finally {
|
|
103
104
|
try {
|
|
104
|
-
if (!
|
|
105
|
+
if (!_k && !_a && (_b = _l.return)) await _b.call(_l);
|
|
105
106
|
}
|
|
106
107
|
finally { if (e_1) throw e_1.error; }
|
|
107
108
|
}
|
|
@@ -127,9 +128,15 @@ export class Fetcher {
|
|
|
127
128
|
logger.log(req.init.body); // todo: check if we can _inspect it
|
|
128
129
|
}
|
|
129
130
|
}
|
|
130
|
-
|
|
131
|
+
try {
|
|
132
|
+
res.fetchResponse = await globalThis.fetch(req.url, req.init);
|
|
133
|
+
}
|
|
134
|
+
catch (err) {
|
|
135
|
+
// For example, CORS error would result in "TypeError: failed to fetch" here
|
|
136
|
+
res.err = err;
|
|
137
|
+
}
|
|
131
138
|
res.statusFamily = this.getStatusFamily(res);
|
|
132
|
-
if (res.fetchResponse.ok) {
|
|
139
|
+
if ((_g = res.fetchResponse) === null || _g === void 0 ? void 0 : _g.ok) {
|
|
133
140
|
if (mode === 'json') {
|
|
134
141
|
// if no body: set responseBody as {}
|
|
135
142
|
// do not throw a "cannot parse null as Json" error
|
|
@@ -158,11 +165,25 @@ export class Fetcher {
|
|
|
158
165
|
}
|
|
159
166
|
else {
|
|
160
167
|
clearTimeout(timeout);
|
|
161
|
-
|
|
162
|
-
|
|
168
|
+
let errObj;
|
|
169
|
+
if (res.fetchResponse) {
|
|
170
|
+
const body = _jsonParseIfPossible(await res.fetchResponse.text());
|
|
171
|
+
errObj = _anyToErrorObject(body);
|
|
172
|
+
}
|
|
173
|
+
else if (res.err) {
|
|
174
|
+
errObj = _errorToErrorObject(res.err);
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
errObj = {};
|
|
178
|
+
}
|
|
163
179
|
const originalMessage = errObj.message;
|
|
164
|
-
errObj.message = [
|
|
165
|
-
|
|
180
|
+
errObj.message = [
|
|
181
|
+
[(_h = res.fetchResponse) === null || _h === void 0 ? void 0 : _h.status, signature].filter(Boolean).join(' '),
|
|
182
|
+
originalMessage,
|
|
183
|
+
]
|
|
184
|
+
.filter(Boolean)
|
|
185
|
+
.join('\n');
|
|
186
|
+
res.err = new HttpError(errObj.message, _filterNullishValues(Object.assign(Object.assign({}, errObj.data), { originalMessage, httpStatusCode: ((_j = res.fetchResponse) === null || _j === void 0 ? void 0 : _j.status) || 0,
|
|
166
187
|
// These properties are provided to be used in e.g custom Sentry error grouping
|
|
167
188
|
// Actually, disabled now, to avoid unnecessary error printing when both msg and data are printed
|
|
168
189
|
// Enabled, cause `data` is not printed by default when error is HttpError
|
|
@@ -172,22 +193,22 @@ export class Fetcher {
|
|
|
172
193
|
}
|
|
173
194
|
}
|
|
174
195
|
try {
|
|
175
|
-
for (var
|
|
176
|
-
_f =
|
|
177
|
-
|
|
196
|
+
for (var _o = true, _p = __asyncValues(this.cfg.hooks.afterResponse || []), _q; _q = await _p.next(), _d = _q.done, !_d;) {
|
|
197
|
+
_f = _q.value;
|
|
198
|
+
_o = false;
|
|
178
199
|
try {
|
|
179
200
|
const hook = _f;
|
|
180
201
|
await hook(res);
|
|
181
202
|
}
|
|
182
203
|
finally {
|
|
183
|
-
|
|
204
|
+
_o = true;
|
|
184
205
|
}
|
|
185
206
|
}
|
|
186
207
|
}
|
|
187
208
|
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
188
209
|
finally {
|
|
189
210
|
try {
|
|
190
|
-
if (!
|
|
211
|
+
if (!_o && !_d && (_e = _p.return)) await _e.call(_p);
|
|
191
212
|
}
|
|
192
213
|
finally { if (e_2) throw e_2.error; }
|
|
193
214
|
}
|
|
@@ -234,13 +255,19 @@ export class Fetcher {
|
|
|
234
255
|
* unless there's reason not to (e.g method is POST).
|
|
235
256
|
*/
|
|
236
257
|
shouldRetry(res) {
|
|
258
|
+
var _a;
|
|
237
259
|
const { retryPost, retry4xx, retry5xx } = res.req;
|
|
238
260
|
const { method } = res.req.init;
|
|
239
261
|
if (method === 'post' && !retryPost)
|
|
240
262
|
return false;
|
|
241
263
|
const { statusFamily } = res;
|
|
264
|
+
const statusCode = ((_a = res.fetchResponse) === null || _a === void 0 ? void 0 : _a.status) || 0;
|
|
242
265
|
if (statusFamily === 5 && !retry5xx)
|
|
243
266
|
return false;
|
|
267
|
+
if ([408, 429].includes(statusCode)) {
|
|
268
|
+
// these codes are always retried
|
|
269
|
+
return true;
|
|
270
|
+
}
|
|
244
271
|
if (statusFamily === 4 && !retry4xx)
|
|
245
272
|
return false;
|
|
246
273
|
return true; // default is true
|
|
@@ -294,11 +321,12 @@ export class Fetcher {
|
|
|
294
321
|
logResponseBody: debug,
|
|
295
322
|
retry: Object.assign({}, defRetryOptions),
|
|
296
323
|
init: {
|
|
297
|
-
method: 'get',
|
|
298
|
-
headers: {},
|
|
324
|
+
method: cfg.method || 'get',
|
|
325
|
+
headers: cfg.headers || {},
|
|
326
|
+
credentials: cfg.credentials,
|
|
299
327
|
},
|
|
300
328
|
hooks: {},
|
|
301
|
-
}, cfg);
|
|
329
|
+
}, _omit(cfg, ['method', 'credentials', 'headers']));
|
|
302
330
|
norm.init.headers = _mapKeys(norm.init.headers, k => k.toLowerCase());
|
|
303
331
|
return norm;
|
|
304
332
|
}
|
|
@@ -309,13 +337,9 @@ export class Fetcher {
|
|
|
309
337
|
throwHttpErrors,
|
|
310
338
|
retryPost,
|
|
311
339
|
retry4xx,
|
|
312
|
-
retry5xx }, _omit(opt, ['method', 'headers'])), { retry: Object.assign(Object.assign({}, retry), _filterUndefinedValues(opt.retry || {})), init: _merge(Object.assign({}, this.cfg.init),
|
|
313
|
-
// opt.init,
|
|
314
|
-
_filterUndefinedValues({
|
|
315
|
-
method: opt.method,
|
|
316
|
-
credentials: opt.credentials,
|
|
340
|
+
retry5xx }, _omit(opt, ['method', 'headers', 'credentials'])), { retry: Object.assign(Object.assign({}, retry), _filterUndefinedValues(opt.retry || {})), init: _merge(Object.assign(Object.assign({}, this.cfg.init), { method: opt.method || this.cfg.init.method, credentials: opt.credentials || this.cfg.init.credentials }), {
|
|
317
341
|
headers: _mapKeys(opt.headers || {}, k => k.toLowerCase()),
|
|
318
|
-
})
|
|
342
|
+
}) });
|
|
319
343
|
// setup url
|
|
320
344
|
if (baseUrl) {
|
|
321
345
|
if (url.startsWith('/')) {
|
|
@@ -338,6 +362,9 @@ export class Fetcher {
|
|
|
338
362
|
req.init.body = opt.text;
|
|
339
363
|
req.init.headers['content-type'] = 'text/plain';
|
|
340
364
|
}
|
|
365
|
+
else if (opt.body !== undefined) {
|
|
366
|
+
req.init.body = opt.body;
|
|
367
|
+
}
|
|
341
368
|
return req;
|
|
342
369
|
}
|
|
343
370
|
}
|
package/package.json
CHANGED
package/src/http/fetcher.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/// <reference lib="dom"/>
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { ErrorObject } from '../error/error.model'
|
|
4
|
+
import { _anyToErrorObject, _errorToErrorObject } from '../error/error.util'
|
|
4
5
|
import { HttpError } from '../error/http.error'
|
|
5
6
|
import { CommonLogger } from '../log/commonLogger'
|
|
6
7
|
import { _clamp } from '../number/number.util'
|
|
@@ -103,8 +104,15 @@ export interface FetcherOptions {
|
|
|
103
104
|
* so both should finish within this single timeout (not each).
|
|
104
105
|
*/
|
|
105
106
|
timeoutSeconds?: number
|
|
107
|
+
|
|
106
108
|
json?: any
|
|
107
109
|
text?: string
|
|
110
|
+
/**
|
|
111
|
+
* Supports all the types that RequestInit.body supports.
|
|
112
|
+
*
|
|
113
|
+
* Useful when you want to e.g pass FormData.
|
|
114
|
+
*/
|
|
115
|
+
body?: Blob | BufferSource | FormData | URLSearchParams | string
|
|
108
116
|
|
|
109
117
|
credentials?: RequestCredentials
|
|
110
118
|
|
|
@@ -326,10 +334,15 @@ export class Fetcher {
|
|
|
326
334
|
}
|
|
327
335
|
}
|
|
328
336
|
|
|
329
|
-
|
|
337
|
+
try {
|
|
338
|
+
res.fetchResponse = await globalThis.fetch(req.url, req.init)
|
|
339
|
+
} catch (err) {
|
|
340
|
+
// For example, CORS error would result in "TypeError: failed to fetch" here
|
|
341
|
+
res.err = err as Error
|
|
342
|
+
}
|
|
330
343
|
res.statusFamily = this.getStatusFamily(res)
|
|
331
344
|
|
|
332
|
-
if (res.fetchResponse
|
|
345
|
+
if (res.fetchResponse?.ok) {
|
|
333
346
|
if (mode === 'json') {
|
|
334
347
|
// if no body: set responseBody as {}
|
|
335
348
|
// do not throw a "cannot parse null as Json" error
|
|
@@ -362,12 +375,24 @@ export class Fetcher {
|
|
|
362
375
|
} else {
|
|
363
376
|
clearTimeout(timeout)
|
|
364
377
|
|
|
365
|
-
|
|
366
|
-
|
|
378
|
+
let errObj: ErrorObject
|
|
379
|
+
|
|
380
|
+
if (res.fetchResponse) {
|
|
381
|
+
const body = _jsonParseIfPossible(await res.fetchResponse.text())
|
|
382
|
+
errObj = _anyToErrorObject(body)
|
|
383
|
+
} else if (res.err) {
|
|
384
|
+
errObj = _errorToErrorObject(res.err)
|
|
385
|
+
} else {
|
|
386
|
+
errObj = {} as ErrorObject
|
|
387
|
+
}
|
|
388
|
+
|
|
367
389
|
const originalMessage = errObj.message
|
|
368
|
-
errObj.message = [
|
|
369
|
-
'
|
|
370
|
-
|
|
390
|
+
errObj.message = [
|
|
391
|
+
[res.fetchResponse?.status, signature].filter(Boolean).join(' '),
|
|
392
|
+
originalMessage,
|
|
393
|
+
]
|
|
394
|
+
.filter(Boolean)
|
|
395
|
+
.join('\n')
|
|
371
396
|
|
|
372
397
|
res.err = new HttpError(
|
|
373
398
|
errObj.message,
|
|
@@ -375,7 +400,7 @@ export class Fetcher {
|
|
|
375
400
|
_filterNullishValues({
|
|
376
401
|
...errObj.data,
|
|
377
402
|
originalMessage,
|
|
378
|
-
httpStatusCode: res.fetchResponse
|
|
403
|
+
httpStatusCode: res.fetchResponse?.status || 0,
|
|
379
404
|
// These properties are provided to be used in e.g custom Sentry error grouping
|
|
380
405
|
// Actually, disabled now, to avoid unnecessary error printing when both msg and data are printed
|
|
381
406
|
// Enabled, cause `data` is not printed by default when error is HttpError
|
|
@@ -430,7 +455,12 @@ export class Fetcher {
|
|
|
430
455
|
const { method } = res.req.init
|
|
431
456
|
if (method === 'post' && !retryPost) return false
|
|
432
457
|
const { statusFamily } = res
|
|
458
|
+
const statusCode = res.fetchResponse?.status || 0
|
|
433
459
|
if (statusFamily === 5 && !retry5xx) return false
|
|
460
|
+
if ([408, 429].includes(statusCode)) {
|
|
461
|
+
// these codes are always retried
|
|
462
|
+
return true
|
|
463
|
+
}
|
|
434
464
|
if (statusFamily === 4 && !retry4xx) return false
|
|
435
465
|
return true // default is true
|
|
436
466
|
}
|
|
@@ -480,12 +510,13 @@ export class Fetcher {
|
|
|
480
510
|
logResponseBody: debug,
|
|
481
511
|
retry: { ...defRetryOptions },
|
|
482
512
|
init: {
|
|
483
|
-
method: 'get',
|
|
484
|
-
headers: {},
|
|
513
|
+
method: cfg.method || 'get',
|
|
514
|
+
headers: cfg.headers || {},
|
|
515
|
+
credentials: cfg.credentials,
|
|
485
516
|
},
|
|
486
517
|
hooks: {},
|
|
487
518
|
},
|
|
488
|
-
cfg,
|
|
519
|
+
_omit(cfg, ['method', 'credentials', 'headers']),
|
|
489
520
|
)
|
|
490
521
|
|
|
491
522
|
norm.init.headers = _mapKeys(norm.init.headers, k => k.toLowerCase())
|
|
@@ -504,19 +535,20 @@ export class Fetcher {
|
|
|
504
535
|
retryPost,
|
|
505
536
|
retry4xx,
|
|
506
537
|
retry5xx,
|
|
507
|
-
..._omit(opt, ['method', 'headers']),
|
|
538
|
+
..._omit(opt, ['method', 'headers', 'credentials']),
|
|
508
539
|
retry: {
|
|
509
540
|
...retry,
|
|
510
541
|
..._filterUndefinedValues(opt.retry || {}),
|
|
511
542
|
},
|
|
512
543
|
init: _merge(
|
|
513
|
-
{
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
544
|
+
{
|
|
545
|
+
...this.cfg.init,
|
|
546
|
+
method: opt.method || this.cfg.init.method,
|
|
547
|
+
credentials: opt.credentials || this.cfg.init.credentials,
|
|
548
|
+
},
|
|
549
|
+
{
|
|
518
550
|
headers: _mapKeys(opt.headers || {}, k => k.toLowerCase()),
|
|
519
|
-
} as RequestInit
|
|
551
|
+
} as RequestInit,
|
|
520
552
|
),
|
|
521
553
|
}
|
|
522
554
|
|
|
@@ -546,6 +578,8 @@ export class Fetcher {
|
|
|
546
578
|
} else if (opt.text !== undefined) {
|
|
547
579
|
req.init.body = opt.text
|
|
548
580
|
req.init.headers['content-type'] = 'text/plain'
|
|
581
|
+
} else if (opt.body !== undefined) {
|
|
582
|
+
req.init.body = opt.body
|
|
549
583
|
}
|
|
550
584
|
|
|
551
585
|
return req
|