@whatwg-node/node-fetch 0.8.0-alpha-20241212154840-0a0effe808a6614e0a3afd853126a38641485756 → 0.8.0-alpha-20250917012053-36c9ccdc3e94ee8d0961f17398a9053fa55df37b
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/AbortError.js +5 -3
- package/cjs/Blob.js +21 -19
- package/cjs/Body.js +146 -76
- package/cjs/FormData.js +54 -41
- package/cjs/Headers.js +54 -15
- package/cjs/ReadableStream.js +62 -26
- package/cjs/Request.js +9 -16
- package/cjs/Response.js +56 -10
- package/cjs/TextEncoderDecoder.js +6 -5
- package/cjs/TextEncoderDecoderStream.js +2 -6
- package/cjs/TransformStream.js +2 -1
- package/cjs/URL.js +10 -66
- package/cjs/URLSearchParams.js +1 -117
- package/cjs/WritableStream.js +35 -111
- package/cjs/fetch.js +37 -8
- package/cjs/fetchCurl.js +30 -61
- package/cjs/fetchNodeHttp.js +60 -64
- package/cjs/index.js +1 -7
- package/cjs/utils.js +76 -55
- package/esm/AbortError.js +5 -3
- package/esm/Blob.js +6 -4
- package/esm/Body.js +134 -63
- package/esm/FormData.js +54 -41
- package/esm/Headers.js +54 -15
- package/esm/ReadableStream.js +57 -21
- package/esm/Request.js +7 -14
- package/esm/Response.js +55 -9
- package/esm/TextEncoderDecoder.js +1 -0
- package/esm/TextEncoderDecoderStream.js +2 -6
- package/esm/TransformStream.js +2 -1
- package/esm/URL.js +9 -64
- package/esm/URLSearchParams.js +1 -115
- package/esm/WritableStream.js +33 -109
- package/esm/fetch.js +35 -6
- package/esm/fetchCurl.js +28 -59
- package/esm/fetchNodeHttp.js +55 -59
- package/esm/index.js +0 -3
- package/esm/utils.js +70 -53
- package/package.json +4 -5
- package/typings/AbortError.d.cts +1 -1
- package/typings/AbortError.d.ts +1 -1
- package/typings/Blob.d.cts +5 -4
- package/typings/Blob.d.ts +5 -4
- package/typings/Body.d.cts +11 -6
- package/typings/Body.d.ts +11 -6
- package/typings/Headers.d.cts +1 -1
- package/typings/Headers.d.ts +1 -1
- package/typings/ReadableStream.d.cts +8 -2
- package/typings/ReadableStream.d.ts +8 -2
- package/typings/Request.d.cts +9 -10
- package/typings/Request.d.ts +9 -10
- package/typings/Response.d.cts +6 -5
- package/typings/Response.d.ts +6 -5
- package/typings/TextEncoderDecoder.d.cts +2 -1
- package/typings/TextEncoderDecoder.d.ts +2 -1
- package/typings/URL.d.cts +12 -16
- package/typings/URL.d.ts +12 -16
- package/typings/URLSearchParams.d.cts +4 -21
- package/typings/URLSearchParams.d.ts +4 -21
- package/typings/WritableStream.d.cts +1 -1
- package/typings/WritableStream.d.ts +1 -1
- package/typings/index.d.cts +0 -3
- package/typings/index.d.ts +0 -3
- package/typings/utils.d.cts +13 -8
- package/typings/utils.d.ts +13 -8
- package/cjs/AbortController.js +0 -18
- package/cjs/AbortSignal.js +0 -85
- package/esm/AbortController.js +0 -14
- package/esm/AbortSignal.js +0 -81
- package/typings/AbortController.d.cts +0 -8
- package/typings/AbortController.d.ts +0 -8
- package/typings/AbortSignal.d.cts +0 -15
- package/typings/AbortSignal.d.ts +0 -15
package/esm/WritableStream.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { once } from 'node:events';
|
|
2
|
+
import { Writable } from 'node:stream';
|
|
3
|
+
import { fakeRejectPromise } from '@whatwg-node/promise-helpers';
|
|
4
|
+
import { endStream, fakePromise, safeWrite } from './utils.js';
|
|
3
5
|
export class PonyfillWritableStream {
|
|
4
6
|
writable;
|
|
5
7
|
constructor(underlyingSink) {
|
|
@@ -41,55 +43,15 @@ export class PonyfillWritableStream {
|
|
|
41
43
|
},
|
|
42
44
|
});
|
|
43
45
|
this.writable = writable;
|
|
44
|
-
|
|
45
|
-
let reason;
|
|
46
|
+
const abortCtrl = new AbortController();
|
|
46
47
|
const controller = {
|
|
47
|
-
signal:
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
},
|
|
51
|
-
get reason() {
|
|
52
|
-
return reason;
|
|
53
|
-
},
|
|
54
|
-
get aborted() {
|
|
55
|
-
return writable.destroyed;
|
|
56
|
-
},
|
|
57
|
-
addEventListener: (_event, eventListener) => {
|
|
58
|
-
writable.once('error', eventListener);
|
|
59
|
-
writable.once('close', eventListener);
|
|
60
|
-
},
|
|
61
|
-
removeEventListener: (_event, eventListener) => {
|
|
62
|
-
writable.off('error', eventListener);
|
|
63
|
-
writable.off('close', eventListener);
|
|
64
|
-
},
|
|
65
|
-
dispatchEvent: (_event) => {
|
|
66
|
-
return false;
|
|
67
|
-
},
|
|
68
|
-
get onabort() {
|
|
69
|
-
return onabort;
|
|
70
|
-
},
|
|
71
|
-
set onabort(value) {
|
|
72
|
-
if (onabort) {
|
|
73
|
-
this.removeEventListener('abort', onabort);
|
|
74
|
-
}
|
|
75
|
-
onabort = value;
|
|
76
|
-
if (onabort) {
|
|
77
|
-
this.addEventListener('abort', onabort);
|
|
78
|
-
}
|
|
79
|
-
},
|
|
80
|
-
throwIfAborted() {
|
|
81
|
-
if (writable.destroyed) {
|
|
82
|
-
throw reason;
|
|
83
|
-
}
|
|
84
|
-
},
|
|
85
|
-
},
|
|
86
|
-
error: e => {
|
|
87
|
-
this.writable.destroy(e);
|
|
48
|
+
signal: abortCtrl.signal,
|
|
49
|
+
error(e) {
|
|
50
|
+
writable.destroy(e);
|
|
88
51
|
},
|
|
89
52
|
};
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
});
|
|
53
|
+
writable.once('error', err => abortCtrl.abort(err));
|
|
54
|
+
writable.once('close', () => abortCtrl.abort());
|
|
93
55
|
}
|
|
94
56
|
else {
|
|
95
57
|
this.writable = new Writable();
|
|
@@ -98,90 +60,52 @@ export class PonyfillWritableStream {
|
|
|
98
60
|
getWriter() {
|
|
99
61
|
const writable = this.writable;
|
|
100
62
|
return {
|
|
101
|
-
closed
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
});
|
|
105
|
-
}),
|
|
63
|
+
get closed() {
|
|
64
|
+
return once(writable, 'close');
|
|
65
|
+
},
|
|
106
66
|
get desiredSize() {
|
|
107
67
|
return writable.writableLength;
|
|
108
68
|
},
|
|
109
|
-
ready
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
});
|
|
113
|
-
}),
|
|
69
|
+
get ready() {
|
|
70
|
+
return once(writable, 'drain');
|
|
71
|
+
},
|
|
114
72
|
releaseLock() {
|
|
115
73
|
// no-op
|
|
116
74
|
},
|
|
117
75
|
write(chunk) {
|
|
76
|
+
const promise = fakePromise();
|
|
118
77
|
if (chunk == null) {
|
|
119
|
-
return
|
|
78
|
+
return promise;
|
|
120
79
|
}
|
|
121
|
-
return
|
|
122
|
-
writable.write(chunk, (err) => {
|
|
123
|
-
if (err) {
|
|
124
|
-
reject(err);
|
|
125
|
-
}
|
|
126
|
-
else {
|
|
127
|
-
resolve();
|
|
128
|
-
}
|
|
129
|
-
});
|
|
130
|
-
});
|
|
80
|
+
return promise.then(() => safeWrite(chunk, writable));
|
|
131
81
|
},
|
|
132
82
|
close() {
|
|
133
83
|
if (!writable.errored && writable.closed) {
|
|
134
|
-
return fakePromise(
|
|
84
|
+
return fakePromise();
|
|
135
85
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
else {
|
|
141
|
-
writable.end((err) => {
|
|
142
|
-
if (err) {
|
|
143
|
-
reject(err);
|
|
144
|
-
}
|
|
145
|
-
else {
|
|
146
|
-
resolve();
|
|
147
|
-
}
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
});
|
|
86
|
+
if (writable.errored) {
|
|
87
|
+
return fakeRejectPromise(writable.errored);
|
|
88
|
+
}
|
|
89
|
+
return fakePromise().then(() => endStream(writable));
|
|
151
90
|
},
|
|
152
91
|
abort(reason) {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
writable.once('close', resolve);
|
|
156
|
-
});
|
|
92
|
+
writable.destroy(reason);
|
|
93
|
+
return once(writable, 'close');
|
|
157
94
|
},
|
|
158
95
|
};
|
|
159
96
|
}
|
|
160
97
|
close() {
|
|
161
98
|
if (!this.writable.errored && this.writable.closed) {
|
|
162
|
-
return fakePromise(
|
|
99
|
+
return fakePromise();
|
|
163
100
|
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
else {
|
|
169
|
-
this.writable.end((err) => {
|
|
170
|
-
if (err) {
|
|
171
|
-
reject(err);
|
|
172
|
-
}
|
|
173
|
-
else {
|
|
174
|
-
resolve();
|
|
175
|
-
}
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
|
-
});
|
|
101
|
+
if (this.writable.errored) {
|
|
102
|
+
return fakeRejectPromise(this.writable.errored);
|
|
103
|
+
}
|
|
104
|
+
return fakePromise().then(() => endStream(this.writable));
|
|
179
105
|
}
|
|
180
106
|
abort(reason) {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
this.writable.once('close', resolve);
|
|
184
|
-
});
|
|
107
|
+
this.writable.destroy(reason);
|
|
108
|
+
return once(this.writable, 'close');
|
|
185
109
|
}
|
|
186
110
|
locked = false;
|
|
187
111
|
}
|
package/esm/fetch.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { Buffer } from 'node:buffer';
|
|
2
|
+
import { createReadStream, promises as fsPromises } from 'node:fs';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
3
4
|
import { fetchCurl } from './fetchCurl.js';
|
|
4
5
|
import { fetchNodeHttp } from './fetchNodeHttp.js';
|
|
5
6
|
import { PonyfillRequest } from './Request.js';
|
|
@@ -7,10 +8,38 @@ import { PonyfillResponse } from './Response.js';
|
|
|
7
8
|
import { PonyfillURL } from './URL.js';
|
|
8
9
|
import { fakePromise } from './utils.js';
|
|
9
10
|
const BASE64_SUFFIX = ';base64';
|
|
10
|
-
function getResponseForFile(url) {
|
|
11
|
+
async function getResponseForFile(url) {
|
|
11
12
|
const path = fileURLToPath(url);
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
try {
|
|
14
|
+
await fsPromises.access(path, fsPromises.constants.R_OK);
|
|
15
|
+
const stats = await fsPromises.stat(path, {
|
|
16
|
+
bigint: true,
|
|
17
|
+
});
|
|
18
|
+
const readable = createReadStream(path);
|
|
19
|
+
return new PonyfillResponse(readable, {
|
|
20
|
+
status: 200,
|
|
21
|
+
statusText: 'OK',
|
|
22
|
+
headers: {
|
|
23
|
+
'content-type': 'application/octet-stream',
|
|
24
|
+
'last-modified': stats.mtime.toUTCString(),
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
if (err.code === 'ENOENT') {
|
|
30
|
+
return new PonyfillResponse(null, {
|
|
31
|
+
status: 404,
|
|
32
|
+
statusText: 'Not Found',
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
else if (err.code === 'EACCES') {
|
|
36
|
+
return new PonyfillResponse(null, {
|
|
37
|
+
status: 403,
|
|
38
|
+
statusText: 'Forbidden',
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
throw err;
|
|
42
|
+
}
|
|
14
43
|
}
|
|
15
44
|
function getResponseForDataUri(url) {
|
|
16
45
|
const [mimeType = 'text/plain', ...datas] = url.substring(5).split(',');
|
|
@@ -62,7 +91,7 @@ export function fetchPonyfill(info, init) {
|
|
|
62
91
|
}
|
|
63
92
|
if (fetchRequest.url.startsWith('file:')) {
|
|
64
93
|
const response = getResponseForFile(fetchRequest.url);
|
|
65
|
-
return
|
|
94
|
+
return response;
|
|
66
95
|
}
|
|
67
96
|
if (fetchRequest.url.startsWith('blob:')) {
|
|
68
97
|
const response = getResponseForBlob(fetchRequest.url);
|
package/esm/fetchCurl.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { PassThrough, Readable
|
|
2
|
-
import { rootCertificates } from 'tls';
|
|
1
|
+
import { PassThrough, Readable } from 'node:stream';
|
|
2
|
+
import { rootCertificates } from 'node:tls';
|
|
3
|
+
import { createDeferredPromise } from '@whatwg-node/promise-helpers';
|
|
3
4
|
import { PonyfillResponse } from './Response.js';
|
|
4
|
-
import {
|
|
5
|
+
import { defaultHeadersSerializer, isNodeReadable, shouldRedirect } from './utils.js';
|
|
5
6
|
export function fetchCurl(fetchRequest) {
|
|
6
7
|
const { Curl, CurlFeature, CurlPause, CurlProgressFunc } = globalThis['libcurl'];
|
|
7
8
|
const curlHandle = new Curl();
|
|
@@ -17,12 +18,15 @@ export function fetchCurl(fetchRequest) {
|
|
|
17
18
|
curlHandle.setOpt('CAINFO_BLOB', rootCertificates.join('\n'));
|
|
18
19
|
}
|
|
19
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
|
+
}
|
|
20
28
|
curlHandle.setStreamProgressCallback(function () {
|
|
21
|
-
return
|
|
22
|
-
? process.env.DEBUG
|
|
23
|
-
? CurlProgressFunc.Continue
|
|
24
|
-
: 1
|
|
25
|
-
: 0;
|
|
29
|
+
return signal?.aborted ? (process.env.DEBUG ? CurlProgressFunc.Continue : 1) : 0;
|
|
26
30
|
});
|
|
27
31
|
if (fetchRequest['bodyType'] === 'String') {
|
|
28
32
|
curlHandle.setOpt('POSTFIELDS', fetchRequest['bodyInit']);
|
|
@@ -59,18 +63,17 @@ export function fetchCurl(fetchRequest) {
|
|
|
59
63
|
curlHandle.enable(CurlFeature.NoHeaderParsing);
|
|
60
64
|
const deferredPromise = createDeferredPromise();
|
|
61
65
|
let streamResolved;
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
deferredPromise.reject(e);
|
|
70
|
-
}
|
|
66
|
+
function onAbort() {
|
|
67
|
+
if (curlHandle.isOpen) {
|
|
68
|
+
try {
|
|
69
|
+
curlHandle.pause(CurlPause.Recv);
|
|
70
|
+
}
|
|
71
|
+
catch (e) {
|
|
72
|
+
deferredPromise.reject(e);
|
|
71
73
|
}
|
|
72
|
-
}
|
|
74
|
+
}
|
|
73
75
|
}
|
|
76
|
+
signal?.addEventListener('abort', onAbort, { once: true });
|
|
74
77
|
curlHandle.once('end', function endListener() {
|
|
75
78
|
try {
|
|
76
79
|
curlHandle.close();
|
|
@@ -78,6 +81,7 @@ export function fetchCurl(fetchRequest) {
|
|
|
78
81
|
catch (e) {
|
|
79
82
|
deferredPromise.reject(e);
|
|
80
83
|
}
|
|
84
|
+
signal?.removeEventListener('abort', onAbort);
|
|
81
85
|
});
|
|
82
86
|
curlHandle.once('error', function errorListener(error) {
|
|
83
87
|
if (streamResolved && !streamResolved.closed && !streamResolved.destroyed) {
|
|
@@ -97,42 +101,17 @@ export function fetchCurl(fetchRequest) {
|
|
|
97
101
|
}
|
|
98
102
|
});
|
|
99
103
|
curlHandle.once('stream', function streamListener(stream, status, headersBuf) {
|
|
100
|
-
const outputStream = new PassThrough()
|
|
101
|
-
streamPromises
|
|
102
|
-
.pipeline(stream, outputStream, {
|
|
104
|
+
const outputStream = stream.pipe(new PassThrough(), {
|
|
103
105
|
end: true,
|
|
104
|
-
|
|
105
|
-
})
|
|
106
|
-
.then(() => {
|
|
107
|
-
if (!stream.destroyed) {
|
|
108
|
-
stream.resume();
|
|
109
|
-
}
|
|
110
|
-
})
|
|
111
|
-
.catch(deferredPromise.reject);
|
|
112
|
-
if (fetchRequest['_signal']) {
|
|
113
|
-
outputStream.once('error', () => {
|
|
114
|
-
if (!fetchRequest['_signal']?.aborted) {
|
|
115
|
-
fetchRequest['_signal']?.sendAbort?.();
|
|
116
|
-
}
|
|
117
|
-
});
|
|
118
|
-
outputStream.once('close', () => {
|
|
119
|
-
if (!fetchRequest['_signal']?.aborted) {
|
|
120
|
-
fetchRequest['_signal']?.sendAbort?.();
|
|
121
|
-
}
|
|
122
|
-
});
|
|
123
|
-
outputStream.once('destroy', () => {
|
|
124
|
-
if (!fetchRequest['_signal']?.aborted) {
|
|
125
|
-
fetchRequest['_signal']?.sendAbort?.();
|
|
126
|
-
}
|
|
127
|
-
});
|
|
128
|
-
}
|
|
106
|
+
});
|
|
129
107
|
const headersFlat = headersBuf
|
|
130
108
|
.toString('utf8')
|
|
131
109
|
.split(/\r?\n|\r/g)
|
|
132
110
|
.filter(headerFilter => {
|
|
133
111
|
if (headerFilter && !headerFilter.startsWith('HTTP/')) {
|
|
134
112
|
if (fetchRequest.redirect === 'error' &&
|
|
135
|
-
|
|
113
|
+
headerFilter.toLowerCase().includes('location') &&
|
|
114
|
+
shouldRedirect(status)) {
|
|
136
115
|
if (!stream.destroyed) {
|
|
137
116
|
stream.resume();
|
|
138
117
|
}
|
|
@@ -153,18 +132,8 @@ export function fetchCurl(fetchRequest) {
|
|
|
153
132
|
deferredPromise.resolve(ponyfillResponse);
|
|
154
133
|
streamResolved = outputStream;
|
|
155
134
|
});
|
|
156
|
-
|
|
157
|
-
try {
|
|
158
|
-
count = Curl.getCount();
|
|
159
|
-
}
|
|
160
|
-
catch { }
|
|
161
|
-
if (count > 0) {
|
|
162
|
-
setImmediate(() => {
|
|
163
|
-
curlHandle.perform();
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
else {
|
|
135
|
+
setImmediate(() => {
|
|
167
136
|
curlHandle.perform();
|
|
168
|
-
}
|
|
137
|
+
});
|
|
169
138
|
return deferredPromise.promise;
|
|
170
139
|
}
|
package/esm/fetchNodeHttp.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { request as httpRequest } from 'http';
|
|
2
|
-
import { request as httpsRequest } from 'https';
|
|
3
|
-
import { PassThrough, Readable
|
|
4
|
-
import { createBrotliDecompress, createGunzip, createInflate, createInflateRaw } from 'zlib';
|
|
1
|
+
import { request as httpRequest, STATUS_CODES } from 'node:http';
|
|
2
|
+
import { request as httpsRequest } from 'node:https';
|
|
3
|
+
import { PassThrough, Readable } from 'node:stream';
|
|
4
|
+
import { createBrotliDecompress, createGunzip, createInflate, createInflateRaw } from 'node:zlib';
|
|
5
|
+
import { handleMaybePromise } from '@whatwg-node/promise-helpers';
|
|
5
6
|
import { PonyfillRequest } from './Request.js';
|
|
6
7
|
import { PonyfillResponse } from './Response.js';
|
|
7
8
|
import { PonyfillURL } from './URL.js';
|
|
8
|
-
import { getHeadersObj, isNodeReadable } from './utils.js';
|
|
9
|
+
import { endStream, getHeadersObj, isNodeReadable, pipeThrough, safeWrite, shouldRedirect, } from './utils.js';
|
|
9
10
|
function getRequestFnForProtocol(url) {
|
|
10
11
|
if (url.startsWith('http:')) {
|
|
11
12
|
return httpRequest;
|
|
@@ -19,30 +20,24 @@ export function fetchNodeHttp(fetchRequest) {
|
|
|
19
20
|
return new Promise((resolve, reject) => {
|
|
20
21
|
try {
|
|
21
22
|
const requestFn = getRequestFnForProtocol(fetchRequest.parsedUrl?.protocol || fetchRequest.url);
|
|
22
|
-
const nodeReadable = (fetchRequest.body != null
|
|
23
|
-
? isNodeReadable(fetchRequest.body)
|
|
24
|
-
? fetchRequest.body
|
|
25
|
-
: Readable.from(fetchRequest.body)
|
|
26
|
-
: null);
|
|
27
23
|
const headersSerializer = fetchRequest.headersSerializer || getHeadersObj;
|
|
28
24
|
const nodeHeaders = headersSerializer(fetchRequest.headers);
|
|
29
|
-
|
|
30
|
-
|
|
25
|
+
nodeHeaders['accept-encoding'] ||= 'gzip, deflate, br';
|
|
26
|
+
nodeHeaders['user-agent'] ||= 'node';
|
|
27
|
+
let signal;
|
|
28
|
+
if (fetchRequest._signal == null) {
|
|
29
|
+
signal = undefined;
|
|
30
|
+
}
|
|
31
|
+
else if (fetchRequest._signal) {
|
|
32
|
+
signal = fetchRequest._signal;
|
|
31
33
|
}
|
|
32
34
|
let nodeRequest;
|
|
33
|
-
//
|
|
34
|
-
if (fetchRequest.parsedUrl
|
|
35
|
-
nodeRequest = requestFn({
|
|
36
|
-
auth: fetchRequest.parsedUrl.username
|
|
37
|
-
? `${fetchRequest.parsedUrl.username}:${fetchRequest.parsedUrl.password}`
|
|
38
|
-
: undefined,
|
|
39
|
-
hostname: fetchRequest.parsedUrl.hostname,
|
|
35
|
+
// If it is our ponyfilled Request, it should have `parsedUrl` which is a `URL` object
|
|
36
|
+
if (fetchRequest.parsedUrl) {
|
|
37
|
+
nodeRequest = requestFn(fetchRequest.parsedUrl, {
|
|
40
38
|
method: fetchRequest.method,
|
|
41
|
-
path: fetchRequest.parsedUrl.pathname + (fetchRequest.parsedUrl.search || ''),
|
|
42
|
-
port: fetchRequest.parsedUrl.port,
|
|
43
|
-
protocol: fetchRequest.parsedUrl.protocol,
|
|
44
39
|
headers: nodeHeaders,
|
|
45
|
-
signal
|
|
40
|
+
signal,
|
|
46
41
|
agent: fetchRequest.agent,
|
|
47
42
|
});
|
|
48
43
|
}
|
|
@@ -50,10 +45,11 @@ export function fetchNodeHttp(fetchRequest) {
|
|
|
50
45
|
nodeRequest = requestFn(fetchRequest.url, {
|
|
51
46
|
method: fetchRequest.method,
|
|
52
47
|
headers: nodeHeaders,
|
|
53
|
-
signal
|
|
48
|
+
signal,
|
|
54
49
|
agent: fetchRequest.agent,
|
|
55
50
|
});
|
|
56
51
|
}
|
|
52
|
+
nodeRequest.once('error', reject);
|
|
57
53
|
nodeRequest.once('response', nodeResponse => {
|
|
58
54
|
let outputStream;
|
|
59
55
|
const contentEncoding = nodeResponse.headers['content-encoding'];
|
|
@@ -73,10 +69,8 @@ export function fetchNodeHttp(fetchRequest) {
|
|
|
73
69
|
case 'br':
|
|
74
70
|
outputStream = createBrotliDecompress();
|
|
75
71
|
break;
|
|
76
|
-
default:
|
|
77
|
-
outputStream = new PassThrough();
|
|
78
72
|
}
|
|
79
|
-
if (nodeResponse.headers.location) {
|
|
73
|
+
if (nodeResponse.headers.location && shouldRedirect(nodeResponse.statusCode)) {
|
|
80
74
|
if (fetchRequest.redirect === 'error') {
|
|
81
75
|
const redirectError = new Error('Redirects are not allowed');
|
|
82
76
|
reject(redirectError);
|
|
@@ -94,48 +88,50 @@ export function fetchNodeHttp(fetchRequest) {
|
|
|
94
88
|
return;
|
|
95
89
|
}
|
|
96
90
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
}
|
|
106
|
-
})
|
|
107
|
-
.catch(reject);
|
|
108
|
-
if (fetchRequest['_signal']) {
|
|
109
|
-
outputStream.once('error', () => {
|
|
110
|
-
if (!fetchRequest['_signal']?.aborted) {
|
|
111
|
-
fetchRequest['_signal']?.sendAbort?.();
|
|
112
|
-
}
|
|
113
|
-
});
|
|
114
|
-
outputStream.once('close', () => {
|
|
115
|
-
if (!fetchRequest['_signal']?.aborted) {
|
|
116
|
-
fetchRequest['_signal']?.sendAbort?.();
|
|
91
|
+
outputStream ||= new PassThrough();
|
|
92
|
+
pipeThrough({
|
|
93
|
+
src: nodeResponse,
|
|
94
|
+
dest: outputStream,
|
|
95
|
+
signal,
|
|
96
|
+
onError: e => {
|
|
97
|
+
if (!nodeResponse.destroyed) {
|
|
98
|
+
nodeResponse.destroy(e);
|
|
117
99
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
if (!fetchRequest['_signal']?.aborted) {
|
|
121
|
-
fetchRequest['_signal']?.sendAbort?.();
|
|
100
|
+
if (!outputStream.destroyed) {
|
|
101
|
+
outputStream.destroy(e);
|
|
122
102
|
}
|
|
123
|
-
|
|
103
|
+
reject(e);
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
const statusCode = nodeResponse.statusCode || 200;
|
|
107
|
+
let statusText = nodeResponse.statusMessage || STATUS_CODES[statusCode];
|
|
108
|
+
if (statusText == null) {
|
|
109
|
+
statusText = '';
|
|
124
110
|
}
|
|
125
|
-
const ponyfillResponse = new PonyfillResponse(outputStream, {
|
|
126
|
-
status:
|
|
127
|
-
statusText
|
|
111
|
+
const ponyfillResponse = new PonyfillResponse(outputStream || nodeResponse, {
|
|
112
|
+
status: statusCode,
|
|
113
|
+
statusText,
|
|
128
114
|
headers: nodeResponse.headers,
|
|
129
115
|
url: fetchRequest.url,
|
|
116
|
+
signal,
|
|
130
117
|
});
|
|
131
118
|
resolve(ponyfillResponse);
|
|
132
119
|
});
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
nodeReadable.pipe(nodeRequest);
|
|
120
|
+
if (fetchRequest['_buffer'] != null) {
|
|
121
|
+
handleMaybePromise(() => safeWrite(fetchRequest['_buffer'], nodeRequest), () => endStream(nodeRequest), reject);
|
|
136
122
|
}
|
|
137
123
|
else {
|
|
138
|
-
|
|
124
|
+
const nodeReadable = (fetchRequest.body != null
|
|
125
|
+
? isNodeReadable(fetchRequest.body)
|
|
126
|
+
? fetchRequest.body
|
|
127
|
+
: Readable.from(fetchRequest.body)
|
|
128
|
+
: null);
|
|
129
|
+
if (nodeReadable) {
|
|
130
|
+
nodeReadable.pipe(nodeRequest);
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
endStream(nodeRequest);
|
|
134
|
+
}
|
|
139
135
|
}
|
|
140
136
|
}
|
|
141
137
|
catch (e) {
|
package/esm/index.js
CHANGED
|
@@ -16,6 +16,3 @@ export { PonyfillCompressionStream as CompressionStream } from './CompressionStr
|
|
|
16
16
|
export { PonyfillDecompressionStream as DecompressionStream } from './DecompressionStream.js';
|
|
17
17
|
export { PonyfillIteratorObject as IteratorObject } from './IteratorObject.js';
|
|
18
18
|
export { PonyfillTextDecoderStream as TextDecoderStream, PonyfillTextEncoderStream as TextEncoderStream, } from './TextEncoderDecoderStream.js';
|
|
19
|
-
export { PonyfillAbortController as AbortController } from './AbortController.js';
|
|
20
|
-
export { PonyfillAbortSignal as AbortSignal } from './AbortSignal.js';
|
|
21
|
-
export { PonyfillAbortError as AbortError } from './AbortError.js';
|