Socket
Socket
Sign inDemoInstall

node-fetch

Package Overview
Dependencies
0
Maintainers
2
Versions
96
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 2.2.1 to 2.3.0

23

browser.js
"use strict";
module.exports = exports = self.fetch;
// ref: https://github.com/tc39/proposal-global
var getGlobal = function () {
// the only reliable means to get the global object is
// `Function('return this')()`
// However, this causes CSP violations in Chrome apps.
if (typeof self !== 'undefined') { return self; }
if (typeof window !== 'undefined') { return window; }
if (typeof global !== 'undefined') { return global; }
throw new Error('unable to locate global object');
}
var global = getGlobal();
module.exports = exports = global.fetch;
// Needed for TypeScript and Webpack.
exports.default = self.fetch.bind(self);
exports.default = global.fetch.bind(global);
exports.Headers = self.Headers;
exports.Request = self.Request;
exports.Response = self.Response;
exports.Headers = global.Headers;
exports.Request = global.Request;
exports.Response = global.Response;

@@ -8,2 +8,8 @@

## v2.3.0
- New: `AbortSignal` support, with README example.
- Enhance: handle invalid `Location` header during redirect by rejecting them explicitly with `FetchError`.
- Fix: update `browser.js` to support react-native environment, where `self` isn't available globally.
## v2.2.1

@@ -10,0 +16,0 @@

@@ -181,3 +181,4 @@ process.emitWarning("The .es.js file is deprecated. Use .mjs instead.");

body.on('error', function (err) {
_this[INTERNALS].error = new FetchError(`Invalid response body while trying to fetch ${_this.url}: ${err.message}`, 'system', err);
const error = err.name === 'AbortError' ? err : new FetchError(`Invalid response body while trying to fetch ${_this.url}: ${err.message}`, 'system', err);
_this[INTERNALS].error = error;
});

@@ -370,5 +371,12 @@ }

// handle stream error, such as incorrect content-encoding
// handle stream errors
_this4.body.on('error', function (err) {
reject(new FetchError(`Invalid response body while trying to fetch ${_this4.url}: ${err.message}`, 'system', err));
if (err.name === 'AbortError') {
// if the request was aborted, reject with this Error
abort = true;
reject(err);
} else {
// other errors, such as incorrect content-encoding
reject(new FetchError(`Invalid response body while trying to fetch ${_this4.url}: ${err.message}`, 'system', err));
}
});

@@ -1127,2 +1135,4 @@

const streamDestructionSupported = 'destroy' in Stream.Readable.prototype;
/**

@@ -1138,2 +1148,7 @@ * Check if a value is an instance of Request.

function isAbortSignal(signal) {
const proto = signal && typeof signal === 'object' && Object.getPrototypeOf(signal);
return !!(proto && proto.constructor.name === 'AbortSignal');
}
/**

@@ -1191,2 +1206,9 @@ * Request class

let signal = isRequest(input) ? input.signal : null;
if ('signal' in init) signal = init.signal;
if (signal != null && !isAbortSignal(signal)) {
throw new TypeError('Expected signal to be an instanceof AbortSignal');
}
this[INTERNALS$2] = {

@@ -1196,3 +1218,4 @@ method,

headers,
parsedURL
parsedURL,
signal
};

@@ -1223,2 +1246,6 @@

get signal() {
return this[INTERNALS$2].signal;
}
/**

@@ -1248,3 +1275,4 @@ * Clone this request

redirect: { enumerable: true },
clone: { enumerable: true }
clone: { enumerable: true },
signal: { enumerable: true }
});

@@ -1276,2 +1304,6 @@

if (request.signal && request.body instanceof Stream.Readable && !streamDestructionSupported) {
throw new Error('Cancellation of streamed requests with AbortSignal is not supported in node < 8');
}
// HTTP-network-or-cache fetch steps 2.4-2.7

@@ -1316,2 +1348,28 @@ let contentLengthValue = null;

/**
* abort-error.js
*
* AbortError interface for cancelled requests
*/
/**
* Create AbortError instance
*
* @param String message Error message for human
* @return AbortError
*/
function AbortError(message) {
Error.call(this, message);
this.type = 'aborted';
this.message = message;
// hide custom error implementation details from end-users
Error.captureStackTrace(this, this.constructor);
}
AbortError.prototype = Object.create(Error.prototype);
AbortError.prototype.constructor = AbortError;
AbortError.prototype.name = 'AbortError';
// fix an issue where "PassThrough", "resolve" aren't a named export for node <10

@@ -1344,3 +1402,26 @@ const PassThrough$1 = Stream.PassThrough;

const send = (options.protocol === 'https:' ? https : http).request;
const signal = request.signal;
let response = null;
const abort = function abort() {
let error = new AbortError('The user aborted a request.');
reject(error);
if (request.body && request.body instanceof Stream.Readable) {
request.body.destroy(error);
}
if (!response || !response.body) return;
response.body.emit('error', error);
};
if (signal && signal.aborted) {
abort();
return;
}
const abortAndFinalize = function abortAndFinalize() {
abort();
finalize();
};
// send request

@@ -1350,4 +1431,9 @@ const req = send(options);

if (signal) {
signal.addEventListener('abort', abortAndFinalize);
}
function finalize() {
req.abort();
if (signal) signal.removeEventListener('abort', abortAndFinalize);
clearTimeout(reqTimeout);

@@ -1392,3 +1478,9 @@ }

if (locationURL !== null) {
headers.set('Location', locationURL);
// handle corrupted header
try {
headers.set('Location', locationURL);
} catch (err) {
// istanbul ignore next: nodejs server prevent invalid response headers, we can't test this through normal request
reject(err);
}
}

@@ -1418,3 +1510,4 @@ break;

method: request.method,
body: request.body
body: request.body,
signal: request.signal
};

@@ -1444,3 +1537,7 @@

// prepare response
res.once('end', function () {
if (signal) signal.removeEventListener('abort', abortAndFinalize);
});
let body = res.pipe(new PassThrough$1());
const response_options = {

@@ -1467,3 +1564,4 @@ url: request.url,

if (!request.compress || request.method === 'HEAD' || codings === null || res.statusCode === 204 || res.statusCode === 304) {
resolve(new Response(body, response_options));
response = new Response(body, response_options);
resolve(response);
return;

@@ -1485,3 +1583,4 @@ }

body = body.pipe(zlib.createGunzip(zlibOptions));
resolve(new Response(body, response_options));
response = new Response(body, response_options);
resolve(response);
return;

@@ -1502,3 +1601,4 @@ }

}
resolve(new Response(body, response_options));
response = new Response(body, response_options);
resolve(response);
});

@@ -1509,3 +1609,4 @@ return;

// otherwise, use response as-is
resolve(new Response(body, response_options));
response = new Response(body, response_options);
resolve(response);
});

@@ -1512,0 +1613,0 @@

@@ -185,3 +185,4 @@ 'use strict';

body.on('error', function (err) {
_this[INTERNALS].error = new FetchError(`Invalid response body while trying to fetch ${_this.url}: ${err.message}`, 'system', err);
const error = err.name === 'AbortError' ? err : new FetchError(`Invalid response body while trying to fetch ${_this.url}: ${err.message}`, 'system', err);
_this[INTERNALS].error = error;
});

@@ -374,5 +375,12 @@ }

// handle stream error, such as incorrect content-encoding
// handle stream errors
_this4.body.on('error', function (err) {
reject(new FetchError(`Invalid response body while trying to fetch ${_this4.url}: ${err.message}`, 'system', err));
if (err.name === 'AbortError') {
// if the request was aborted, reject with this Error
abort = true;
reject(err);
} else {
// other errors, such as incorrect content-encoding
reject(new FetchError(`Invalid response body while trying to fetch ${_this4.url}: ${err.message}`, 'system', err));
}
});

@@ -1131,2 +1139,4 @@

const streamDestructionSupported = 'destroy' in Stream.Readable.prototype;
/**

@@ -1142,2 +1152,7 @@ * Check if a value is an instance of Request.

function isAbortSignal(signal) {
const proto = signal && typeof signal === 'object' && Object.getPrototypeOf(signal);
return !!(proto && proto.constructor.name === 'AbortSignal');
}
/**

@@ -1195,2 +1210,9 @@ * Request class

let signal = isRequest(input) ? input.signal : null;
if ('signal' in init) signal = init.signal;
if (signal != null && !isAbortSignal(signal)) {
throw new TypeError('Expected signal to be an instanceof AbortSignal');
}
this[INTERNALS$2] = {

@@ -1200,3 +1222,4 @@ method,

headers,
parsedURL
parsedURL,
signal
};

@@ -1227,2 +1250,6 @@

get signal() {
return this[INTERNALS$2].signal;
}
/**

@@ -1252,3 +1279,4 @@ * Clone this request

redirect: { enumerable: true },
clone: { enumerable: true }
clone: { enumerable: true },
signal: { enumerable: true }
});

@@ -1280,2 +1308,6 @@

if (request.signal && request.body instanceof Stream.Readable && !streamDestructionSupported) {
throw new Error('Cancellation of streamed requests with AbortSignal is not supported in node < 8');
}
// HTTP-network-or-cache fetch steps 2.4-2.7

@@ -1320,2 +1352,28 @@ let contentLengthValue = null;

/**
* abort-error.js
*
* AbortError interface for cancelled requests
*/
/**
* Create AbortError instance
*
* @param String message Error message for human
* @return AbortError
*/
function AbortError(message) {
Error.call(this, message);
this.type = 'aborted';
this.message = message;
// hide custom error implementation details from end-users
Error.captureStackTrace(this, this.constructor);
}
AbortError.prototype = Object.create(Error.prototype);
AbortError.prototype.constructor = AbortError;
AbortError.prototype.name = 'AbortError';
// fix an issue where "PassThrough", "resolve" aren't a named export for node <10

@@ -1348,3 +1406,26 @@ const PassThrough$1 = Stream.PassThrough;

const send = (options.protocol === 'https:' ? https : http).request;
const signal = request.signal;
let response = null;
const abort = function abort() {
let error = new AbortError('The user aborted a request.');
reject(error);
if (request.body && request.body instanceof Stream.Readable) {
request.body.destroy(error);
}
if (!response || !response.body) return;
response.body.emit('error', error);
};
if (signal && signal.aborted) {
abort();
return;
}
const abortAndFinalize = function abortAndFinalize() {
abort();
finalize();
};
// send request

@@ -1354,4 +1435,9 @@ const req = send(options);

if (signal) {
signal.addEventListener('abort', abortAndFinalize);
}
function finalize() {
req.abort();
if (signal) signal.removeEventListener('abort', abortAndFinalize);
clearTimeout(reqTimeout);

@@ -1396,3 +1482,9 @@ }

if (locationURL !== null) {
headers.set('Location', locationURL);
// handle corrupted header
try {
headers.set('Location', locationURL);
} catch (err) {
// istanbul ignore next: nodejs server prevent invalid response headers, we can't test this through normal request
reject(err);
}
}

@@ -1422,3 +1514,4 @@ break;

method: request.method,
body: request.body
body: request.body,
signal: request.signal
};

@@ -1448,3 +1541,7 @@

// prepare response
res.once('end', function () {
if (signal) signal.removeEventListener('abort', abortAndFinalize);
});
let body = res.pipe(new PassThrough$1());
const response_options = {

@@ -1471,3 +1568,4 @@ url: request.url,

if (!request.compress || request.method === 'HEAD' || codings === null || res.statusCode === 204 || res.statusCode === 304) {
resolve(new Response(body, response_options));
response = new Response(body, response_options);
resolve(response);
return;

@@ -1489,3 +1587,4 @@ }

body = body.pipe(zlib.createGunzip(zlibOptions));
resolve(new Response(body, response_options));
response = new Response(body, response_options);
resolve(response);
return;

@@ -1506,3 +1605,4 @@ }

}
resolve(new Response(body, response_options));
response = new Response(body, response_options);
resolve(response);
});

@@ -1513,3 +1613,4 @@ return;

// otherwise, use response as-is
resolve(new Response(body, response_options));
response = new Response(body, response_options);
resolve(response);
});

@@ -1516,0 +1617,0 @@

{
"name": "node-fetch",
"version": "2.2.1",
"version": "2.3.0",
"description": "A light-weight module that brings window.fetch to node.js",

@@ -40,2 +40,4 @@ "main": "lib/index",

"devDependencies": {
"abort-controller": "^1.0.2",
"abortcontroller-polyfill": "^1.1.9",
"babel-core": "^6.26.0",

@@ -42,0 +44,0 @@ "babel-plugin-istanbul": "^4.1.5",

@@ -34,2 +34,3 @@ node-fetch

- [Post with form-data (detect multipart)](#post-with-form-data-detect-multipart)
- [Request cancellation with AbortSignal](#request-cancellation-with-abortsignal)
- [API](#api)

@@ -122,3 +123,3 @@ - [fetch(url[, options])](#fetchurl-options)

fetch('https://httpbin.org/post', {
fetch('https://httpbin.org/post', {
method: 'post',

@@ -253,2 +254,36 @@ body: JSON.stringify(body),

#### Request cancellation with AbortSignal
> NOTE: You may only cancel streamed requests on Node >= v8.0.0
You may cancel requests with `AbortController`. A suggested implementation is [`abort-controller`](https://www.npmjs.com/package/abort-controller).
An example of timing out a request after 150ms could be achieved as follows:
```js
import AbortContoller from 'abort-controller';
const controller = new AbortController();
const timeout = setTimeout(
() => { controller.abort(); },
150,
);
fetch(url, { signal: controller.signal })
.then(res => res.json())
.then(
data => {
useData(data)
},
err => {
if (err.name === 'AbortError') {
// request was aborted
}
},
)
.finally(() => {
clearTimeout(timeout);
});
```
See [test cases](https://github.com/bitinn/node-fetch/blob/master/test/test.js) for more examples.

@@ -281,6 +316,7 @@

redirect: 'follow', // set to `manual` to extract redirect headers, `error` to reject redirect
signal: null, // pass an instance of AbortSignal to optionally abort requests
// The following properties are node-fetch extensions
follow: 20, // maximum redirect count. 0 to not follow redirect
timeout: 0, // req/res timeout in ms, it resets on redirect. 0 to disable (OS limit applies)
timeout: 0, // req/res timeout in ms, it resets on redirect. 0 to disable (OS limit applies). Signal is recommended instead.
compress: true, // support gzip/deflate content encoding. false to disable

@@ -470,2 +506,9 @@ size: 0, // maximum response body size in bytes. 0 to disable

<a id="class-aborterror"></a>
### Class: AbortError
<small>*(node-fetch extension)*</small>
An Error thrown when the request is aborted in response to an `AbortSignal`'s `abort` event. It has a `name` property of `AbortError`. See [ERROR-HANDLING.MD][] for more info.
## Acknowledgement

@@ -495,2 +538,2 @@

[ERROR-HANDLING.md]: https://github.com/bitinn/node-fetch/blob/master/ERROR-HANDLING.md
[UPGRADE-GUIDE.md]: https://github.com/bitinn/node-fetch/blob/master/UPGRADE-GUIDE.md
[UPGRADE-GUIDE.md]: https://github.com/bitinn/node-fetch/blob/master/UPGRADE-GUIDE.md

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc