@common.js/node-fetch 3.3.2

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/src/index.js ADDED
@@ -0,0 +1,602 @@
1
+ /**
2
+ * Index.js
3
+ *
4
+ * a request API compatible with window.fetch
5
+ *
6
+ * All spec algorithm step numbers are based on https://fetch.spec.whatwg.org/commit-snapshots/ae716822cb3a61843226cd090eefc6589446c1d2/.
7
+ */ "use strict";
8
+ Object.defineProperty(exports, "__esModule", {
9
+ value: true
10
+ });
11
+ function _export(target, all) {
12
+ for(var name in all)Object.defineProperty(target, name, {
13
+ enumerable: true,
14
+ get: all[name]
15
+ });
16
+ }
17
+ _export(exports, {
18
+ FormData: function() {
19
+ return _esmMinJs.FormData;
20
+ },
21
+ Headers: function() {
22
+ return _headersJs.default;
23
+ },
24
+ Request: function() {
25
+ return _requestJs.default;
26
+ },
27
+ Response: function() {
28
+ return _responseJs.default;
29
+ },
30
+ FetchError: function() {
31
+ return _fetchErrorJs.FetchError;
32
+ },
33
+ AbortError: function() {
34
+ return _abortErrorJs.AbortError;
35
+ },
36
+ isRedirect: function() {
37
+ return _isRedirectJs.isRedirect;
38
+ },
39
+ Blob: function() {
40
+ return _fromJs.Blob;
41
+ },
42
+ File: function() {
43
+ return _fromJs.File;
44
+ },
45
+ fileFromSync: function() {
46
+ return _fromJs.fileFromSync;
47
+ },
48
+ fileFrom: function() {
49
+ return _fromJs.fileFrom;
50
+ },
51
+ blobFromSync: function() {
52
+ return _fromJs.blobFromSync;
53
+ },
54
+ blobFrom: function() {
55
+ return _fromJs.blobFrom;
56
+ },
57
+ /**
58
+ * Fetch function
59
+ *
60
+ * @param {string | URL | import('./request').default} url - Absolute url or Request instance
61
+ * @param {*} [options_] - Fetch options
62
+ * @return {Promise<import('./response').default>}
63
+ */ default: function() {
64
+ return fetch;
65
+ }
66
+ });
67
+ var _nodeHttp = /*#__PURE__*/ _interopRequireDefault(require("node:http"));
68
+ var _nodeHttps = /*#__PURE__*/ _interopRequireDefault(require("node:https"));
69
+ var _nodeZlib = /*#__PURE__*/ _interopRequireDefault(require("node:zlib"));
70
+ var _nodeStream = /*#__PURE__*/ _interopRequireWildcard(require("node:stream"));
71
+ var _nodeBuffer = require("node:buffer");
72
+ var _dataUriToBuffer = /*#__PURE__*/ _interopRequireDefault(require("data-uri-to-buffer"));
73
+ var _bodyJs = require("./body.js");
74
+ var _responseJs = /*#__PURE__*/ _interopRequireDefault(require("./response.js"));
75
+ var _headersJs = /*#__PURE__*/ _interopRequireWildcard(require("./headers.js"));
76
+ var _requestJs = /*#__PURE__*/ _interopRequireWildcard(require("./request.js"));
77
+ var _fetchErrorJs = require("./errors/fetch-error.js");
78
+ var _abortErrorJs = require("./errors/abort-error.js");
79
+ var _isRedirectJs = require("./utils/is-redirect.js");
80
+ var _esmMinJs = require("formdata-polyfill/esm.min.js");
81
+ var _isJs = require("./utils/is.js");
82
+ var _referrerJs = require("./utils/referrer.js");
83
+ var _fromJs = require("fetch-blob/from.js");
84
+ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
85
+ try {
86
+ var info = gen[key](arg);
87
+ var value = info.value;
88
+ } catch (error) {
89
+ reject(error);
90
+ return;
91
+ }
92
+ if (info.done) {
93
+ resolve(value);
94
+ } else {
95
+ Promise.resolve(value).then(_next, _throw);
96
+ }
97
+ }
98
+ function _asyncToGenerator(fn) {
99
+ return function() {
100
+ var self = this, args = arguments;
101
+ return new Promise(function(resolve, reject) {
102
+ var gen = fn.apply(self, args);
103
+ function _next(value) {
104
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
105
+ }
106
+ function _throw(err) {
107
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
108
+ }
109
+ _next(undefined);
110
+ });
111
+ };
112
+ }
113
+ function _instanceof(left, right) {
114
+ if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
115
+ return !!right[Symbol.hasInstance](left);
116
+ } else {
117
+ return left instanceof right;
118
+ }
119
+ }
120
+ function _interopRequireDefault(obj) {
121
+ return obj && obj.__esModule ? obj : {
122
+ default: obj
123
+ };
124
+ }
125
+ function _getRequireWildcardCache(nodeInterop) {
126
+ if (typeof WeakMap !== "function") return null;
127
+ var cacheBabelInterop = new WeakMap();
128
+ var cacheNodeInterop = new WeakMap();
129
+ return (_getRequireWildcardCache = function(nodeInterop) {
130
+ return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
131
+ })(nodeInterop);
132
+ }
133
+ function _interopRequireWildcard(obj, nodeInterop) {
134
+ if (!nodeInterop && obj && obj.__esModule) {
135
+ return obj;
136
+ }
137
+ if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
138
+ return {
139
+ default: obj
140
+ };
141
+ }
142
+ var cache = _getRequireWildcardCache(nodeInterop);
143
+ if (cache && cache.has(obj)) {
144
+ return cache.get(obj);
145
+ }
146
+ var newObj = {};
147
+ var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
148
+ for(var key in obj){
149
+ if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
150
+ var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
151
+ if (desc && (desc.get || desc.set)) {
152
+ Object.defineProperty(newObj, key, desc);
153
+ } else {
154
+ newObj[key] = obj[key];
155
+ }
156
+ }
157
+ }
158
+ newObj.default = obj;
159
+ if (cache) {
160
+ cache.set(obj, newObj);
161
+ }
162
+ return newObj;
163
+ }
164
+ var __generator = (void 0) && (void 0).__generator || function(thisArg, body) {
165
+ var f, y, t, g, _ = {
166
+ label: 0,
167
+ sent: function() {
168
+ if (t[0] & 1) throw t[1];
169
+ return t[1];
170
+ },
171
+ trys: [],
172
+ ops: []
173
+ };
174
+ return g = {
175
+ next: verb(0),
176
+ "throw": verb(1),
177
+ "return": verb(2)
178
+ }, typeof Symbol === "function" && (g[Symbol.iterator] = function() {
179
+ return this;
180
+ }), g;
181
+ function verb(n) {
182
+ return function(v) {
183
+ return step([
184
+ n,
185
+ v
186
+ ]);
187
+ };
188
+ }
189
+ function step(op) {
190
+ if (f) throw new TypeError("Generator is already executing.");
191
+ while(_)try {
192
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
193
+ if (y = 0, t) op = [
194
+ op[0] & 2,
195
+ t.value
196
+ ];
197
+ switch(op[0]){
198
+ case 0:
199
+ case 1:
200
+ t = op;
201
+ break;
202
+ case 4:
203
+ _.label++;
204
+ return {
205
+ value: op[1],
206
+ done: false
207
+ };
208
+ case 5:
209
+ _.label++;
210
+ y = op[1];
211
+ op = [
212
+ 0
213
+ ];
214
+ continue;
215
+ case 7:
216
+ op = _.ops.pop();
217
+ _.trys.pop();
218
+ continue;
219
+ default:
220
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
221
+ _ = 0;
222
+ continue;
223
+ }
224
+ if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
225
+ _.label = op[1];
226
+ break;
227
+ }
228
+ if (op[0] === 6 && _.label < t[1]) {
229
+ _.label = t[1];
230
+ t = op;
231
+ break;
232
+ }
233
+ if (t && _.label < t[2]) {
234
+ _.label = t[2];
235
+ _.ops.push(op);
236
+ break;
237
+ }
238
+ if (t[2]) _.ops.pop();
239
+ _.trys.pop();
240
+ continue;
241
+ }
242
+ op = body.call(thisArg, _);
243
+ } catch (e) {
244
+ op = [
245
+ 6,
246
+ e
247
+ ];
248
+ y = 0;
249
+ } finally{
250
+ f = t = 0;
251
+ }
252
+ if (op[0] & 5) throw op[1];
253
+ return {
254
+ value: op[0] ? op[1] : void 0,
255
+ done: true
256
+ };
257
+ }
258
+ };
259
+ var supportedSchemas = new Set([
260
+ "data:",
261
+ "http:",
262
+ "https:"
263
+ ]);
264
+ function fetch(url, options_) {
265
+ return _fetch.apply(this, arguments);
266
+ }
267
+ function _fetch() {
268
+ _fetch = _asyncToGenerator(function(url, options_) {
269
+ return __generator(this, function(_state) {
270
+ return [
271
+ 2,
272
+ new Promise(function(resolve, reject) {
273
+ // Build request object
274
+ var request = new _requestJs.default(url, options_);
275
+ var ref = (0, _requestJs.getNodeRequestOptions)(request), parsedURL = ref.parsedURL, options = ref.options;
276
+ if (!supportedSchemas.has(parsedURL.protocol)) {
277
+ throw new TypeError("node-fetch cannot load ".concat(url, '. URL scheme "').concat(parsedURL.protocol.replace(/:$/, ""), '" is not supported.'));
278
+ }
279
+ if (parsedURL.protocol === "data:") {
280
+ var data = (0, _dataUriToBuffer.default)(request.url);
281
+ var response = new _responseJs.default(data, {
282
+ headers: {
283
+ "Content-Type": data.typeFull
284
+ }
285
+ });
286
+ resolve(response);
287
+ return;
288
+ }
289
+ // Wrap http.request into fetch
290
+ var send = (parsedURL.protocol === "https:" ? _nodeHttps.default : _nodeHttp.default).request;
291
+ var signal = request.signal;
292
+ var response1 = null;
293
+ var abort = function() {
294
+ var error = new _abortErrorJs.AbortError("The operation was aborted.");
295
+ reject(error);
296
+ if (request.body && _instanceof(request.body, _nodeStream.default.Readable)) {
297
+ request.body.destroy(error);
298
+ }
299
+ if (!response1 || !response1.body) {
300
+ return;
301
+ }
302
+ response1.body.emit("error", error);
303
+ };
304
+ if (signal && signal.aborted) {
305
+ abort();
306
+ return;
307
+ }
308
+ var abortAndFinalize = function() {
309
+ abort();
310
+ finalize();
311
+ };
312
+ // Send request
313
+ var request_ = send(parsedURL.toString(), options);
314
+ if (signal) {
315
+ signal.addEventListener("abort", abortAndFinalize);
316
+ }
317
+ var finalize = function() {
318
+ request_.abort();
319
+ if (signal) {
320
+ signal.removeEventListener("abort", abortAndFinalize);
321
+ }
322
+ };
323
+ request_.on("error", function(error) {
324
+ reject(new _fetchErrorJs.FetchError("request to ".concat(request.url, " failed, reason: ").concat(error.message), "system", error));
325
+ finalize();
326
+ });
327
+ fixResponseChunkedTransferBadEnding(request_, function(error) {
328
+ if (response1 && response1.body) {
329
+ response1.body.destroy(error);
330
+ }
331
+ });
332
+ /* c8 ignore next 18 */ if (process.version < "v14") {
333
+ // Before Node.js 14, pipeline() does not fully support async iterators and does not always
334
+ // properly handle when the socket close/end events are out of order.
335
+ request_.on("socket", function(s) {
336
+ var endedWithEventsCount;
337
+ s.prependListener("end", function() {
338
+ endedWithEventsCount = s._eventsCount;
339
+ });
340
+ s.prependListener("close", function(hadError) {
341
+ // if end happened before close but the socket didn't emit an error, do it now
342
+ if (response1 && endedWithEventsCount < s._eventsCount && !hadError) {
343
+ var error = new Error("Premature close");
344
+ error.code = "ERR_STREAM_PREMATURE_CLOSE";
345
+ response1.body.emit("error", error);
346
+ }
347
+ });
348
+ });
349
+ }
350
+ request_.on("response", function(response_) {
351
+ request_.setTimeout(0);
352
+ var headers = (0, _headersJs.fromRawHeaders)(response_.rawHeaders);
353
+ // HTTP fetch step 5
354
+ if ((0, _isRedirectJs.isRedirect)(response_.statusCode)) {
355
+ // HTTP fetch step 5.2
356
+ var location = headers.get("Location");
357
+ // HTTP fetch step 5.3
358
+ var locationURL = null;
359
+ try {
360
+ locationURL = location === null ? null : new URL(location, request.url);
361
+ } catch (e) {
362
+ // error here can only be invalid URL in Location: header
363
+ // do not throw when options.redirect == manual
364
+ // let the user extract the errorneous redirect URL
365
+ if (request.redirect !== "manual") {
366
+ reject(new _fetchErrorJs.FetchError("uri requested responds with an invalid redirect URL: ".concat(location), "invalid-redirect"));
367
+ finalize();
368
+ return;
369
+ }
370
+ }
371
+ // HTTP fetch step 5.5
372
+ switch(request.redirect){
373
+ case "error":
374
+ reject(new _fetchErrorJs.FetchError("uri requested responds with a redirect, redirect mode is set to error: ".concat(request.url), "no-redirect"));
375
+ finalize();
376
+ return;
377
+ case "manual":
378
+ break;
379
+ case "follow":
380
+ {
381
+ // HTTP-redirect fetch step 2
382
+ if (locationURL === null) {
383
+ break;
384
+ }
385
+ // HTTP-redirect fetch step 5
386
+ if (request.counter >= request.follow) {
387
+ reject(new _fetchErrorJs.FetchError("maximum redirect reached at: ".concat(request.url), "max-redirect"));
388
+ finalize();
389
+ return;
390
+ }
391
+ // HTTP-redirect fetch step 6 (counter increment)
392
+ // Create a new Request object.
393
+ var requestOptions = {
394
+ headers: new _headersJs.default(request.headers),
395
+ follow: request.follow,
396
+ counter: request.counter + 1,
397
+ agent: request.agent,
398
+ compress: request.compress,
399
+ method: request.method,
400
+ body: (0, _bodyJs.clone)(request),
401
+ signal: request.signal,
402
+ size: request.size,
403
+ referrer: request.referrer,
404
+ referrerPolicy: request.referrerPolicy
405
+ };
406
+ // when forwarding sensitive headers like "Authorization",
407
+ // "WWW-Authenticate", and "Cookie" to untrusted targets,
408
+ // headers will be ignored when following a redirect to a domain
409
+ // that is not a subdomain match or exact match of the initial domain.
410
+ // For example, a redirect from "foo.com" to either "foo.com" or "sub.foo.com"
411
+ // will forward the sensitive headers, but a redirect to "bar.com" will not.
412
+ // headers will also be ignored when following a redirect to a domain using
413
+ // a different protocol. For example, a redirect from "https://foo.com" to "http://foo.com"
414
+ // will not forward the sensitive headers
415
+ if (!(0, _isJs.isDomainOrSubdomain)(request.url, locationURL) || !(0, _isJs.isSameProtocol)(request.url, locationURL)) {
416
+ for(var _i = 0, _iter = [
417
+ "authorization",
418
+ "www-authenticate",
419
+ "cookie",
420
+ "cookie2"
421
+ ]; _i < _iter.length; _i++){
422
+ var name = _iter[_i];
423
+ requestOptions.headers.delete(name);
424
+ }
425
+ }
426
+ // HTTP-redirect fetch step 9
427
+ if (response_.statusCode !== 303 && request.body && _instanceof(options_.body, _nodeStream.default.Readable)) {
428
+ reject(new _fetchErrorJs.FetchError("Cannot follow redirect with body being a readable stream", "unsupported-redirect"));
429
+ finalize();
430
+ return;
431
+ }
432
+ // HTTP-redirect fetch step 11
433
+ if (response_.statusCode === 303 || (response_.statusCode === 301 || response_.statusCode === 302) && request.method === "POST") {
434
+ requestOptions.method = "GET";
435
+ requestOptions.body = undefined;
436
+ requestOptions.headers.delete("content-length");
437
+ }
438
+ // HTTP-redirect fetch step 14
439
+ var responseReferrerPolicy = (0, _referrerJs.parseReferrerPolicyFromHeader)(headers);
440
+ if (responseReferrerPolicy) {
441
+ requestOptions.referrerPolicy = responseReferrerPolicy;
442
+ }
443
+ // HTTP-redirect fetch step 15
444
+ resolve(fetch(new _requestJs.default(locationURL, requestOptions)));
445
+ finalize();
446
+ return;
447
+ }
448
+ default:
449
+ return reject(new TypeError("Redirect option '".concat(request.redirect, "' is not a valid value of RequestRedirect")));
450
+ }
451
+ }
452
+ // Prepare response
453
+ if (signal) {
454
+ response_.once("end", function() {
455
+ signal.removeEventListener("abort", abortAndFinalize);
456
+ });
457
+ }
458
+ var body = (0, _nodeStream.pipeline)(response_, new _nodeStream.PassThrough(), function(error) {
459
+ if (error) {
460
+ reject(error);
461
+ }
462
+ });
463
+ // see https://github.com/nodejs/node/pull/29376
464
+ /* c8 ignore next 3 */ if (process.version < "v12.10") {
465
+ response_.on("aborted", abortAndFinalize);
466
+ }
467
+ var responseOptions = {
468
+ url: request.url,
469
+ status: response_.statusCode,
470
+ statusText: response_.statusMessage,
471
+ headers: headers,
472
+ size: request.size,
473
+ counter: request.counter,
474
+ highWaterMark: request.highWaterMark
475
+ };
476
+ // HTTP-network fetch step 12.1.1.3
477
+ var codings = headers.get("Content-Encoding");
478
+ // HTTP-network fetch step 12.1.1.4: handle content codings
479
+ // in following scenarios we ignore compression support
480
+ // 1. compression support is disabled
481
+ // 2. HEAD request
482
+ // 3. no Content-Encoding header
483
+ // 4. no content response (204)
484
+ // 5. content not modified response (304)
485
+ if (!request.compress || request.method === "HEAD" || codings === null || response_.statusCode === 204 || response_.statusCode === 304) {
486
+ response1 = new _responseJs.default(body, responseOptions);
487
+ resolve(response1);
488
+ return;
489
+ }
490
+ // For Node v6+
491
+ // Be less strict when decoding compressed responses, since sometimes
492
+ // servers send slightly invalid responses that are still accepted
493
+ // by common browsers.
494
+ // Always using Z_SYNC_FLUSH is what cURL does.
495
+ var zlibOptions = {
496
+ flush: _nodeZlib.default.Z_SYNC_FLUSH,
497
+ finishFlush: _nodeZlib.default.Z_SYNC_FLUSH
498
+ };
499
+ // For gzip
500
+ if (codings === "gzip" || codings === "x-gzip") {
501
+ body = (0, _nodeStream.pipeline)(body, _nodeZlib.default.createGunzip(zlibOptions), function(error) {
502
+ if (error) {
503
+ reject(error);
504
+ }
505
+ });
506
+ response1 = new _responseJs.default(body, responseOptions);
507
+ resolve(response1);
508
+ return;
509
+ }
510
+ // For deflate
511
+ if (codings === "deflate" || codings === "x-deflate") {
512
+ // Handle the infamous raw deflate response from old servers
513
+ // a hack for old IIS and Apache servers
514
+ var raw = (0, _nodeStream.pipeline)(response_, new _nodeStream.PassThrough(), function(error) {
515
+ if (error) {
516
+ reject(error);
517
+ }
518
+ });
519
+ raw.once("data", function(chunk) {
520
+ // See http://stackoverflow.com/questions/37519828
521
+ if ((chunk[0] & 0x0F) === 0x08) {
522
+ body = (0, _nodeStream.pipeline)(body, _nodeZlib.default.createInflate(), function(error) {
523
+ if (error) {
524
+ reject(error);
525
+ }
526
+ });
527
+ } else {
528
+ body = (0, _nodeStream.pipeline)(body, _nodeZlib.default.createInflateRaw(), function(error) {
529
+ if (error) {
530
+ reject(error);
531
+ }
532
+ });
533
+ }
534
+ response1 = new _responseJs.default(body, responseOptions);
535
+ resolve(response1);
536
+ });
537
+ raw.once("end", function() {
538
+ // Some old IIS servers return zero-length OK deflate responses, so
539
+ // 'data' is never emitted. See https://github.com/node-fetch/node-fetch/pull/903
540
+ if (!response1) {
541
+ response1 = new _responseJs.default(body, responseOptions);
542
+ resolve(response1);
543
+ }
544
+ });
545
+ return;
546
+ }
547
+ // For br
548
+ if (codings === "br") {
549
+ body = (0, _nodeStream.pipeline)(body, _nodeZlib.default.createBrotliDecompress(), function(error) {
550
+ if (error) {
551
+ reject(error);
552
+ }
553
+ });
554
+ response1 = new _responseJs.default(body, responseOptions);
555
+ resolve(response1);
556
+ return;
557
+ }
558
+ // Otherwise, use response as-is
559
+ response1 = new _responseJs.default(body, responseOptions);
560
+ resolve(response1);
561
+ });
562
+ // eslint-disable-next-line promise/prefer-await-to-then
563
+ (0, _bodyJs.writeToStream)(request_, request).catch(reject);
564
+ })
565
+ ];
566
+ });
567
+ });
568
+ return _fetch.apply(this, arguments);
569
+ }
570
+ function fixResponseChunkedTransferBadEnding(request, errorCallback) {
571
+ var LAST_CHUNK = _nodeBuffer.Buffer.from("0\r\n\r\n");
572
+ var isChunkedTransfer = false;
573
+ var properLastChunkReceived = false;
574
+ var previousChunk;
575
+ request.on("response", function(response) {
576
+ var headers = response.headers;
577
+ isChunkedTransfer = headers["transfer-encoding"] === "chunked" && !headers["content-length"];
578
+ });
579
+ request.on("socket", function(socket) {
580
+ var onSocketClose = function() {
581
+ if (isChunkedTransfer && !properLastChunkReceived) {
582
+ var error = new Error("Premature close");
583
+ error.code = "ERR_STREAM_PREMATURE_CLOSE";
584
+ errorCallback(error);
585
+ }
586
+ };
587
+ var onData = function(buf) {
588
+ properLastChunkReceived = _nodeBuffer.Buffer.compare(buf.slice(-5), LAST_CHUNK) === 0;
589
+ // Sometimes final 0-length chunk and end of message code are in separate packets
590
+ if (!properLastChunkReceived && previousChunk) {
591
+ properLastChunkReceived = _nodeBuffer.Buffer.compare(previousChunk.slice(-3), LAST_CHUNK.slice(0, 3)) === 0 && _nodeBuffer.Buffer.compare(buf.slice(-2), LAST_CHUNK.slice(3)) === 0;
592
+ }
593
+ previousChunk = buf;
594
+ };
595
+ socket.prependListener("close", onSocketClose);
596
+ socket.on("data", onData);
597
+ request.on("close", function() {
598
+ socket.removeListener("close", onSocketClose);
599
+ socket.removeListener("data", onData);
600
+ });
601
+ });
602
+ }