@whatwg-node/node-fetch 0.7.22-alpha-20250710160716-6df7209d12299dba404ac539d834654be5d43990 → 0.7.23-alpha-20250725190806-5df0ede70a22656416fd7a0f626f8d5ba8238197
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/cjs/Body.js +4 -2
- package/cjs/fetchCurl.js +7 -5
- package/cjs/fetchNodeHttp.js +3 -3
- package/cjs/utils.js +33 -16
- package/esm/Body.js +6 -4
- package/esm/fetchCurl.js +9 -7
- package/esm/fetchNodeHttp.js +4 -4
- package/esm/utils.js +32 -15
- package/package.json +1 -1
- package/typings/utils.d.cts +6 -7
- package/typings/utils.d.ts +6 -7
package/cjs/Body.js
CHANGED
@@ -457,8 +457,10 @@ function processBodyInit(bodyInit, signal) {
|
|
457
457
|
};
|
458
458
|
}
|
459
459
|
if (bodyInit instanceof node_http_1.IncomingMessage) {
|
460
|
-
const passThrough =
|
461
|
-
|
460
|
+
const passThrough = new node_stream_1.PassThrough();
|
461
|
+
(0, utils_js_1.pipeThrough)({
|
462
|
+
src: bodyInit,
|
463
|
+
dest: passThrough,
|
462
464
|
signal,
|
463
465
|
});
|
464
466
|
return {
|
package/cjs/fetchCurl.js
CHANGED
@@ -107,8 +107,10 @@ function fetchCurl(fetchRequest) {
|
|
107
107
|
}
|
108
108
|
});
|
109
109
|
curlHandle.once('stream', function streamListener(stream, status, headersBuf) {
|
110
|
-
const
|
111
|
-
|
110
|
+
const passThrough = new node_stream_1.PassThrough();
|
111
|
+
(0, utils_js_1.pipeThrough)({
|
112
|
+
src: stream,
|
113
|
+
dest: passThrough,
|
112
114
|
signal,
|
113
115
|
onError: deferredPromise.reject,
|
114
116
|
});
|
@@ -123,7 +125,7 @@ function fetchCurl(fetchRequest) {
|
|
123
125
|
if (!stream.destroyed) {
|
124
126
|
stream.resume();
|
125
127
|
}
|
126
|
-
|
128
|
+
passThrough.destroy();
|
127
129
|
deferredPromise.reject(new Error('redirect is not allowed'));
|
128
130
|
}
|
129
131
|
return true;
|
@@ -131,14 +133,14 @@ function fetchCurl(fetchRequest) {
|
|
131
133
|
return false;
|
132
134
|
});
|
133
135
|
const headersInit = headersFlat.map(headerFlat => headerFlat.split(/:\s(.+)/).slice(0, 2));
|
134
|
-
const ponyfillResponse = new Response_js_1.PonyfillResponse(
|
136
|
+
const ponyfillResponse = new Response_js_1.PonyfillResponse(passThrough, {
|
135
137
|
status,
|
136
138
|
headers: headersInit,
|
137
139
|
url: curlHandle.getInfo(Curl.info.REDIRECT_URL)?.toString() || fetchRequest.url,
|
138
140
|
redirected: Number(curlHandle.getInfo(Curl.info.REDIRECT_COUNT)) > 0,
|
139
141
|
});
|
140
142
|
deferredPromise.resolve(ponyfillResponse);
|
141
|
-
streamResolved =
|
143
|
+
streamResolved = passThrough;
|
142
144
|
});
|
143
145
|
setImmediate(() => {
|
144
146
|
curlHandle.perform();
|
package/cjs/fetchNodeHttp.js
CHANGED
@@ -96,9 +96,9 @@ function fetchNodeHttp(fetchRequest) {
|
|
96
96
|
}
|
97
97
|
}
|
98
98
|
if (outputStream != null) {
|
99
|
-
|
100
|
-
|
101
|
-
|
99
|
+
(0, utils_js_1.pipeThrough)({
|
100
|
+
src: nodeResponse,
|
101
|
+
dest: outputStream,
|
102
102
|
signal,
|
103
103
|
onError: reject,
|
104
104
|
});
|
package/cjs/utils.js
CHANGED
@@ -7,12 +7,10 @@ exports.isArrayBufferView = isArrayBufferView;
|
|
7
7
|
exports.isNodeReadable = isNodeReadable;
|
8
8
|
exports.isIterable = isIterable;
|
9
9
|
exports.shouldRedirect = shouldRedirect;
|
10
|
-
exports.
|
10
|
+
exports.pipeThrough = pipeThrough;
|
11
11
|
exports.endStream = endStream;
|
12
12
|
exports.safeWrite = safeWrite;
|
13
13
|
const node_events_1 = require("node:events");
|
14
|
-
const node_stream_1 = require("node:stream");
|
15
|
-
const promises_1 = require("node:stream/promises");
|
16
14
|
function isHeadersInstance(obj) {
|
17
15
|
return obj?.forEach != null;
|
18
16
|
}
|
@@ -51,20 +49,39 @@ function isIterable(value) {
|
|
51
49
|
function shouldRedirect(status) {
|
52
50
|
return status === 301 || status === 302 || status === 303 || status === 307 || status === 308;
|
53
51
|
}
|
54
|
-
function
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
}
|
61
|
-
|
62
|
-
if (
|
63
|
-
|
52
|
+
function pipeThrough({ src, dest, signal, onError, }) {
|
53
|
+
if (onError) {
|
54
|
+
// listen for errors on the destination stream if necessary. if the readable
|
55
|
+
// stream (src) emits an error, the writable destination (dest) will be
|
56
|
+
// destroyed with that error (see below)
|
57
|
+
dest.once('error', onError);
|
58
|
+
}
|
59
|
+
src.once('error', (e) => {
|
60
|
+
// if the readable stream (src) emits an error during pipe, the writable
|
61
|
+
// destination (dest) is not closed automatically. that needs to be
|
62
|
+
// done manually. the readable stream is closed when error is emitted,
|
63
|
+
// so only the writable destination needs to be destroyed
|
64
|
+
dest.destroy(e);
|
65
|
+
});
|
66
|
+
if (signal) {
|
67
|
+
function handleAbort() {
|
68
|
+
try {
|
69
|
+
signal.throwIfAborted();
|
70
|
+
}
|
71
|
+
catch (abortError) {
|
72
|
+
// destroying the src stream will destroy the dest stream as well
|
73
|
+
src.destroy(abortError);
|
74
|
+
}
|
64
75
|
}
|
65
|
-
|
66
|
-
|
67
|
-
|
76
|
+
if (signal.aborted) {
|
77
|
+
// if the signal is already aborted, we can just destroy the
|
78
|
+
// src stream and not start pipe at all
|
79
|
+
handleAbort();
|
80
|
+
return;
|
81
|
+
}
|
82
|
+
signal.addEventListener('abort', handleAbort, { once: true });
|
83
|
+
}
|
84
|
+
src.pipe(dest, { end: true /* already default */ });
|
68
85
|
}
|
69
86
|
function endStream(stream) {
|
70
87
|
// @ts-expect-error Avoid arguments adaptor trampoline https://v8.dev/blog/adaptor-frame
|
package/esm/Body.js
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
2
2
|
import { Buffer } from 'node:buffer';
|
3
3
|
import { IncomingMessage } from 'node:http';
|
4
|
-
import { addAbortSignal, Readable } from 'node:stream';
|
4
|
+
import { addAbortSignal, PassThrough, Readable } from 'node:stream';
|
5
5
|
import { Busboy } from '@fastify/busboy';
|
6
6
|
import { handleMaybePromise } from '@whatwg-node/promise-helpers';
|
7
7
|
import { hasArrayBufferMethod, hasBufferMethod, hasBytesMethod, PonyfillBlob } from './Blob.js';
|
8
8
|
import { PonyfillFile } from './File.js';
|
9
9
|
import { getStreamFromFormData, PonyfillFormData } from './FormData.js';
|
10
10
|
import { PonyfillReadableStream } from './ReadableStream.js';
|
11
|
-
import { fakePromise, isArrayBufferView,
|
11
|
+
import { fakePromise, isArrayBufferView, pipeThrough } from './utils.js';
|
12
12
|
var BodyInitType;
|
13
13
|
(function (BodyInitType) {
|
14
14
|
BodyInitType["ReadableStream"] = "ReadableStream";
|
@@ -453,8 +453,10 @@ function processBodyInit(bodyInit, signal) {
|
|
453
453
|
};
|
454
454
|
}
|
455
455
|
if (bodyInit instanceof IncomingMessage) {
|
456
|
-
const passThrough =
|
457
|
-
|
456
|
+
const passThrough = new PassThrough();
|
457
|
+
pipeThrough({
|
458
|
+
src: bodyInit,
|
459
|
+
dest: passThrough,
|
458
460
|
signal,
|
459
461
|
});
|
460
462
|
return {
|
package/esm/fetchCurl.js
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
import { Readable } from 'node:stream';
|
1
|
+
import { PassThrough, Readable } from 'node:stream';
|
2
2
|
import { rootCertificates } from 'node:tls';
|
3
3
|
import { createDeferredPromise } from '@whatwg-node/promise-helpers';
|
4
4
|
import { PonyfillResponse } from './Response.js';
|
5
|
-
import { defaultHeadersSerializer, isNodeReadable,
|
5
|
+
import { defaultHeadersSerializer, isNodeReadable, pipeThrough, shouldRedirect } from './utils.js';
|
6
6
|
export function fetchCurl(fetchRequest) {
|
7
7
|
const { Curl, CurlFeature, CurlPause, CurlProgressFunc } = globalThis['libcurl'];
|
8
8
|
const curlHandle = new Curl();
|
@@ -104,8 +104,10 @@ export function fetchCurl(fetchRequest) {
|
|
104
104
|
}
|
105
105
|
});
|
106
106
|
curlHandle.once('stream', function streamListener(stream, status, headersBuf) {
|
107
|
-
const
|
108
|
-
|
107
|
+
const passThrough = new PassThrough();
|
108
|
+
pipeThrough({
|
109
|
+
src: stream,
|
110
|
+
dest: passThrough,
|
109
111
|
signal,
|
110
112
|
onError: deferredPromise.reject,
|
111
113
|
});
|
@@ -120,7 +122,7 @@ export function fetchCurl(fetchRequest) {
|
|
120
122
|
if (!stream.destroyed) {
|
121
123
|
stream.resume();
|
122
124
|
}
|
123
|
-
|
125
|
+
passThrough.destroy();
|
124
126
|
deferredPromise.reject(new Error('redirect is not allowed'));
|
125
127
|
}
|
126
128
|
return true;
|
@@ -128,14 +130,14 @@ export function fetchCurl(fetchRequest) {
|
|
128
130
|
return false;
|
129
131
|
});
|
130
132
|
const headersInit = headersFlat.map(headerFlat => headerFlat.split(/:\s(.+)/).slice(0, 2));
|
131
|
-
const ponyfillResponse = new PonyfillResponse(
|
133
|
+
const ponyfillResponse = new PonyfillResponse(passThrough, {
|
132
134
|
status,
|
133
135
|
headers: headersInit,
|
134
136
|
url: curlHandle.getInfo(Curl.info.REDIRECT_URL)?.toString() || fetchRequest.url,
|
135
137
|
redirected: Number(curlHandle.getInfo(Curl.info.REDIRECT_COUNT)) > 0,
|
136
138
|
});
|
137
139
|
deferredPromise.resolve(ponyfillResponse);
|
138
|
-
streamResolved =
|
140
|
+
streamResolved = passThrough;
|
139
141
|
});
|
140
142
|
setImmediate(() => {
|
141
143
|
curlHandle.perform();
|
package/esm/fetchNodeHttp.js
CHANGED
@@ -6,7 +6,7 @@ import { handleMaybePromise } from '@whatwg-node/promise-helpers';
|
|
6
6
|
import { PonyfillRequest } from './Request.js';
|
7
7
|
import { PonyfillResponse } from './Response.js';
|
8
8
|
import { PonyfillURL } from './URL.js';
|
9
|
-
import { endStream, getHeadersObj, isNodeReadable, safeWrite, shouldRedirect,
|
9
|
+
import { endStream, getHeadersObj, isNodeReadable, pipeThrough, safeWrite, shouldRedirect, } from './utils.js';
|
10
10
|
function getRequestFnForProtocol(url) {
|
11
11
|
if (url.startsWith('http:')) {
|
12
12
|
return httpRequest;
|
@@ -93,9 +93,9 @@ export function fetchNodeHttp(fetchRequest) {
|
|
93
93
|
}
|
94
94
|
}
|
95
95
|
if (outputStream != null) {
|
96
|
-
|
97
|
-
|
98
|
-
|
96
|
+
pipeThrough({
|
97
|
+
src: nodeResponse,
|
98
|
+
dest: outputStream,
|
99
99
|
signal,
|
100
100
|
onError: reject,
|
101
101
|
});
|
package/esm/utils.js
CHANGED
@@ -1,6 +1,4 @@
|
|
1
1
|
import { once } from 'node:events';
|
2
|
-
import { PassThrough } from 'node:stream';
|
3
|
-
import { pipeline } from 'node:stream/promises';
|
4
2
|
function isHeadersInstance(obj) {
|
5
3
|
return obj?.forEach != null;
|
6
4
|
}
|
@@ -38,20 +36,39 @@ export function isIterable(value) {
|
|
38
36
|
export function shouldRedirect(status) {
|
39
37
|
return status === 301 || status === 302 || status === 303 || status === 307 || status === 308;
|
40
38
|
}
|
41
|
-
export function
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
}
|
48
|
-
|
49
|
-
if (
|
50
|
-
|
39
|
+
export function pipeThrough({ src, dest, signal, onError, }) {
|
40
|
+
if (onError) {
|
41
|
+
// listen for errors on the destination stream if necessary. if the readable
|
42
|
+
// stream (src) emits an error, the writable destination (dest) will be
|
43
|
+
// destroyed with that error (see below)
|
44
|
+
dest.once('error', onError);
|
45
|
+
}
|
46
|
+
src.once('error', (e) => {
|
47
|
+
// if the readable stream (src) emits an error during pipe, the writable
|
48
|
+
// destination (dest) is not closed automatically. that needs to be
|
49
|
+
// done manually. the readable stream is closed when error is emitted,
|
50
|
+
// so only the writable destination needs to be destroyed
|
51
|
+
dest.destroy(e);
|
52
|
+
});
|
53
|
+
if (signal) {
|
54
|
+
function handleAbort() {
|
55
|
+
try {
|
56
|
+
signal.throwIfAborted();
|
57
|
+
}
|
58
|
+
catch (abortError) {
|
59
|
+
// destroying the src stream will destroy the dest stream as well
|
60
|
+
src.destroy(abortError);
|
61
|
+
}
|
51
62
|
}
|
52
|
-
|
53
|
-
|
54
|
-
|
63
|
+
if (signal.aborted) {
|
64
|
+
// if the signal is already aborted, we can just destroy the
|
65
|
+
// src stream and not start pipe at all
|
66
|
+
handleAbort();
|
67
|
+
return;
|
68
|
+
}
|
69
|
+
signal.addEventListener('abort', handleAbort, { once: true });
|
70
|
+
}
|
71
|
+
src.pipe(dest, { end: true /* already default */ });
|
55
72
|
}
|
56
73
|
export function endStream(stream) {
|
57
74
|
// @ts-expect-error Avoid arguments adaptor trampoline https://v8.dev/blog/adaptor-frame
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@whatwg-node/node-fetch",
|
3
|
-
"version": "0.7.
|
3
|
+
"version": "0.7.23-alpha-20250725190806-5df0ede70a22656416fd7a0f626f8d5ba8238197",
|
4
4
|
"description": "Fetch API implementation for Node",
|
5
5
|
"sideEffects": false,
|
6
6
|
"dependencies": {
|
package/typings/utils.d.cts
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
import {
|
2
|
-
import { PassThrough, Readable, Writable } from 'node:stream';
|
1
|
+
import { Readable, Writable } from 'node:stream';
|
3
2
|
export declare function getHeadersObj(headers: Headers): Record<string, string>;
|
4
3
|
export declare function defaultHeadersSerializer(headers: Headers, onContentLength?: (value: string) => void): string[];
|
5
4
|
export { fakePromise } from '@whatwg-node/promise-helpers';
|
@@ -7,12 +6,12 @@ export declare function isArrayBufferView(obj: any): obj is ArrayBufferView;
|
|
7
6
|
export declare function isNodeReadable(obj: any): obj is Readable;
|
8
7
|
export declare function isIterable(value: any): value is Iterable<unknown>;
|
9
8
|
export declare function shouldRedirect(status?: number): boolean;
|
10
|
-
export declare function
|
11
|
-
|
12
|
-
|
9
|
+
export declare function pipeThrough({ src, dest, signal, onError, }: {
|
10
|
+
src: Readable;
|
11
|
+
dest: Writable;
|
13
12
|
signal?: AbortSignal | undefined;
|
14
|
-
onError?: (e: Error) => void;
|
15
|
-
}):
|
13
|
+
onError?: ((e: Error) => void) | undefined;
|
14
|
+
}): void;
|
16
15
|
export declare function endStream(stream: {
|
17
16
|
end: () => void;
|
18
17
|
}): void;
|
package/typings/utils.d.ts
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
import {
|
2
|
-
import { PassThrough, Readable, Writable } from 'node:stream';
|
1
|
+
import { Readable, Writable } from 'node:stream';
|
3
2
|
export declare function getHeadersObj(headers: Headers): Record<string, string>;
|
4
3
|
export declare function defaultHeadersSerializer(headers: Headers, onContentLength?: (value: string) => void): string[];
|
5
4
|
export { fakePromise } from '@whatwg-node/promise-helpers';
|
@@ -7,12 +6,12 @@ export declare function isArrayBufferView(obj: any): obj is ArrayBufferView;
|
|
7
6
|
export declare function isNodeReadable(obj: any): obj is Readable;
|
8
7
|
export declare function isIterable(value: any): value is Iterable<unknown>;
|
9
8
|
export declare function shouldRedirect(status?: number): boolean;
|
10
|
-
export declare function
|
11
|
-
|
12
|
-
|
9
|
+
export declare function pipeThrough({ src, dest, signal, onError, }: {
|
10
|
+
src: Readable;
|
11
|
+
dest: Writable;
|
13
12
|
signal?: AbortSignal | undefined;
|
14
|
-
onError?: (e: Error) => void;
|
15
|
-
}):
|
13
|
+
onError?: ((e: Error) => void) | undefined;
|
14
|
+
}): void;
|
16
15
|
export declare function endStream(stream: {
|
17
16
|
end: () => void;
|
18
17
|
}): void;
|