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.3.0 to 2.4.0

10

CHANGELOG.md

@@ -8,5 +8,13 @@

## v2.4.0
- Enhance: added `Brotli` compression support (using node's zlib).
- Enhance: updated `Blob` implementation per spec.
- Fix: set content type automatically for `URLSearchParams`.
- Fix: `Headers` now reject empty header names.
- Fix: test cases, as node 12+ no longer accepts invalid header response.
## v2.3.0
- New: `AbortSignal` support, with README example.
- Enhance: added `AbortSignal` support, with README example.
- Enhance: handle invalid `Location` header during redirect by rejecting them explicitly with `FetchError`.

@@ -13,0 +21,0 @@ - Fix: update `browser.js` to support react-native environment, where `self` isn't available globally.

138

lib/index.es.js
process.emitWarning("The .es.js file is deprecated. Use .mjs instead.");
import Stream from 'stream';
import Stream, { Readable } from 'stream';
import http from 'http';

@@ -10,3 +10,2 @@ import Url from 'url';

// Based on https://github.com/tmpvar/jsdom/blob/aa85b2abf07766ff7bf5c1f6daafb3726f2f2db5/lib/jsdom/living/blob.js
// (MIT licensed)

@@ -24,2 +23,3 @@ const BUFFER = Symbol('buffer');

const buffers = [];
let size = 0;

@@ -43,2 +43,3 @@ if (blobParts) {

}
size += buffer.length;
buffers.push(buffer);

@@ -61,2 +62,20 @@ }

}
text() {
return Promise.resolve(this[BUFFER].toString());
}
arrayBuffer() {
const buf = this[BUFFER];
const ab = buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
return Promise.resolve(ab);
}
stream() {
const readable = new Readable();
readable._read = function () {};
readable.push(this[BUFFER]);
readable.push(null);
return readable;
}
toString() {
return '[object Blob]';
}
slice() {

@@ -170,6 +189,18 @@ const size = this.size;

body = null;
} else if (typeof body === 'string') ; else if (isURLSearchParams(body)) ; else if (body instanceof Blob) ; else if (Buffer.isBuffer(body)) ; else if (Object.prototype.toString.call(body) === '[object ArrayBuffer]') ; else if (ArrayBuffer.isView(body)) ; else if (body instanceof Stream) ; else {
} else if (isURLSearchParams(body)) {
// body is a URLSearchParams
body = Buffer.from(body.toString());
} else if (body instanceof Blob) {
// body is blob
body = body[BUFFER];
} else if (Buffer.isBuffer(body)) ; else if (Object.prototype.toString.call(body) === '[object ArrayBuffer]') {
// body is ArrayBuffer
body = Buffer.from(body);
} else if (ArrayBuffer.isView(body)) {
// body is ArrayBufferView
body = Buffer.from(body.buffer, body.byteOffset, body.byteLength);
} else if (body instanceof Stream) ; else {
// none of the above
// coerce to string
body = String(body);
// coerce to string then buffer
body = Buffer.from(String(body));
}

@@ -280,3 +311,2 @@ this[INTERNALS] = {

}
};

@@ -329,12 +359,2 @@

// body is string
if (typeof this.body === 'string') {
return Body.Promise.resolve(Buffer.from(this.body));
}
// body is blob
if (this.body instanceof Blob) {
return Body.Promise.resolve(this.body[BUFFER]);
}
// body is buffer

@@ -345,12 +365,2 @@ if (Buffer.isBuffer(this.body)) {

// body is ArrayBuffer
if (Object.prototype.toString.call(this.body) === '[object ArrayBuffer]') {
return Body.Promise.resolve(Buffer.from(this.body));
}
// body is ArrayBufferView
if (ArrayBuffer.isView(this.body)) {
return Body.Promise.resolve(Buffer.from(this.body.buffer, this.body.byteOffset, this.body.byteLength));
}
// istanbul ignore if: should never happen

@@ -413,3 +423,3 @@ if (!(this.body instanceof Stream)) {

try {
resolve(Buffer.concat(accum));
resolve(Buffer.concat(accum, accumBytes));
} catch (err) {

@@ -539,8 +549,5 @@ // handle streams that have accumulated too much data (issue #414)

*/
function extractContentType(instance) {
const body = instance.body;
function extractContentType(body) {
// istanbul ignore if: Currently, because of a guard in Request, body
// can never be null. Included here for completeness.
if (body === null) {

@@ -570,6 +577,9 @@ // body is null

return `multipart/form-data;boundary=${body.getBoundary()}`;
} else {
} else if (body instanceof Stream) {
// body is stream
// can't really do much about this
return null;
} else {
// Body constructor defaults other things to string
return 'text/plain;charset=UTF-8';
}

@@ -595,20 +605,5 @@ }

return 0;
} else if (typeof body === 'string') {
// body is string
return Buffer.byteLength(body);
} else if (isURLSearchParams(body)) {
// body is URLSearchParams
return Buffer.byteLength(String(body));
} else if (body instanceof Blob) {
// body is blob
return body.size;
} else if (Buffer.isBuffer(body)) {
// body is buffer
return body.length;
} else if (Object.prototype.toString.call(body) === '[object ArrayBuffer]') {
// body is ArrayBuffer
return body.byteLength;
} else if (ArrayBuffer.isView(body)) {
// body is ArrayBufferView
return body.byteLength;
} else if (body && typeof body.getLengthSync === 'function') {

@@ -642,14 +637,2 @@ // detect form data input from form-data module

dest.end();
} else if (typeof body === 'string') {
// body is string
dest.write(body);
dest.end();
} else if (isURLSearchParams(body)) {
// body is URLSearchParams
dest.write(Buffer.from(String(body)));
dest.end();
} else if (body instanceof Blob) {
// body is blob
dest.write(body[BUFFER]);
dest.end();
} else if (Buffer.isBuffer(body)) {

@@ -659,10 +642,2 @@ // body is buffer

dest.end();
} else if (Object.prototype.toString.call(body) === '[object ArrayBuffer]') {
// body is ArrayBuffer
dest.write(Buffer.from(body));
dest.end();
} else if (ArrayBuffer.isView(body)) {
// body is ArrayBufferView
dest.write(Buffer.from(body.buffer, body.byteOffset, body.byteLength));
dest.end();
} else {

@@ -688,3 +663,3 @@ // body is stream

name = `${name}`;
if (invalidTokenRegex.test(name)) {
if (invalidTokenRegex.test(name) || name === '') {
throw new TypeError(`${name} is not a legal HTTP header name`);

@@ -1076,3 +1051,11 @@ }

const status = opts.status || 200;
const headers = new Headers(opts.headers);
if (body != null && !headers.has('Content-Type')) {
const contentType = extractContentType(body);
if (contentType) {
headers.append('Content-Type', contentType);
}
}
this[INTERNALS$1] = {

@@ -1082,3 +1065,3 @@ url: opts.url,

statusText: opts.statusText || STATUS_CODES[status],
headers: new Headers(opts.headers)
headers
};

@@ -1212,5 +1195,5 @@ }

if (init.body != null) {
const contentType = extractContentType(this);
if (contentType !== null && !headers.has('Content-Type')) {
if (inputBody != null && !headers.has('Content-Type')) {
const contentType = extractContentType(inputBody);
if (contentType) {
headers.append('Content-Type', contentType);

@@ -1516,3 +1499,4 @@ }

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

@@ -1609,2 +1593,10 @@

// for br
if (codings == 'br' && typeof zlib.createBrotliDecompress === 'function') {
body = body.pipe(zlib.createBrotliDecompress());
response = new Response(body, response_options);
resolve(response);
return;
}
// otherwise, use response as-is

@@ -1611,0 +1603,0 @@ response = new Response(body, response_options);

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

var Stream = _interopDefault(require('stream'));
var Stream = require('stream');
var Stream__default = _interopDefault(Stream);
var http = _interopDefault(require('http'));

@@ -15,3 +16,2 @@ var Url = _interopDefault(require('url'));

// Based on https://github.com/tmpvar/jsdom/blob/aa85b2abf07766ff7bf5c1f6daafb3726f2f2db5/lib/jsdom/living/blob.js
// (MIT licensed)

@@ -29,2 +29,3 @@ const BUFFER = Symbol('buffer');

const buffers = [];
let size = 0;

@@ -48,2 +49,3 @@ if (blobParts) {

}
size += buffer.length;
buffers.push(buffer);

@@ -66,2 +68,20 @@ }

}
text() {
return Promise.resolve(this[BUFFER].toString());
}
arrayBuffer() {
const buf = this[BUFFER];
const ab = buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
return Promise.resolve(ab);
}
stream() {
const readable = new Stream.Readable();
readable._read = function () {};
readable.push(this[BUFFER]);
readable.push(null);
return readable;
}
toString() {
return '[object Blob]';
}
slice() {

@@ -151,3 +171,3 @@ const size = this.size;

// fix an issue where "PassThrough" isn't a named export for node <10
const PassThrough = Stream.PassThrough;
const PassThrough = Stream__default.PassThrough;

@@ -176,6 +196,18 @@ /**

body = null;
} else if (typeof body === 'string') ; else if (isURLSearchParams(body)) ; else if (body instanceof Blob) ; else if (Buffer.isBuffer(body)) ; else if (Object.prototype.toString.call(body) === '[object ArrayBuffer]') ; else if (ArrayBuffer.isView(body)) ; else if (body instanceof Stream) ; else {
} else if (isURLSearchParams(body)) {
// body is a URLSearchParams
body = Buffer.from(body.toString());
} else if (body instanceof Blob) {
// body is blob
body = body[BUFFER];
} else if (Buffer.isBuffer(body)) ; else if (Object.prototype.toString.call(body) === '[object ArrayBuffer]') {
// body is ArrayBuffer
body = Buffer.from(body);
} else if (ArrayBuffer.isView(body)) {
// body is ArrayBufferView
body = Buffer.from(body.buffer, body.byteOffset, body.byteLength);
} else if (body instanceof Stream__default) ; else {
// none of the above
// coerce to string
body = String(body);
// coerce to string then buffer
body = Buffer.from(String(body));
}

@@ -190,3 +222,3 @@ this[INTERNALS] = {

if (body instanceof Stream) {
if (body instanceof Stream__default) {
body.on('error', function (err) {

@@ -287,3 +319,2 @@ const error = err.name === 'AbortError' ? err : new FetchError(`Invalid response body while trying to fetch ${_this.url}: ${err.message}`, 'system', err);

}
};

@@ -336,12 +367,2 @@

// body is string
if (typeof this.body === 'string') {
return Body.Promise.resolve(Buffer.from(this.body));
}
// body is blob
if (this.body instanceof Blob) {
return Body.Promise.resolve(this.body[BUFFER]);
}
// body is buffer

@@ -352,14 +373,4 @@ if (Buffer.isBuffer(this.body)) {

// body is ArrayBuffer
if (Object.prototype.toString.call(this.body) === '[object ArrayBuffer]') {
return Body.Promise.resolve(Buffer.from(this.body));
}
// body is ArrayBufferView
if (ArrayBuffer.isView(this.body)) {
return Body.Promise.resolve(Buffer.from(this.body.buffer, this.body.byteOffset, this.body.byteLength));
}
// istanbul ignore if: should never happen
if (!(this.body instanceof Stream)) {
if (!(this.body instanceof Stream__default)) {
return Body.Promise.resolve(Buffer.alloc(0));

@@ -420,3 +431,3 @@ }

try {
resolve(Buffer.concat(accum));
resolve(Buffer.concat(accum, accumBytes));
} catch (err) {

@@ -523,3 +534,3 @@ // handle streams that have accumulated too much data (issue #414)

// note: we can't clone the form-data object without having it as a dependency
if (body instanceof Stream && typeof body.getBoundary !== 'function') {
if (body instanceof Stream__default && typeof body.getBoundary !== 'function') {
// tee instance body

@@ -547,8 +558,5 @@ p1 = new PassThrough();

*/
function extractContentType(instance) {
const body = instance.body;
function extractContentType(body) {
// istanbul ignore if: Currently, because of a guard in Request, body
// can never be null. Included here for completeness.
if (body === null) {

@@ -578,6 +586,9 @@ // body is null

return `multipart/form-data;boundary=${body.getBoundary()}`;
} else {
} else if (body instanceof Stream__default) {
// body is stream
// can't really do much about this
return null;
} else {
// Body constructor defaults other things to string
return 'text/plain;charset=UTF-8';
}

@@ -603,20 +614,5 @@ }

return 0;
} else if (typeof body === 'string') {
// body is string
return Buffer.byteLength(body);
} else if (isURLSearchParams(body)) {
// body is URLSearchParams
return Buffer.byteLength(String(body));
} else if (body instanceof Blob) {
// body is blob
return body.size;
} else if (Buffer.isBuffer(body)) {
// body is buffer
return body.length;
} else if (Object.prototype.toString.call(body) === '[object ArrayBuffer]') {
// body is ArrayBuffer
return body.byteLength;
} else if (ArrayBuffer.isView(body)) {
// body is ArrayBufferView
return body.byteLength;
} else if (body && typeof body.getLengthSync === 'function') {

@@ -650,14 +646,2 @@ // detect form data input from form-data module

dest.end();
} else if (typeof body === 'string') {
// body is string
dest.write(body);
dest.end();
} else if (isURLSearchParams(body)) {
// body is URLSearchParams
dest.write(Buffer.from(String(body)));
dest.end();
} else if (body instanceof Blob) {
// body is blob
dest.write(body[BUFFER]);
dest.end();
} else if (Buffer.isBuffer(body)) {

@@ -667,10 +651,2 @@ // body is buffer

dest.end();
} else if (Object.prototype.toString.call(body) === '[object ArrayBuffer]') {
// body is ArrayBuffer
dest.write(Buffer.from(body));
dest.end();
} else if (ArrayBuffer.isView(body)) {
// body is ArrayBufferView
dest.write(Buffer.from(body.buffer, body.byteOffset, body.byteLength));
dest.end();
} else {

@@ -696,3 +672,3 @@ // body is stream

name = `${name}`;
if (invalidTokenRegex.test(name)) {
if (invalidTokenRegex.test(name) || name === '') {
throw new TypeError(`${name} is not a legal HTTP header name`);

@@ -1084,3 +1060,11 @@ }

const status = opts.status || 200;
const headers = new Headers(opts.headers);
if (body != null && !headers.has('Content-Type')) {
const contentType = extractContentType(body);
if (contentType) {
headers.append('Content-Type', contentType);
}
}
this[INTERNALS$1] = {

@@ -1090,3 +1074,3 @@ url: opts.url,

statusText: opts.statusText || STATUS_CODES[status],
headers: new Headers(opts.headers)
headers
};

@@ -1158,3 +1142,3 @@ }

const streamDestructionSupported = 'destroy' in Stream.Readable.prototype;
const streamDestructionSupported = 'destroy' in Stream__default.Readable.prototype;

@@ -1221,5 +1205,5 @@ /**

if (init.body != null) {
const contentType = extractContentType(this);
if (contentType !== null && !headers.has('Content-Type')) {
if (inputBody != null && !headers.has('Content-Type')) {
const contentType = extractContentType(inputBody);
if (contentType) {
headers.append('Content-Type', contentType);

@@ -1323,3 +1307,3 @@ }

if (request.signal && request.body instanceof Stream.Readable && !streamDestructionSupported) {
if (request.signal && request.body instanceof Stream__default.Readable && !streamDestructionSupported) {
throw new Error('Cancellation of streamed requests with AbortSignal is not supported in node < 8');

@@ -1394,3 +1378,3 @@ }

// fix an issue where "PassThrough", "resolve" aren't a named export for node <10
const PassThrough$1 = Stream.PassThrough;
const PassThrough$1 = Stream__default.PassThrough;
const resolve_url = Url.resolve;

@@ -1428,3 +1412,3 @@

reject(error);
if (request.body && request.body instanceof Stream.Readable) {
if (request.body && request.body instanceof Stream__default.Readable) {
request.body.destroy(error);

@@ -1528,3 +1512,4 @@ }

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

@@ -1621,2 +1606,10 @@

// for br
if (codings == 'br' && typeof zlib.createBrotliDecompress === 'function') {
body = body.pipe(zlib.createBrotliDecompress());
response = new Response(body, response_options);
resolve(response);
return;
}
// otherwise, use response as-is

@@ -1623,0 +1616,0 @@ response = new Response(body, response_options);

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

@@ -40,6 +40,6 @@ "main": "lib/index",

"devDependencies": {
"abort-controller": "^1.0.2",
"abortcontroller-polyfill": "^1.1.9",
"babel-core": "^6.26.0",
"babel-plugin-istanbul": "^4.1.5",
"abort-controller": "^1.1.0",
"abortcontroller-polyfill": "^1.3.0",
"babel-core": "^6.26.3",
"babel-plugin-istanbul": "^4.1.6",
"babel-preset-env": "^1.6.1",

@@ -51,5 +51,5 @@ "babel-register": "^6.16.3",

"chai-string": "~1.3.0",
"codecov": "^3.0.0",
"cross-env": "^5.1.3",
"form-data": "^2.3.1",
"codecov": "^3.3.0",
"cross-env": "^5.2.0",
"form-data": "^2.3.3",
"is-builtin-module": "^1.0.0",

@@ -59,7 +59,7 @@ "mocha": "^5.0.0",

"parted": "^0.1.1",
"promise": "^8.0.1",
"promise": "^8.0.3",
"resumer": "0.0.0",
"rollup": "^0.63.4",
"rollup-plugin-babel": "^3.0.3",
"string-to-arraybuffer": "^1.0.0",
"rollup-plugin-babel": "^3.0.7",
"string-to-arraybuffer": "^1.0.2",
"url-search-params": "^1.0.2",

@@ -66,0 +66,0 @@ "whatwg-url": "^5.0.0"

@@ -11,3 +11,3 @@ node-fetch

(We are looking for [v2 maintainers and collaborators](https://github.com/bitinn/node-fetch/issues/252))
(We are looking for [v2 maintainers and collaborators](https://github.com/bitinn/node-fetch/issues/567))

@@ -262,3 +262,3 @@ <!-- TOC -->

```js
import AbortContoller from 'abort-controller';
import AbortController from 'abort-controller';

@@ -527,3 +527,3 @@ const controller = new AbortController();

[codecov-url]: https://codecov.io/gh/bitinn/node-fetch
[install-size-image]: https://packagephobia.now.sh/badge?p=node-fetch
[install-size-image]: https://flat.badgen.net/packagephobia/install/node-fetch
[install-size-url]: https://packagephobia.now.sh/result?p=node-fetch

@@ -530,0 +530,0 @@ [whatwg-fetch]: https://fetch.spec.whatwg.org/

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