Socket
Socket
Sign inDemoInstall

node-fetch

Package Overview
Dependencies
Maintainers
5
Versions
96
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

node-fetch - npm Package Compare versions

Comparing version 3.1.0 to 3.1.1

7

package.json
{
"name": "node-fetch",
"version": "3.1.0",
"version": "3.1.1",
"description": "A light-weight module that brings Fetch API to node.js",

@@ -61,2 +61,3 @@ "main": "./src/index.js",

"p-timeout": "^5.0.0",
"stream-consumers": "^1.0.1",
"tsd": "^0.14.0",

@@ -67,4 +68,4 @@ "xo": "^0.39.1"

"data-uri-to-buffer": "^4.0.0",
"formdata-polyfill": "^4.0.10",
"fetch-blob": "^3.1.2"
"fetch-blob": "^3.1.3",
"formdata-polyfill": "^4.0.10"
},

@@ -71,0 +72,0 @@ "tsd": {

@@ -44,3 +44,3 @@ <div align="center">

- [Extract Set-Cookie Header](#extract-set-cookie-header)
- [Post data using a file stream](#post-data-using-a-file-stream)
- [Post data using a file](#post-data-using-a-file)
- [Request cancellation with AbortSignal](#request-cancellation-with-abortsignal)

@@ -299,5 +299,5 @@ - [API](#api)

```js
import {createWriteStream} from 'fs';
import {pipeline} from 'stream';
import {promisify} from 'util'
import {createWriteStream} from 'node:fs';
import {pipeline} from 'node:stream';
import {promisify} from 'node:util'
import fetch from 'node-fetch';

@@ -408,3 +408,3 @@

import fetch from 'node-fetch';
import {FormData} from 'formdata-polyfill/esm-min.js';
import {FormData} from 'formdata-polyfill/esm.min.js';

@@ -523,4 +523,4 @@ // Alternative hack to get the same FormData instance as node-fetch

```js
import http from 'http';
import https from 'https';
import http from 'node:http';
import https from 'node:https';

@@ -583,3 +583,20 @@ const httpAgent = new http.Agent({

#### Manual Redirect
The `redirect: 'manual'` option for node-fetch is different from the browser & specification, which
results in an [opaque-redirect filtered response](https://fetch.spec.whatwg.org/#concept-filtered-response-opaque-redirect).
node-fetch gives you the typical [basic filtered response](https://fetch.spec.whatwg.org/#concept-filtered-response-basic) instead.
```js
const fetch = require('node-fetch');
const response = await fetch('https://httpbin.org/status/301', { redirect: 'manual' });
if (response.status === 301 || response.status === 302) {
const locationURL = new URL(response.headers.get('location'), response.url);
const response2 = await fetch(locationURL, { redirect: 'manual' });
console.dir(response2);
}
```
<a id="class-request"></a>

@@ -758,3 +775,3 @@

```sh
npm install --save-dev @types/node-fetch
npm install --save-dev @types/node-fetch@2.x
```

@@ -761,0 +778,0 @@

@@ -9,3 +9,4 @@

import Stream, {PassThrough} from 'node:stream';
import {types, deprecate} from 'node:util';
import {types, deprecate, promisify} from 'node:util';
import {Buffer} from 'node:buffer';

@@ -19,2 +20,3 @@ import Blob from 'fetch-blob';

const pipeline = promisify(Stream.pipeline);
const INTERNALS = Symbol('Body internals');

@@ -135,3 +137,3 @@

const ct = (this.headers && this.headers.get('content-type')) || (this[INTERNALS].body && this[INTERNALS].body.type) || '';
const buf = await this.buffer();
const buf = await this.arrayBuffer();

@@ -182,3 +184,6 @@ return new Blob([buf], {

json: {enumerable: true},
text: {enumerable: true}
text: {enumerable: true},
data: {get: deprecate(() => {},
'data doesn\'t exist, use json(), text(), arrayBuffer(), or body instead',
'https://github.com/node-fetch/node-fetch/issues/1000 (response)')}
});

@@ -386,5 +391,5 @@

* @param obj.body Body object from the Body instance.
* @returns {void}
* @returns {Promise<void>}
*/
export const writeToStream = (dest, {body}) => {
export const writeToStream = async (dest, {body}) => {
if (body === null) {

@@ -395,4 +400,4 @@ // Body is null

// Body is stream
body.pipe(dest);
await pipeline(body, dest);
}
};

@@ -10,2 +10,3 @@ /**

/* c8 ignore next 9 */
const validateHeaderName = typeof http.validateHeaderName === 'function' ?

@@ -21,2 +22,3 @@ http.validateHeaderName :

/* c8 ignore next 9 */
const validateHeaderValue = typeof http.validateHeaderValue === 'function' ?

@@ -146,4 +148,4 @@ http.validateHeaderValue :

}
/* c8 ignore next */
});
/* c8 ignore next */
}

@@ -150,0 +152,0 @@

@@ -13,2 +13,4 @@ /**

import Stream, {PassThrough, pipeline as pump} from 'node:stream';
import {Buffer} from 'node:buffer';
import dataUriToBuffer from 'data-uri-to-buffer';

@@ -23,2 +25,3 @@

import {isRedirect} from './utils/is-redirect.js';
import {isDomainOrSubdomain} from './utils/is.js';
import {parseReferrerPolicyFromHeader} from './utils/referrer.js';

@@ -83,3 +86,3 @@

// Send request
const request_ = send(parsedURL, options);
const request_ = send(parsedURL.toString(), options);

@@ -136,3 +139,15 @@ if (signal) {

// HTTP fetch step 5.3
const locationURL = location === null ? null : new URL(location, request.url);
let locationURL = null;
try {
locationURL = location === null ? null : new URL(location, request.url);
} catch {
// error here can only be invalid URL in Location: header
// do not throw when options.redirect == manual
// let the user extract the errorneous redirect URL
if (request.redirect !== 'manual') {
reject(new FetchError(`uri requested responds with an invalid redirect URL: ${location}`, 'invalid-redirect'));
finalize();
return;
}
}

@@ -146,7 +161,3 @@ // HTTP fetch step 5.5

case 'manual':
// Node-fetch-specific step: make manual redirect a bit easier to use by setting the Location header value to the resolved URL.
if (locationURL !== null) {
headers.set('Location', locationURL);
}
// Nothing to do
break;

@@ -182,2 +193,14 @@ case 'follow': {

// when forwarding sensitive headers like "Authorization",
// "WWW-Authenticate", and "Cookie" to untrusted targets,
// headers will be ignored when following a redirect to a domain
// that is not a subdomain match or exact match of the initial domain.
// For example, a redirect from "foo.com" to either "foo.com" or "sub.foo.com"
// will forward the sensitive headers, but a redirect to "bar.com" will not.
if (!isDomainOrSubdomain(request.url, locationURL)) {
for (const name of ['authorization', 'www-authenticate', 'cookie', 'cookie2']) {
requestOptions.headers.delete(name);
}
}
// HTTP-redirect fetch step 9

@@ -223,2 +246,3 @@ if (response_.statusCode !== 303 && request.body && options_.body instanceof Stream.Readable) {

// see https://github.com/nodejs/node/pull/29376
/* c8 ignore next 3 */
if (process.version < 'v12.10') {

@@ -301,3 +325,4 @@ response_.on('aborted', abortAndFinalize);

writeToStream(request_, request);
// eslint-disable-next-line promise/prefer-await-to-then
writeToStream(request_, request).catch(reject);
});

@@ -304,0 +329,0 @@ }

@@ -1,2 +0,1 @@

/**

@@ -11,2 +10,3 @@ * Request.js

import {format as formatUrl} from 'node:url';
import {deprecate} from 'node:util';
import Headers from './headers.js';

@@ -25,3 +25,3 @@ import Body, {clone, extractContentType, getTotalBytes} from './body.js';

*
* @param {*} obj
* @param {*} object
* @return {boolean}

@@ -36,2 +36,6 @@ */

const doBadDataWarn = deprecate(() => {},
'.data is not a valid RequestInit property, use .body instead',
'https://github.com/node-fetch/node-fetch/issues/1000 (request)');
/**

@@ -65,4 +69,8 @@ * Request class

if ('data' in init) {
doBadDataWarn();
}
// eslint-disable-next-line no-eq-null, eqeqeq
if (((init.body != null || isRequest(input)) && input.body !== null) &&
if ((init.body != null || (isRequest(input) && input.body !== null)) &&
(method === 'GET' || method === 'HEAD')) {

@@ -140,2 +148,3 @@ throw new TypeError('Request with GET/HEAD method cannot have body');

/** @returns {string} */
get method() {

@@ -145,2 +154,3 @@ return this[INTERNALS].method;

/** @returns {string} */
get url() {

@@ -150,2 +160,3 @@ return formatUrl(this[INTERNALS].parsedURL);

/** @returns {Headers} */
get headers() {

@@ -159,2 +170,3 @@ return this[INTERNALS].headers;

/** @returns {AbortSignal} */
get signal() {

@@ -217,4 +229,4 @@ return this[INTERNALS].signal;

*
* @param Request A Request instance
* @return Object The options object to be passed to http.request
* @param {Request} request - A Request instance
* @return The options object to be passed to http.request
*/

@@ -308,2 +320,3 @@ export const getNodeRequestOptions = request => {

return {
/** @type {URL} */
parsedURL,

@@ -310,0 +323,0 @@ options

@@ -59,1 +59,18 @@ /**

};
/**
* isDomainOrSubdomain reports whether sub is a subdomain (or exact match) of
* the parent domain.
*
* Both domains must already be in canonical form.
* @param {string|URL} original
* @param {string|URL} destination
*/
export const isDomainOrSubdomain = (destination, original) => {
const orig = new URL(original).hostname;
const dest = new URL(destination).hostname;
return orig === dest || (
orig[orig.length - dest.length - 1] === '.' && orig.endsWith(dest)
);
};

@@ -1,2 +0,2 @@

import {isIP} from 'net';
import {isIP} from 'node:net';

@@ -3,0 +3,0 @@ /**

SocketSocket SOC 2 Logo

Product

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

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc