@whatwg-node/node-fetch 0.7.20-alpha-20250515210136-f3eeba6bfbd13f3930315ee75f80a9091e946e92 → 0.7.20-alpha-20250516115150-ce23c7139392555706532687427aa8535aae5852
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 +24 -8
- package/cjs/Headers.js +30 -8
- package/cjs/Request.js +4 -2
- package/cjs/Response.js +28 -8
- package/cjs/fetchCurl.js +14 -8
- package/cjs/fetchNodeHttp.js +15 -5
- package/cjs/utils.js +9 -0
- package/esm/Body.js +24 -8
- package/esm/Headers.js +30 -8
- package/esm/Request.js +4 -2
- package/esm/Response.js +28 -8
- package/esm/fetchCurl.js +14 -8
- package/esm/fetchNodeHttp.js +15 -5
- package/esm/utils.js +8 -0
- package/package.json +1 -1
- package/typings/Body.d.cts +2 -2
- package/typings/Body.d.ts +2 -2
- package/typings/Request.d.cts +1 -1
- package/typings/Request.d.ts +1 -1
- package/typings/utils.d.cts +1 -0
- package/typings/utils.d.ts +1 -0
package/cjs/Body.js
CHANGED
@@ -28,11 +28,11 @@ class PonyfillBody {
|
|
28
28
|
bodyUsed = false;
|
29
29
|
contentType = null;
|
30
30
|
contentLength = null;
|
31
|
-
|
31
|
+
_signal = null;
|
32
32
|
constructor(bodyInit, options = {}) {
|
33
33
|
this.bodyInit = bodyInit;
|
34
34
|
this.options = options;
|
35
|
-
this.
|
35
|
+
this._signal = options.signal || null;
|
36
36
|
const { bodyFactory, contentType, contentLength, bodyType, buffer } = processBodyInit(bodyInit, options?.signal);
|
37
37
|
this._bodyFactory = bodyFactory;
|
38
38
|
this.contentType = contentType;
|
@@ -150,6 +150,13 @@ class PonyfillBody {
|
|
150
150
|
if (this._blob) {
|
151
151
|
return (0, utils_js_1.fakePromise)(this._blob);
|
152
152
|
}
|
153
|
+
if (this.bodyType === BodyInitType.String) {
|
154
|
+
this._text = this.bodyInit;
|
155
|
+
this._blob = new Blob_js_1.PonyfillBlob([this._text], {
|
156
|
+
type: this.contentType || 'text/plain;charset=UTF-8',
|
157
|
+
size: this.contentLength,
|
158
|
+
});
|
159
|
+
}
|
153
160
|
if (this.bodyType === BodyInitType.Blob) {
|
154
161
|
this._blob = this.bodyInit;
|
155
162
|
return (0, utils_js_1.fakePromise)(this._blob);
|
@@ -205,8 +212,8 @@ class PonyfillBody {
|
|
205
212
|
limits: formDataLimits,
|
206
213
|
defCharset: 'utf-8',
|
207
214
|
});
|
208
|
-
if (this.
|
209
|
-
(0, node_stream_1.addAbortSignal)(this.
|
215
|
+
if (this._signal) {
|
216
|
+
(0, node_stream_1.addAbortSignal)(this._signal, bb);
|
210
217
|
}
|
211
218
|
let completed = false;
|
212
219
|
const complete = (err) => {
|
@@ -279,6 +286,17 @@ class PonyfillBody {
|
|
279
286
|
if (this._buffer) {
|
280
287
|
return (0, utils_js_1.fakePromise)(this._buffer);
|
281
288
|
}
|
289
|
+
if (this._text) {
|
290
|
+
this._buffer = node_buffer_1.Buffer.from(this._text, 'utf-8');
|
291
|
+
return (0, utils_js_1.fakePromise)(this._buffer);
|
292
|
+
}
|
293
|
+
if (this.bodyType === BodyInitType.String) {
|
294
|
+
return this.text().then(text => {
|
295
|
+
this._text = text;
|
296
|
+
this._buffer = node_buffer_1.Buffer.from(text, 'utf-8');
|
297
|
+
return this._buffer;
|
298
|
+
});
|
299
|
+
}
|
282
300
|
if (this.bodyType === BodyInitType.Blob) {
|
283
301
|
if ((0, Blob_js_1.hasBufferMethod)(this.bodyInit)) {
|
284
302
|
return this.bodyInit.buffer().then(buf => {
|
@@ -358,15 +376,13 @@ function processBodyInit(bodyInit, signal) {
|
|
358
376
|
};
|
359
377
|
}
|
360
378
|
if (typeof bodyInit === 'string') {
|
361
|
-
const
|
362
|
-
const contentLength = buffer.byteLength;
|
379
|
+
const contentLength = node_buffer_1.Buffer.byteLength(bodyInit);
|
363
380
|
return {
|
364
381
|
bodyType: BodyInitType.String,
|
365
382
|
contentType: 'text/plain;charset=UTF-8',
|
366
383
|
contentLength,
|
367
|
-
buffer,
|
368
384
|
bodyFactory() {
|
369
|
-
const readable = node_stream_1.Readable.from(
|
385
|
+
const readable = node_stream_1.Readable.from(node_buffer_1.Buffer.from(bodyInit, 'utf-8'));
|
370
386
|
return new ReadableStream_js_1.PonyfillReadableStream(readable);
|
371
387
|
},
|
372
388
|
};
|
package/cjs/Headers.js
CHANGED
@@ -4,6 +4,7 @@ exports.PonyfillHeaders = void 0;
|
|
4
4
|
exports.isHeadersLike = isHeadersLike;
|
5
5
|
const node_util_1 = require("node:util");
|
6
6
|
const IteratorObject_js_1 = require("./IteratorObject.js");
|
7
|
+
const utils_js_1 = require("./utils.js");
|
7
8
|
function isHeadersLike(headers) {
|
8
9
|
return headers?.get && headers?.forEach;
|
9
10
|
}
|
@@ -30,7 +31,7 @@ class PonyfillHeaders {
|
|
30
31
|
if (this.headersInit == null) {
|
31
32
|
return null;
|
32
33
|
}
|
33
|
-
if (
|
34
|
+
if ((0, utils_js_1.isArray)(this.headersInit)) {
|
34
35
|
const found = this.headersInit.filter(([headerKey]) => headerKey.toLowerCase() === normalized);
|
35
36
|
if (found.length === 0) {
|
36
37
|
return null;
|
@@ -66,9 +67,9 @@ class PonyfillHeaders {
|
|
66
67
|
// I could do a getter here, but I'm too lazy to type `getter`.
|
67
68
|
getMap() {
|
68
69
|
if (!this._map) {
|
69
|
-
this._setCookies
|
70
|
+
this._setCookies ||= [];
|
70
71
|
if (this.headersInit != null) {
|
71
|
-
if (
|
72
|
+
if ((0, utils_js_1.isArray)(this.headersInit)) {
|
72
73
|
this._map = new Map();
|
73
74
|
for (const [key, value] of this.headersInit) {
|
74
75
|
const normalizedKey = key.toLowerCase();
|
@@ -131,7 +132,8 @@ class PonyfillHeaders {
|
|
131
132
|
return value.toString();
|
132
133
|
}
|
133
134
|
has(name) {
|
134
|
-
|
135
|
+
const key = name.toLowerCase();
|
136
|
+
if (key === 'set-cookie') {
|
135
137
|
return !!this._setCookies?.length;
|
136
138
|
}
|
137
139
|
return !!this._get(name); // we might need to check if header exists and not just check if it's not nullable
|
@@ -142,6 +144,26 @@ class PonyfillHeaders {
|
|
142
144
|
this._setCookies = [value];
|
143
145
|
return;
|
144
146
|
}
|
147
|
+
if (!this._map && this.headersInit != null) {
|
148
|
+
if ((0, utils_js_1.isArray)(this.headersInit)) {
|
149
|
+
const found = this.headersInit.find(([headerKey]) => headerKey.toLowerCase() === key);
|
150
|
+
if (found) {
|
151
|
+
found[1] = value;
|
152
|
+
}
|
153
|
+
else {
|
154
|
+
this.headersInit.push([key, value]);
|
155
|
+
}
|
156
|
+
return;
|
157
|
+
}
|
158
|
+
else if (isHeadersLike(this.headersInit)) {
|
159
|
+
this.headersInit.set(key, value);
|
160
|
+
return;
|
161
|
+
}
|
162
|
+
else {
|
163
|
+
this.headersInit[key] = value;
|
164
|
+
return;
|
165
|
+
}
|
166
|
+
}
|
145
167
|
this.getMap().set(key, value);
|
146
168
|
}
|
147
169
|
delete(name) {
|
@@ -158,7 +180,7 @@ class PonyfillHeaders {
|
|
158
180
|
});
|
159
181
|
if (!this._map) {
|
160
182
|
if (this.headersInit) {
|
161
|
-
if (
|
183
|
+
if ((0, utils_js_1.isArray)(this.headersInit)) {
|
162
184
|
this.headersInit.forEach(([key, value]) => {
|
163
185
|
callback(value, key, this);
|
164
186
|
});
|
@@ -186,7 +208,7 @@ class PonyfillHeaders {
|
|
186
208
|
}
|
187
209
|
if (!this._map) {
|
188
210
|
if (this.headersInit) {
|
189
|
-
if (
|
211
|
+
if ((0, utils_js_1.isArray)(this.headersInit)) {
|
190
212
|
yield* this.headersInit.map(([key]) => key)[Symbol.iterator]();
|
191
213
|
return;
|
192
214
|
}
|
@@ -209,7 +231,7 @@ class PonyfillHeaders {
|
|
209
231
|
}
|
210
232
|
if (!this._map) {
|
211
233
|
if (this.headersInit) {
|
212
|
-
if (
|
234
|
+
if ((0, utils_js_1.isArray)(this.headersInit)) {
|
213
235
|
yield* this.headersInit.map(([, value]) => value)[Symbol.iterator]();
|
214
236
|
return;
|
215
237
|
}
|
@@ -232,7 +254,7 @@ class PonyfillHeaders {
|
|
232
254
|
}
|
233
255
|
if (!this._map) {
|
234
256
|
if (this.headersInit) {
|
235
|
-
if (
|
257
|
+
if ((0, utils_js_1.isArray)(this.headersInit)) {
|
236
258
|
yield* this.headersInit;
|
237
259
|
return;
|
238
260
|
}
|
package/cjs/Request.js
CHANGED
@@ -57,7 +57,6 @@ class PonyfillRequest extends Body_js_1.PonyfillBody {
|
|
57
57
|
this.redirect = requestInit?.redirect || 'follow';
|
58
58
|
this.referrer = requestInit?.referrer || 'about:client';
|
59
59
|
this.referrerPolicy = requestInit?.referrerPolicy || 'no-referrer';
|
60
|
-
this.signal = requestInit?.signal || new AbortController().signal;
|
61
60
|
this.headersSerializer = requestInit?.headersSerializer;
|
62
61
|
this.duplex = requestInit?.duplex || 'half';
|
63
62
|
this.destination = 'document';
|
@@ -92,6 +91,10 @@ class PonyfillRequest extends Body_js_1.PonyfillBody {
|
|
92
91
|
referrer;
|
93
92
|
referrerPolicy;
|
94
93
|
_url;
|
94
|
+
get signal() {
|
95
|
+
this._signal ||= new AbortController().signal;
|
96
|
+
return this._signal;
|
97
|
+
}
|
95
98
|
get url() {
|
96
99
|
if (this._url == null) {
|
97
100
|
if (this._parsedUrl) {
|
@@ -117,7 +120,6 @@ class PonyfillRequest extends Body_js_1.PonyfillBody {
|
|
117
120
|
}
|
118
121
|
duplex;
|
119
122
|
agent;
|
120
|
-
signal;
|
121
123
|
clone() {
|
122
124
|
return this;
|
123
125
|
}
|
package/cjs/Response.js
CHANGED
@@ -4,6 +4,7 @@ exports.PonyfillResponse = void 0;
|
|
4
4
|
const node_http_1 = require("node:http");
|
5
5
|
const Body_js_1 = require("./Body.js");
|
6
6
|
const Headers_js_1 = require("./Headers.js");
|
7
|
+
const utils_js_1 = require("./utils.js");
|
7
8
|
const JSON_CONTENT_TYPE = 'application/json; charset=utf-8';
|
8
9
|
class PonyfillResponse extends Body_js_1.PonyfillBody {
|
9
10
|
headers;
|
@@ -18,7 +19,6 @@ class PonyfillResponse extends Body_js_1.PonyfillBody {
|
|
18
19
|
this.url = init?.url || '';
|
19
20
|
this.redirected = init?.redirected || false;
|
20
21
|
this.type = init?.type || 'default';
|
21
|
-
this.signal = init?.signal || null;
|
22
22
|
this.handleContentLengthHeader();
|
23
23
|
}
|
24
24
|
get ok() {
|
@@ -49,13 +49,33 @@ class PonyfillResponse extends Body_js_1.PonyfillBody {
|
|
49
49
|
status,
|
50
50
|
});
|
51
51
|
}
|
52
|
-
static json(data, init
|
53
|
-
init
|
54
|
-
init
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
52
|
+
static json(data, init) {
|
53
|
+
if (!init) {
|
54
|
+
init = {
|
55
|
+
headers: {
|
56
|
+
'content-type': JSON_CONTENT_TYPE,
|
57
|
+
},
|
58
|
+
};
|
59
|
+
}
|
60
|
+
else if (!init.headers) {
|
61
|
+
init.headers = {
|
62
|
+
'content-type': JSON_CONTENT_TYPE,
|
63
|
+
};
|
64
|
+
}
|
65
|
+
else if ((0, Headers_js_1.isHeadersLike)(init.headers)) {
|
66
|
+
if (!init.headers.has('content-type')) {
|
67
|
+
init.headers.set('content-type', JSON_CONTENT_TYPE);
|
68
|
+
}
|
69
|
+
}
|
70
|
+
else if ((0, utils_js_1.isArray)(init.headers)) {
|
71
|
+
if (!init.headers.some(([key]) => key.toLowerCase() === 'content-type')) {
|
72
|
+
init.headers.push(['content-type', JSON_CONTENT_TYPE]);
|
73
|
+
}
|
74
|
+
}
|
75
|
+
else if (typeof init.headers === 'object') {
|
76
|
+
if (init.headers?.['content-type'] == null) {
|
77
|
+
init.headers['content-type'] = JSON_CONTENT_TYPE;
|
78
|
+
}
|
59
79
|
}
|
60
80
|
return new PonyfillResponse(JSON.stringify(data), init);
|
61
81
|
}
|
package/cjs/fetchCurl.js
CHANGED
@@ -21,8 +21,18 @@ function fetchCurl(fetchRequest) {
|
|
21
21
|
curlHandle.setOpt('CAINFO_BLOB', node_tls_1.rootCertificates.join('\n'));
|
22
22
|
}
|
23
23
|
curlHandle.enable(CurlFeature.StreamResponse);
|
24
|
+
let signal;
|
25
|
+
if (fetchRequest._signal === null) {
|
26
|
+
signal = undefined;
|
27
|
+
}
|
28
|
+
else if (fetchRequest._signal) {
|
29
|
+
signal = fetchRequest._signal;
|
30
|
+
}
|
31
|
+
else {
|
32
|
+
signal = fetchRequest.signal;
|
33
|
+
}
|
24
34
|
curlHandle.setStreamProgressCallback(function () {
|
25
|
-
return
|
35
|
+
return signal?.aborted ? (process.env.DEBUG ? CurlProgressFunc.Continue : 1) : 0;
|
26
36
|
});
|
27
37
|
if (fetchRequest['bodyType'] === 'String') {
|
28
38
|
curlHandle.setOpt('POSTFIELDS', fetchRequest['bodyInit']);
|
@@ -69,9 +79,7 @@ function fetchCurl(fetchRequest) {
|
|
69
79
|
}
|
70
80
|
}
|
71
81
|
}
|
72
|
-
|
73
|
-
fetchRequest.signal.addEventListener('abort', onAbort, { once: true });
|
74
|
-
}
|
82
|
+
signal?.addEventListener('abort', onAbort, { once: true });
|
75
83
|
curlHandle.once('end', function endListener() {
|
76
84
|
try {
|
77
85
|
curlHandle.close();
|
@@ -79,9 +87,7 @@ function fetchCurl(fetchRequest) {
|
|
79
87
|
catch (e) {
|
80
88
|
deferredPromise.reject(e);
|
81
89
|
}
|
82
|
-
|
83
|
-
fetchRequest.signal.removeEventListener('abort', onAbort);
|
84
|
-
}
|
90
|
+
signal?.removeEventListener('abort', onAbort);
|
85
91
|
});
|
86
92
|
curlHandle.once('error', function errorListener(error) {
|
87
93
|
if (streamResolved && !streamResolved.closed && !streamResolved.destroyed) {
|
@@ -103,7 +109,7 @@ function fetchCurl(fetchRequest) {
|
|
103
109
|
curlHandle.once('stream', function streamListener(stream, status, headersBuf) {
|
104
110
|
const outputStream = (0, utils_js_1.wrapIncomingMessageWithPassthrough)({
|
105
111
|
incomingMessage: stream,
|
106
|
-
signal
|
112
|
+
signal,
|
107
113
|
onError: deferredPromise.reject,
|
108
114
|
});
|
109
115
|
const headersFlat = headersBuf
|
package/cjs/fetchNodeHttp.js
CHANGED
@@ -28,13 +28,23 @@ function fetchNodeHttp(fetchRequest) {
|
|
28
28
|
if (nodeHeaders['accept-encoding'] == null) {
|
29
29
|
nodeHeaders['accept-encoding'] = 'gzip, deflate, br';
|
30
30
|
}
|
31
|
+
let signal;
|
32
|
+
if (fetchRequest._signal === null) {
|
33
|
+
signal = undefined;
|
34
|
+
}
|
35
|
+
else if (fetchRequest._signal) {
|
36
|
+
signal = fetchRequest._signal;
|
37
|
+
}
|
38
|
+
else {
|
39
|
+
signal = fetchRequest.signal;
|
40
|
+
}
|
31
41
|
let nodeRequest;
|
32
42
|
// If it is our ponyfilled Request, it should have `parsedUrl` which is a `URL` object
|
33
43
|
if (fetchRequest.parsedUrl) {
|
34
44
|
nodeRequest = requestFn(fetchRequest.parsedUrl, {
|
35
45
|
method: fetchRequest.method,
|
36
46
|
headers: nodeHeaders,
|
37
|
-
signal
|
47
|
+
signal,
|
38
48
|
agent: fetchRequest.agent,
|
39
49
|
});
|
40
50
|
}
|
@@ -42,7 +52,7 @@ function fetchNodeHttp(fetchRequest) {
|
|
42
52
|
nodeRequest = requestFn(fetchRequest.url, {
|
43
53
|
method: fetchRequest.method,
|
44
54
|
headers: nodeHeaders,
|
45
|
-
signal
|
55
|
+
signal,
|
46
56
|
agent: fetchRequest.agent,
|
47
57
|
});
|
48
58
|
}
|
@@ -89,7 +99,7 @@ function fetchNodeHttp(fetchRequest) {
|
|
89
99
|
outputStream = (0, utils_js_1.wrapIncomingMessageWithPassthrough)({
|
90
100
|
incomingMessage: nodeResponse,
|
91
101
|
passThrough: outputStream,
|
92
|
-
signal
|
102
|
+
signal,
|
93
103
|
onError: reject,
|
94
104
|
});
|
95
105
|
}
|
@@ -103,12 +113,12 @@ function fetchNodeHttp(fetchRequest) {
|
|
103
113
|
statusText,
|
104
114
|
headers: nodeResponse.headers,
|
105
115
|
url: fetchRequest.url,
|
106
|
-
signal
|
116
|
+
signal,
|
107
117
|
});
|
108
118
|
resolve(ponyfillResponse);
|
109
119
|
});
|
110
120
|
if (fetchRequest['_buffer'] != null) {
|
111
|
-
(0, promise_helpers_1.handleMaybePromise)(() => (0, utils_js_1.safeWrite)(fetchRequest['_buffer'], nodeRequest,
|
121
|
+
(0, promise_helpers_1.handleMaybePromise)(() => (0, utils_js_1.safeWrite)(fetchRequest['_buffer'], nodeRequest, signal), () => (0, utils_js_1.endStream)(nodeRequest), reject);
|
112
122
|
}
|
113
123
|
else {
|
114
124
|
const nodeReadable = (fetchRequest.body != null
|
package/cjs/utils.js
CHANGED
@@ -10,6 +10,7 @@ exports.shouldRedirect = shouldRedirect;
|
|
10
10
|
exports.wrapIncomingMessageWithPassthrough = wrapIncomingMessageWithPassthrough;
|
11
11
|
exports.endStream = endStream;
|
12
12
|
exports.safeWrite = safeWrite;
|
13
|
+
exports.isArray = isArray;
|
13
14
|
const node_events_1 = require("node:events");
|
14
15
|
const node_stream_1 = require("node:stream");
|
15
16
|
const promises_1 = require("node:stream/promises");
|
@@ -20,6 +21,11 @@ function getHeadersObj(headers) {
|
|
20
21
|
if (headers == null || !isHeadersInstance(headers)) {
|
21
22
|
return headers;
|
22
23
|
}
|
24
|
+
// @ts-expect-error - `headersInit` is not a public property
|
25
|
+
if (headers.headersInit && !headers._map && !isHeadersInstance(headers.headersInit)) {
|
26
|
+
// @ts-expect-error - `headersInit` is not a public property
|
27
|
+
return headers.headersInit;
|
28
|
+
}
|
23
29
|
return Object.fromEntries(headers.entries());
|
24
30
|
}
|
25
31
|
function defaultHeadersSerializer(headers, onContentLength) {
|
@@ -73,3 +79,6 @@ function safeWrite(chunk, stream, signal) {
|
|
73
79
|
});
|
74
80
|
}
|
75
81
|
}
|
82
|
+
function isArray(value) {
|
83
|
+
return value?.splice != null;
|
84
|
+
}
|
package/esm/Body.js
CHANGED
@@ -25,11 +25,11 @@ export class PonyfillBody {
|
|
25
25
|
bodyUsed = false;
|
26
26
|
contentType = null;
|
27
27
|
contentLength = null;
|
28
|
-
|
28
|
+
_signal = null;
|
29
29
|
constructor(bodyInit, options = {}) {
|
30
30
|
this.bodyInit = bodyInit;
|
31
31
|
this.options = options;
|
32
|
-
this.
|
32
|
+
this._signal = options.signal || null;
|
33
33
|
const { bodyFactory, contentType, contentLength, bodyType, buffer } = processBodyInit(bodyInit, options?.signal);
|
34
34
|
this._bodyFactory = bodyFactory;
|
35
35
|
this.contentType = contentType;
|
@@ -147,6 +147,13 @@ export class PonyfillBody {
|
|
147
147
|
if (this._blob) {
|
148
148
|
return fakePromise(this._blob);
|
149
149
|
}
|
150
|
+
if (this.bodyType === BodyInitType.String) {
|
151
|
+
this._text = this.bodyInit;
|
152
|
+
this._blob = new PonyfillBlob([this._text], {
|
153
|
+
type: this.contentType || 'text/plain;charset=UTF-8',
|
154
|
+
size: this.contentLength,
|
155
|
+
});
|
156
|
+
}
|
150
157
|
if (this.bodyType === BodyInitType.Blob) {
|
151
158
|
this._blob = this.bodyInit;
|
152
159
|
return fakePromise(this._blob);
|
@@ -202,8 +209,8 @@ export class PonyfillBody {
|
|
202
209
|
limits: formDataLimits,
|
203
210
|
defCharset: 'utf-8',
|
204
211
|
});
|
205
|
-
if (this.
|
206
|
-
addAbortSignal(this.
|
212
|
+
if (this._signal) {
|
213
|
+
addAbortSignal(this._signal, bb);
|
207
214
|
}
|
208
215
|
let completed = false;
|
209
216
|
const complete = (err) => {
|
@@ -276,6 +283,17 @@ export class PonyfillBody {
|
|
276
283
|
if (this._buffer) {
|
277
284
|
return fakePromise(this._buffer);
|
278
285
|
}
|
286
|
+
if (this._text) {
|
287
|
+
this._buffer = Buffer.from(this._text, 'utf-8');
|
288
|
+
return fakePromise(this._buffer);
|
289
|
+
}
|
290
|
+
if (this.bodyType === BodyInitType.String) {
|
291
|
+
return this.text().then(text => {
|
292
|
+
this._text = text;
|
293
|
+
this._buffer = Buffer.from(text, 'utf-8');
|
294
|
+
return this._buffer;
|
295
|
+
});
|
296
|
+
}
|
279
297
|
if (this.bodyType === BodyInitType.Blob) {
|
280
298
|
if (hasBufferMethod(this.bodyInit)) {
|
281
299
|
return this.bodyInit.buffer().then(buf => {
|
@@ -354,15 +372,13 @@ function processBodyInit(bodyInit, signal) {
|
|
354
372
|
};
|
355
373
|
}
|
356
374
|
if (typeof bodyInit === 'string') {
|
357
|
-
const
|
358
|
-
const contentLength = buffer.byteLength;
|
375
|
+
const contentLength = Buffer.byteLength(bodyInit);
|
359
376
|
return {
|
360
377
|
bodyType: BodyInitType.String,
|
361
378
|
contentType: 'text/plain;charset=UTF-8',
|
362
379
|
contentLength,
|
363
|
-
buffer,
|
364
380
|
bodyFactory() {
|
365
|
-
const readable = Readable.from(
|
381
|
+
const readable = Readable.from(Buffer.from(bodyInit, 'utf-8'));
|
366
382
|
return new PonyfillReadableStream(readable);
|
367
383
|
},
|
368
384
|
};
|
package/esm/Headers.js
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
import { inspect } from 'node:util';
|
2
2
|
import { PonyfillIteratorObject } from './IteratorObject.js';
|
3
|
+
import { isArray } from './utils.js';
|
3
4
|
export function isHeadersLike(headers) {
|
4
5
|
return headers?.get && headers?.forEach;
|
5
6
|
}
|
@@ -26,7 +27,7 @@ export class PonyfillHeaders {
|
|
26
27
|
if (this.headersInit == null) {
|
27
28
|
return null;
|
28
29
|
}
|
29
|
-
if (
|
30
|
+
if (isArray(this.headersInit)) {
|
30
31
|
const found = this.headersInit.filter(([headerKey]) => headerKey.toLowerCase() === normalized);
|
31
32
|
if (found.length === 0) {
|
32
33
|
return null;
|
@@ -62,9 +63,9 @@ export class PonyfillHeaders {
|
|
62
63
|
// I could do a getter here, but I'm too lazy to type `getter`.
|
63
64
|
getMap() {
|
64
65
|
if (!this._map) {
|
65
|
-
this._setCookies
|
66
|
+
this._setCookies ||= [];
|
66
67
|
if (this.headersInit != null) {
|
67
|
-
if (
|
68
|
+
if (isArray(this.headersInit)) {
|
68
69
|
this._map = new Map();
|
69
70
|
for (const [key, value] of this.headersInit) {
|
70
71
|
const normalizedKey = key.toLowerCase();
|
@@ -127,7 +128,8 @@ export class PonyfillHeaders {
|
|
127
128
|
return value.toString();
|
128
129
|
}
|
129
130
|
has(name) {
|
130
|
-
|
131
|
+
const key = name.toLowerCase();
|
132
|
+
if (key === 'set-cookie') {
|
131
133
|
return !!this._setCookies?.length;
|
132
134
|
}
|
133
135
|
return !!this._get(name); // we might need to check if header exists and not just check if it's not nullable
|
@@ -138,6 +140,26 @@ export class PonyfillHeaders {
|
|
138
140
|
this._setCookies = [value];
|
139
141
|
return;
|
140
142
|
}
|
143
|
+
if (!this._map && this.headersInit != null) {
|
144
|
+
if (isArray(this.headersInit)) {
|
145
|
+
const found = this.headersInit.find(([headerKey]) => headerKey.toLowerCase() === key);
|
146
|
+
if (found) {
|
147
|
+
found[1] = value;
|
148
|
+
}
|
149
|
+
else {
|
150
|
+
this.headersInit.push([key, value]);
|
151
|
+
}
|
152
|
+
return;
|
153
|
+
}
|
154
|
+
else if (isHeadersLike(this.headersInit)) {
|
155
|
+
this.headersInit.set(key, value);
|
156
|
+
return;
|
157
|
+
}
|
158
|
+
else {
|
159
|
+
this.headersInit[key] = value;
|
160
|
+
return;
|
161
|
+
}
|
162
|
+
}
|
141
163
|
this.getMap().set(key, value);
|
142
164
|
}
|
143
165
|
delete(name) {
|
@@ -154,7 +176,7 @@ export class PonyfillHeaders {
|
|
154
176
|
});
|
155
177
|
if (!this._map) {
|
156
178
|
if (this.headersInit) {
|
157
|
-
if (
|
179
|
+
if (isArray(this.headersInit)) {
|
158
180
|
this.headersInit.forEach(([key, value]) => {
|
159
181
|
callback(value, key, this);
|
160
182
|
});
|
@@ -182,7 +204,7 @@ export class PonyfillHeaders {
|
|
182
204
|
}
|
183
205
|
if (!this._map) {
|
184
206
|
if (this.headersInit) {
|
185
|
-
if (
|
207
|
+
if (isArray(this.headersInit)) {
|
186
208
|
yield* this.headersInit.map(([key]) => key)[Symbol.iterator]();
|
187
209
|
return;
|
188
210
|
}
|
@@ -205,7 +227,7 @@ export class PonyfillHeaders {
|
|
205
227
|
}
|
206
228
|
if (!this._map) {
|
207
229
|
if (this.headersInit) {
|
208
|
-
if (
|
230
|
+
if (isArray(this.headersInit)) {
|
209
231
|
yield* this.headersInit.map(([, value]) => value)[Symbol.iterator]();
|
210
232
|
return;
|
211
233
|
}
|
@@ -228,7 +250,7 @@ export class PonyfillHeaders {
|
|
228
250
|
}
|
229
251
|
if (!this._map) {
|
230
252
|
if (this.headersInit) {
|
231
|
-
if (
|
253
|
+
if (isArray(this.headersInit)) {
|
232
254
|
yield* this.headersInit;
|
233
255
|
return;
|
234
256
|
}
|
package/esm/Request.js
CHANGED
@@ -54,7 +54,6 @@ export class PonyfillRequest extends PonyfillBody {
|
|
54
54
|
this.redirect = requestInit?.redirect || 'follow';
|
55
55
|
this.referrer = requestInit?.referrer || 'about:client';
|
56
56
|
this.referrerPolicy = requestInit?.referrerPolicy || 'no-referrer';
|
57
|
-
this.signal = requestInit?.signal || new AbortController().signal;
|
58
57
|
this.headersSerializer = requestInit?.headersSerializer;
|
59
58
|
this.duplex = requestInit?.duplex || 'half';
|
60
59
|
this.destination = 'document';
|
@@ -89,6 +88,10 @@ export class PonyfillRequest extends PonyfillBody {
|
|
89
88
|
referrer;
|
90
89
|
referrerPolicy;
|
91
90
|
_url;
|
91
|
+
get signal() {
|
92
|
+
this._signal ||= new AbortController().signal;
|
93
|
+
return this._signal;
|
94
|
+
}
|
92
95
|
get url() {
|
93
96
|
if (this._url == null) {
|
94
97
|
if (this._parsedUrl) {
|
@@ -114,7 +117,6 @@ export class PonyfillRequest extends PonyfillBody {
|
|
114
117
|
}
|
115
118
|
duplex;
|
116
119
|
agent;
|
117
|
-
signal;
|
118
120
|
clone() {
|
119
121
|
return this;
|
120
122
|
}
|
package/esm/Response.js
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
import { STATUS_CODES } from 'node:http';
|
2
2
|
import { PonyfillBody } from './Body.js';
|
3
3
|
import { isHeadersLike, PonyfillHeaders } from './Headers.js';
|
4
|
+
import { isArray } from './utils.js';
|
4
5
|
const JSON_CONTENT_TYPE = 'application/json; charset=utf-8';
|
5
6
|
export class PonyfillResponse extends PonyfillBody {
|
6
7
|
headers;
|
@@ -15,7 +16,6 @@ export class PonyfillResponse extends PonyfillBody {
|
|
15
16
|
this.url = init?.url || '';
|
16
17
|
this.redirected = init?.redirected || false;
|
17
18
|
this.type = init?.type || 'default';
|
18
|
-
this.signal = init?.signal || null;
|
19
19
|
this.handleContentLengthHeader();
|
20
20
|
}
|
21
21
|
get ok() {
|
@@ -46,13 +46,33 @@ export class PonyfillResponse extends PonyfillBody {
|
|
46
46
|
status,
|
47
47
|
});
|
48
48
|
}
|
49
|
-
static json(data, init
|
50
|
-
init
|
51
|
-
init
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
49
|
+
static json(data, init) {
|
50
|
+
if (!init) {
|
51
|
+
init = {
|
52
|
+
headers: {
|
53
|
+
'content-type': JSON_CONTENT_TYPE,
|
54
|
+
},
|
55
|
+
};
|
56
|
+
}
|
57
|
+
else if (!init.headers) {
|
58
|
+
init.headers = {
|
59
|
+
'content-type': JSON_CONTENT_TYPE,
|
60
|
+
};
|
61
|
+
}
|
62
|
+
else if (isHeadersLike(init.headers)) {
|
63
|
+
if (!init.headers.has('content-type')) {
|
64
|
+
init.headers.set('content-type', JSON_CONTENT_TYPE);
|
65
|
+
}
|
66
|
+
}
|
67
|
+
else if (isArray(init.headers)) {
|
68
|
+
if (!init.headers.some(([key]) => key.toLowerCase() === 'content-type')) {
|
69
|
+
init.headers.push(['content-type', JSON_CONTENT_TYPE]);
|
70
|
+
}
|
71
|
+
}
|
72
|
+
else if (typeof init.headers === 'object') {
|
73
|
+
if (init.headers?.['content-type'] == null) {
|
74
|
+
init.headers['content-type'] = JSON_CONTENT_TYPE;
|
75
|
+
}
|
56
76
|
}
|
57
77
|
return new PonyfillResponse(JSON.stringify(data), init);
|
58
78
|
}
|
package/esm/fetchCurl.js
CHANGED
@@ -18,8 +18,18 @@ export function fetchCurl(fetchRequest) {
|
|
18
18
|
curlHandle.setOpt('CAINFO_BLOB', rootCertificates.join('\n'));
|
19
19
|
}
|
20
20
|
curlHandle.enable(CurlFeature.StreamResponse);
|
21
|
+
let signal;
|
22
|
+
if (fetchRequest._signal === null) {
|
23
|
+
signal = undefined;
|
24
|
+
}
|
25
|
+
else if (fetchRequest._signal) {
|
26
|
+
signal = fetchRequest._signal;
|
27
|
+
}
|
28
|
+
else {
|
29
|
+
signal = fetchRequest.signal;
|
30
|
+
}
|
21
31
|
curlHandle.setStreamProgressCallback(function () {
|
22
|
-
return
|
32
|
+
return signal?.aborted ? (process.env.DEBUG ? CurlProgressFunc.Continue : 1) : 0;
|
23
33
|
});
|
24
34
|
if (fetchRequest['bodyType'] === 'String') {
|
25
35
|
curlHandle.setOpt('POSTFIELDS', fetchRequest['bodyInit']);
|
@@ -66,9 +76,7 @@ export function fetchCurl(fetchRequest) {
|
|
66
76
|
}
|
67
77
|
}
|
68
78
|
}
|
69
|
-
|
70
|
-
fetchRequest.signal.addEventListener('abort', onAbort, { once: true });
|
71
|
-
}
|
79
|
+
signal?.addEventListener('abort', onAbort, { once: true });
|
72
80
|
curlHandle.once('end', function endListener() {
|
73
81
|
try {
|
74
82
|
curlHandle.close();
|
@@ -76,9 +84,7 @@ export function fetchCurl(fetchRequest) {
|
|
76
84
|
catch (e) {
|
77
85
|
deferredPromise.reject(e);
|
78
86
|
}
|
79
|
-
|
80
|
-
fetchRequest.signal.removeEventListener('abort', onAbort);
|
81
|
-
}
|
87
|
+
signal?.removeEventListener('abort', onAbort);
|
82
88
|
});
|
83
89
|
curlHandle.once('error', function errorListener(error) {
|
84
90
|
if (streamResolved && !streamResolved.closed && !streamResolved.destroyed) {
|
@@ -100,7 +106,7 @@ export function fetchCurl(fetchRequest) {
|
|
100
106
|
curlHandle.once('stream', function streamListener(stream, status, headersBuf) {
|
101
107
|
const outputStream = wrapIncomingMessageWithPassthrough({
|
102
108
|
incomingMessage: stream,
|
103
|
-
signal
|
109
|
+
signal,
|
104
110
|
onError: deferredPromise.reject,
|
105
111
|
});
|
106
112
|
const headersFlat = headersBuf
|
package/esm/fetchNodeHttp.js
CHANGED
@@ -25,13 +25,23 @@ export function fetchNodeHttp(fetchRequest) {
|
|
25
25
|
if (nodeHeaders['accept-encoding'] == null) {
|
26
26
|
nodeHeaders['accept-encoding'] = 'gzip, deflate, br';
|
27
27
|
}
|
28
|
+
let signal;
|
29
|
+
if (fetchRequest._signal === null) {
|
30
|
+
signal = undefined;
|
31
|
+
}
|
32
|
+
else if (fetchRequest._signal) {
|
33
|
+
signal = fetchRequest._signal;
|
34
|
+
}
|
35
|
+
else {
|
36
|
+
signal = fetchRequest.signal;
|
37
|
+
}
|
28
38
|
let nodeRequest;
|
29
39
|
// If it is our ponyfilled Request, it should have `parsedUrl` which is a `URL` object
|
30
40
|
if (fetchRequest.parsedUrl) {
|
31
41
|
nodeRequest = requestFn(fetchRequest.parsedUrl, {
|
32
42
|
method: fetchRequest.method,
|
33
43
|
headers: nodeHeaders,
|
34
|
-
signal
|
44
|
+
signal,
|
35
45
|
agent: fetchRequest.agent,
|
36
46
|
});
|
37
47
|
}
|
@@ -39,7 +49,7 @@ export function fetchNodeHttp(fetchRequest) {
|
|
39
49
|
nodeRequest = requestFn(fetchRequest.url, {
|
40
50
|
method: fetchRequest.method,
|
41
51
|
headers: nodeHeaders,
|
42
|
-
signal
|
52
|
+
signal,
|
43
53
|
agent: fetchRequest.agent,
|
44
54
|
});
|
45
55
|
}
|
@@ -86,7 +96,7 @@ export function fetchNodeHttp(fetchRequest) {
|
|
86
96
|
outputStream = wrapIncomingMessageWithPassthrough({
|
87
97
|
incomingMessage: nodeResponse,
|
88
98
|
passThrough: outputStream,
|
89
|
-
signal
|
99
|
+
signal,
|
90
100
|
onError: reject,
|
91
101
|
});
|
92
102
|
}
|
@@ -100,12 +110,12 @@ export function fetchNodeHttp(fetchRequest) {
|
|
100
110
|
statusText,
|
101
111
|
headers: nodeResponse.headers,
|
102
112
|
url: fetchRequest.url,
|
103
|
-
signal
|
113
|
+
signal,
|
104
114
|
});
|
105
115
|
resolve(ponyfillResponse);
|
106
116
|
});
|
107
117
|
if (fetchRequest['_buffer'] != null) {
|
108
|
-
handleMaybePromise(() => safeWrite(fetchRequest['_buffer'], nodeRequest,
|
118
|
+
handleMaybePromise(() => safeWrite(fetchRequest['_buffer'], nodeRequest, signal), () => endStream(nodeRequest), reject);
|
109
119
|
}
|
110
120
|
else {
|
111
121
|
const nodeReadable = (fetchRequest.body != null
|
package/esm/utils.js
CHANGED
@@ -8,6 +8,11 @@ export function getHeadersObj(headers) {
|
|
8
8
|
if (headers == null || !isHeadersInstance(headers)) {
|
9
9
|
return headers;
|
10
10
|
}
|
11
|
+
// @ts-expect-error - `headersInit` is not a public property
|
12
|
+
if (headers.headersInit && !headers._map && !isHeadersInstance(headers.headersInit)) {
|
13
|
+
// @ts-expect-error - `headersInit` is not a public property
|
14
|
+
return headers.headersInit;
|
15
|
+
}
|
11
16
|
return Object.fromEntries(headers.entries());
|
12
17
|
}
|
13
18
|
export function defaultHeadersSerializer(headers, onContentLength) {
|
@@ -60,3 +65,6 @@ export function safeWrite(chunk, stream, signal) {
|
|
60
65
|
});
|
61
66
|
}
|
62
67
|
}
|
68
|
+
export function isArray(value) {
|
69
|
+
return value?.splice != null;
|
70
|
+
}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@whatwg-node/node-fetch",
|
3
|
-
"version": "0.7.20-alpha-
|
3
|
+
"version": "0.7.20-alpha-20250516115150-ce23c7139392555706532687427aa8535aae5852",
|
4
4
|
"description": "Fetch API implementation for Node",
|
5
5
|
"sideEffects": false,
|
6
6
|
"dependencies": {
|
package/typings/Body.d.cts
CHANGED
@@ -16,7 +16,7 @@ export interface FormDataLimits {
|
|
16
16
|
}
|
17
17
|
export interface PonyfillBodyOptions {
|
18
18
|
formDataLimits?: FormDataLimits;
|
19
|
-
signal?: AbortSignal;
|
19
|
+
signal?: AbortSignal | undefined;
|
20
20
|
}
|
21
21
|
export declare class PonyfillBody<TJSON = any> implements Body {
|
22
22
|
private bodyInit;
|
@@ -24,7 +24,7 @@ export declare class PonyfillBody<TJSON = any> implements Body {
|
|
24
24
|
bodyUsed: boolean;
|
25
25
|
contentType: string | null;
|
26
26
|
contentLength: number | null;
|
27
|
-
|
27
|
+
_signal?: AbortSignal | null;
|
28
28
|
constructor(bodyInit: BodyPonyfillInit | null, options?: PonyfillBodyOptions);
|
29
29
|
private bodyType?;
|
30
30
|
private _bodyFactory;
|
package/typings/Body.d.ts
CHANGED
@@ -16,7 +16,7 @@ export interface FormDataLimits {
|
|
16
16
|
}
|
17
17
|
export interface PonyfillBodyOptions {
|
18
18
|
formDataLimits?: FormDataLimits;
|
19
|
-
signal?: AbortSignal;
|
19
|
+
signal?: AbortSignal | undefined;
|
20
20
|
}
|
21
21
|
export declare class PonyfillBody<TJSON = any> implements Body {
|
22
22
|
private bodyInit;
|
@@ -24,7 +24,7 @@ export declare class PonyfillBody<TJSON = any> implements Body {
|
|
24
24
|
bodyUsed: boolean;
|
25
25
|
contentType: string | null;
|
26
26
|
contentLength: number | null;
|
27
|
-
|
27
|
+
_signal?: AbortSignal | null;
|
28
28
|
constructor(bodyInit: BodyPonyfillInit | null, options?: PonyfillBodyOptions);
|
29
29
|
private bodyType?;
|
30
30
|
private _bodyFactory;
|
package/typings/Request.d.cts
CHANGED
@@ -26,12 +26,12 @@ export declare class PonyfillRequest<TJSON = any> extends PonyfillBody<TJSON> im
|
|
26
26
|
referrer: string;
|
27
27
|
referrerPolicy: ReferrerPolicy;
|
28
28
|
_url: string | undefined;
|
29
|
+
get signal(): AbortSignal;
|
29
30
|
get url(): string;
|
30
31
|
_parsedUrl: URL | undefined;
|
31
32
|
get parsedUrl(): URL;
|
32
33
|
duplex: 'half' | 'full';
|
33
34
|
agent: HTTPAgent | HTTPSAgent | false | undefined;
|
34
|
-
signal: AbortSignal;
|
35
35
|
clone(): PonyfillRequest<TJSON>;
|
36
36
|
[Symbol.toStringTag]: string;
|
37
37
|
}
|
package/typings/Request.d.ts
CHANGED
@@ -26,12 +26,12 @@ export declare class PonyfillRequest<TJSON = any> extends PonyfillBody<TJSON> im
|
|
26
26
|
referrer: string;
|
27
27
|
referrerPolicy: ReferrerPolicy;
|
28
28
|
_url: string | undefined;
|
29
|
+
get signal(): AbortSignal;
|
29
30
|
get url(): string;
|
30
31
|
_parsedUrl: URL | undefined;
|
31
32
|
get parsedUrl(): URL;
|
32
33
|
duplex: 'half' | 'full';
|
33
34
|
agent: HTTPAgent | HTTPSAgent | false | undefined;
|
34
|
-
signal: AbortSignal;
|
35
35
|
clone(): PonyfillRequest<TJSON>;
|
36
36
|
[Symbol.toStringTag]: string;
|
37
37
|
}
|
package/typings/utils.d.cts
CHANGED
package/typings/utils.d.ts
CHANGED