@whatwg-node/node-fetch 0.7.17 → 0.7.18-alpha-20250414142501-d6dc56a6dae8ef2cab5ea56aad70f6fd874ade7e
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 +54 -27
- package/esm/Body.js +54 -26
- package/package.json +3 -3
package/cjs/Body.js
CHANGED
@@ -1,12 +1,11 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.PonyfillBody = void 0;
|
4
|
-
const tslib_1 = require("tslib");
|
5
4
|
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
6
5
|
const node_buffer_1 = require("node:buffer");
|
7
6
|
const node_http_1 = require("node:http");
|
8
7
|
const node_stream_1 = require("node:stream");
|
9
|
-
const busboy_1 =
|
8
|
+
const busboy_1 = require("@fastify/busboy");
|
10
9
|
const promise_helpers_1 = require("@whatwg-node/promise-helpers");
|
11
10
|
const Blob_js_1 = require("./Blob.js");
|
12
11
|
const File_js_1 = require("./File.js");
|
@@ -189,56 +188,84 @@ class PonyfillBody {
|
|
189
188
|
...opts?.formDataLimits,
|
190
189
|
};
|
191
190
|
return new Promise((resolve, reject) => {
|
192
|
-
const
|
191
|
+
const stream = this.body?.readable;
|
192
|
+
if (!stream) {
|
193
|
+
return reject(new Error('No stream available'));
|
194
|
+
}
|
195
|
+
// form data file that is currently being processed, it's
|
196
|
+
// important to keep track of it in case the stream ends early
|
197
|
+
let currFile = null;
|
198
|
+
const bb = new busboy_1.Busboy({
|
193
199
|
headers: {
|
200
|
+
'content-length': typeof this.contentLength === 'number'
|
201
|
+
? this.contentLength.toString()
|
202
|
+
: this.contentLength || '',
|
194
203
|
'content-type': this.contentType || '',
|
195
204
|
},
|
196
205
|
limits: formDataLimits,
|
197
|
-
|
206
|
+
defCharset: 'utf-8',
|
198
207
|
});
|
199
|
-
|
200
|
-
|
201
|
-
|
208
|
+
const complete = (err) => {
|
209
|
+
stream.unpipe(bb);
|
210
|
+
bb.destroy();
|
211
|
+
if (currFile) {
|
212
|
+
currFile.destroy();
|
213
|
+
currFile = null;
|
214
|
+
}
|
215
|
+
if (err) {
|
216
|
+
reject(err);
|
217
|
+
}
|
218
|
+
else {
|
219
|
+
// no error occured, this is a successful end/complete/finish
|
220
|
+
resolve(this._formData);
|
221
|
+
}
|
222
|
+
};
|
223
|
+
// we dont need to listen to the stream close event because bb will close or error when necessary
|
224
|
+
// stream.on('close', complete);
|
225
|
+
// stream can be aborted, for example
|
226
|
+
stream.on('error', complete);
|
227
|
+
bb.on('field', (name, value, fieldnameTruncated, valueTruncated) => {
|
228
|
+
if (fieldnameTruncated) {
|
229
|
+
return complete(new Error(`Field name size exceeded: ${formDataLimits?.fieldNameSize} bytes`));
|
202
230
|
}
|
203
231
|
if (valueTruncated) {
|
204
|
-
|
232
|
+
return complete(new Error(`Field value size exceeded: ${formDataLimits?.fieldSize} bytes`));
|
205
233
|
}
|
206
234
|
this._formData.set(name, value);
|
207
235
|
});
|
208
|
-
bb.on('
|
209
|
-
|
210
|
-
});
|
211
|
-
bb.on('file', (name, fileStream, { filename, mimeType }) => {
|
236
|
+
bb.on('file', (name, fileStream, filename, _transferEncoding, mimeType) => {
|
237
|
+
currFile = fileStream;
|
212
238
|
const chunks = [];
|
213
|
-
fileStream.on('limit', () => {
|
214
|
-
reject(new Error(`File size limit exceeded: ${formDataLimits?.fileSize} bytes`));
|
215
|
-
});
|
216
239
|
fileStream.on('data', chunk => {
|
217
240
|
chunks.push(chunk);
|
218
241
|
});
|
242
|
+
fileStream.on('error', complete);
|
243
|
+
fileStream.on('limit', () => {
|
244
|
+
complete(new Error(`File size limit exceeded: ${formDataLimits?.fileSize} bytes`));
|
245
|
+
});
|
219
246
|
fileStream.on('close', () => {
|
220
247
|
if (fileStream.truncated) {
|
221
|
-
|
248
|
+
complete(new Error(`File size limit exceeded: ${formDataLimits?.fileSize} bytes`));
|
222
249
|
}
|
250
|
+
currFile = null;
|
223
251
|
const file = new File_js_1.PonyfillFile(chunks, filename, { type: mimeType });
|
224
252
|
this._formData.set(name, file);
|
225
253
|
});
|
226
254
|
});
|
255
|
+
bb.on('fieldsLimit', () => {
|
256
|
+
complete(new Error(`Fields limit exceeded: ${formDataLimits?.fields}`));
|
257
|
+
});
|
227
258
|
bb.on('filesLimit', () => {
|
228
|
-
|
259
|
+
complete(new Error(`Files limit exceeded: ${formDataLimits?.files}`));
|
229
260
|
});
|
230
261
|
bb.on('partsLimit', () => {
|
231
|
-
|
232
|
-
});
|
233
|
-
bb.on('close', () => {
|
234
|
-
resolve(this._formData);
|
235
|
-
});
|
236
|
-
bb.on('error', (err = 'An error occurred while parsing the form data') => {
|
237
|
-
const errMessage = err.message || err.toString();
|
238
|
-
// @ts-ignore - `cause` is in `TypeError`in node
|
239
|
-
reject(new TypeError(errMessage, err.cause));
|
262
|
+
complete(new Error(`Parts limit exceeded: ${formDataLimits?.parts}`));
|
240
263
|
});
|
241
|
-
|
264
|
+
bb.on('end', complete);
|
265
|
+
bb.on('finish', complete);
|
266
|
+
bb.on('close', complete);
|
267
|
+
bb.on('error', complete);
|
268
|
+
stream.pipe(bb);
|
242
269
|
});
|
243
270
|
}
|
244
271
|
buffer() {
|
package/esm/Body.js
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
import { Buffer } from 'node:buffer';
|
3
3
|
import { IncomingMessage } from 'node:http';
|
4
4
|
import { Readable } from 'node:stream';
|
5
|
-
import
|
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';
|
@@ -185,56 +185,84 @@ export class PonyfillBody {
|
|
185
185
|
...opts?.formDataLimits,
|
186
186
|
};
|
187
187
|
return new Promise((resolve, reject) => {
|
188
|
-
const
|
188
|
+
const stream = this.body?.readable;
|
189
|
+
if (!stream) {
|
190
|
+
return reject(new Error('No stream available'));
|
191
|
+
}
|
192
|
+
// form data file that is currently being processed, it's
|
193
|
+
// important to keep track of it in case the stream ends early
|
194
|
+
let currFile = null;
|
195
|
+
const bb = new Busboy({
|
189
196
|
headers: {
|
197
|
+
'content-length': typeof this.contentLength === 'number'
|
198
|
+
? this.contentLength.toString()
|
199
|
+
: this.contentLength || '',
|
190
200
|
'content-type': this.contentType || '',
|
191
201
|
},
|
192
202
|
limits: formDataLimits,
|
193
|
-
|
203
|
+
defCharset: 'utf-8',
|
194
204
|
});
|
195
|
-
|
196
|
-
|
197
|
-
|
205
|
+
const complete = (err) => {
|
206
|
+
stream.unpipe(bb);
|
207
|
+
bb.destroy();
|
208
|
+
if (currFile) {
|
209
|
+
currFile.destroy();
|
210
|
+
currFile = null;
|
211
|
+
}
|
212
|
+
if (err) {
|
213
|
+
reject(err);
|
214
|
+
}
|
215
|
+
else {
|
216
|
+
// no error occured, this is a successful end/complete/finish
|
217
|
+
resolve(this._formData);
|
218
|
+
}
|
219
|
+
};
|
220
|
+
// we dont need to listen to the stream close event because bb will close or error when necessary
|
221
|
+
// stream.on('close', complete);
|
222
|
+
// stream can be aborted, for example
|
223
|
+
stream.on('error', complete);
|
224
|
+
bb.on('field', (name, value, fieldnameTruncated, valueTruncated) => {
|
225
|
+
if (fieldnameTruncated) {
|
226
|
+
return complete(new Error(`Field name size exceeded: ${formDataLimits?.fieldNameSize} bytes`));
|
198
227
|
}
|
199
228
|
if (valueTruncated) {
|
200
|
-
|
229
|
+
return complete(new Error(`Field value size exceeded: ${formDataLimits?.fieldSize} bytes`));
|
201
230
|
}
|
202
231
|
this._formData.set(name, value);
|
203
232
|
});
|
204
|
-
bb.on('
|
205
|
-
|
206
|
-
});
|
207
|
-
bb.on('file', (name, fileStream, { filename, mimeType }) => {
|
233
|
+
bb.on('file', (name, fileStream, filename, _transferEncoding, mimeType) => {
|
234
|
+
currFile = fileStream;
|
208
235
|
const chunks = [];
|
209
|
-
fileStream.on('limit', () => {
|
210
|
-
reject(new Error(`File size limit exceeded: ${formDataLimits?.fileSize} bytes`));
|
211
|
-
});
|
212
236
|
fileStream.on('data', chunk => {
|
213
237
|
chunks.push(chunk);
|
214
238
|
});
|
239
|
+
fileStream.on('error', complete);
|
240
|
+
fileStream.on('limit', () => {
|
241
|
+
complete(new Error(`File size limit exceeded: ${formDataLimits?.fileSize} bytes`));
|
242
|
+
});
|
215
243
|
fileStream.on('close', () => {
|
216
244
|
if (fileStream.truncated) {
|
217
|
-
|
245
|
+
complete(new Error(`File size limit exceeded: ${formDataLimits?.fileSize} bytes`));
|
218
246
|
}
|
247
|
+
currFile = null;
|
219
248
|
const file = new PonyfillFile(chunks, filename, { type: mimeType });
|
220
249
|
this._formData.set(name, file);
|
221
250
|
});
|
222
251
|
});
|
252
|
+
bb.on('fieldsLimit', () => {
|
253
|
+
complete(new Error(`Fields limit exceeded: ${formDataLimits?.fields}`));
|
254
|
+
});
|
223
255
|
bb.on('filesLimit', () => {
|
224
|
-
|
256
|
+
complete(new Error(`Files limit exceeded: ${formDataLimits?.files}`));
|
225
257
|
});
|
226
258
|
bb.on('partsLimit', () => {
|
227
|
-
|
228
|
-
});
|
229
|
-
bb.on('close', () => {
|
230
|
-
resolve(this._formData);
|
231
|
-
});
|
232
|
-
bb.on('error', (err = 'An error occurred while parsing the form data') => {
|
233
|
-
const errMessage = err.message || err.toString();
|
234
|
-
// @ts-ignore - `cause` is in `TypeError`in node
|
235
|
-
reject(new TypeError(errMessage, err.cause));
|
259
|
+
complete(new Error(`Parts limit exceeded: ${formDataLimits?.parts}`));
|
236
260
|
});
|
237
|
-
|
261
|
+
bb.on('end', complete);
|
262
|
+
bb.on('finish', complete);
|
263
|
+
bb.on('close', complete);
|
264
|
+
bb.on('error', complete);
|
265
|
+
stream.pipe(bb);
|
238
266
|
});
|
239
267
|
}
|
240
268
|
buffer() {
|
package/package.json
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
{
|
2
2
|
"name": "@whatwg-node/node-fetch",
|
3
|
-
"version": "0.7.
|
3
|
+
"version": "0.7.18-alpha-20250414142501-d6dc56a6dae8ef2cab5ea56aad70f6fd874ade7e",
|
4
4
|
"description": "Fetch API implementation for Node",
|
5
5
|
"sideEffects": false,
|
6
6
|
"dependencies": {
|
7
|
+
"@fastify/busboy": "^3.1.1",
|
7
8
|
"@whatwg-node/disposablestack": "^0.0.6",
|
8
|
-
"@whatwg-node/promise-helpers": "
|
9
|
-
"busboy": "^1.6.0",
|
9
|
+
"@whatwg-node/promise-helpers": "1.3.1-alpha-20250414142501-d6dc56a6dae8ef2cab5ea56aad70f6fd874ade7e",
|
10
10
|
"tslib": "^2.6.3"
|
11
11
|
},
|
12
12
|
"repository": {
|