Skip to content

Commit 0fc414c

Browse files
authored
Allow third party blob implementation (#629)
* Support making request with any blob that have stream() method * don't clone blob when cloning request * check for blob api that node-fetch uses
1 parent d8f5ba0 commit 0fc414c

File tree

1 file changed

+37
-12
lines changed

1 file changed

+37
-12
lines changed

src/body.js

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,8 @@ export default function Body(body, {
3737
} else if (isURLSearchParams(body)) {
3838
// body is a URLSearchParams
3939
body = Buffer.from(body.toString());
40-
} else if (body instanceof Blob) {
40+
} else if (isBlob(body)) {
4141
// body is blob
42-
body = body[BUFFER];
4342
} else if (Buffer.isBuffer(body)) {
4443
// body is Buffer
4544
} else if (Object.prototype.toString.call(body) === '[object ArrayBuffer]') {
@@ -191,18 +190,25 @@ function consumeBody() {
191190
return Body.Promise.reject(this[INTERNALS].error);
192191
}
193192

193+
let body = this.body;
194+
194195
// body is null
195-
if (this.body === null) {
196+
if (body === null) {
196197
return Body.Promise.resolve(Buffer.alloc(0));
197198
}
198199

200+
// body is blob
201+
if (isBlob(body)) {
202+
body = body.stream();
203+
}
204+
199205
// body is buffer
200-
if (Buffer.isBuffer(this.body)) {
201-
return Body.Promise.resolve(this.body);
206+
if (Buffer.isBuffer(body)) {
207+
return Body.Promise.resolve(body);
202208
}
203209

204210
// istanbul ignore if: should never happen
205-
if (!(this.body instanceof Stream)) {
211+
if (!(body instanceof Stream)) {
206212
return Body.Promise.resolve(Buffer.alloc(0));
207213
}
208214

@@ -224,7 +230,7 @@ function consumeBody() {
224230
}
225231

226232
// handle stream errors
227-
this.body.on('error', err => {
233+
body.on('error', err => {
228234
if (err.name === 'AbortError') {
229235
// if the request was aborted, reject with this Error
230236
abort = true;
@@ -235,7 +241,7 @@ function consumeBody() {
235241
}
236242
});
237243

238-
this.body.on('data', chunk => {
244+
body.on('data', chunk => {
239245
if (abort || chunk === null) {
240246
return;
241247
}
@@ -250,7 +256,7 @@ function consumeBody() {
250256
accum.push(chunk);
251257
});
252258

253-
this.body.on('end', () => {
259+
body.on('end', () => {
254260
if (abort) {
255261
return;
256262
}
@@ -355,6 +361,22 @@ function isURLSearchParams(obj) {
355361
typeof obj.sort === 'function';
356362
}
357363

364+
/**
365+
* Check if `obj` is a W3C `Blob` object (which `File` inherits from)
366+
* @param {*} obj
367+
* @return {boolean}
368+
*/
369+
function isBlob(obj) {
370+
return typeof obj === 'object' &&
371+
typeof obj.arrayBuffer === 'function' &&
372+
typeof obj.type === 'string' &&
373+
typeof obj.stream === 'function' &&
374+
typeof obj.constructor === 'function' &&
375+
typeof obj.constructor.name === 'string' &&
376+
/^(Blob|File)$/.test(obj.constructor.name) &&
377+
/^(Blob|File)$/.test(obj[Symbol.toStringTag])
378+
}
379+
358380
/**
359381
* Clone body given Res/Req instance
360382
*
@@ -407,7 +429,7 @@ export function extractContentType(body) {
407429
} else if (isURLSearchParams(body)) {
408430
// body is a URLSearchParams
409431
return 'application/x-www-form-urlencoded;charset=UTF-8';
410-
} else if (body instanceof Blob) {
432+
} else if (isBlob(body)) {
411433
// body is blob
412434
return body.type || null;
413435
} else if (Buffer.isBuffer(body)) {
@@ -448,6 +470,8 @@ export function getTotalBytes(instance) {
448470
if (body === null) {
449471
// body is null
450472
return 0;
473+
} else if (isBlob(body)) {
474+
return body.size;
451475
} else if (Buffer.isBuffer(body)) {
452476
// body is buffer
453477
return body.length;
@@ -460,8 +484,7 @@ export function getTotalBytes(instance) {
460484
return null;
461485
} else {
462486
// body is stream
463-
// can't really do much about this
464-
return null;
487+
return instance.size || null;
465488
}
466489
}
467490

@@ -477,6 +500,8 @@ export function writeToStream(dest, instance) {
477500
if (body === null) {
478501
// body is null
479502
dest.end();
503+
} else if (isBlob(body)) {
504+
body.stream().pipe(dest);
480505
} else if (Buffer.isBuffer(body)) {
481506
// body is buffer
482507
dest.write(body);

0 commit comments

Comments
 (0)