[Spec] Should check body _source_ on redirect (#866)

* correct stream tests

* bump Node.JS min to 10.17

* lint
This commit is contained in:
Konstantin Vyatkin 2020-06-10 07:16:51 -04:00 committed by GitHub
parent df1a4fafa9
commit 1cb9070cce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 26 additions and 41 deletions

View File

@ -17,7 +17,7 @@
],
"types": "./@types/index.d.ts",
"engines": {
"node": ">=10.16"
"node": ">=10.17"
},
"scripts": {
"build": "rollup -c",
@ -60,7 +60,6 @@
"mocha": "^7.2.0",
"p-timeout": "^3.2.0",
"parted": "^0.1.1",
"resumer": "0.0.0",
"rollup": "^2.15.0",
"string-to-arraybuffer": "^1.0.2",
"tsd": "^0.11.0",

View File

@ -208,6 +208,10 @@ async function consumeBody(data) {
if (body.readableEnded === true || body._readableState.ended === true) {
try {
if (accum.every(c => typeof c === 'string')) {
return Buffer.from(accum.join(''));
}
return Buffer.concat(accum, accumBytes);
} catch (error) {
throw new FetchError(`Could not create Buffer from response body for ${data.url}: ${error.message}`, 'system', error);

View File

@ -12,7 +12,7 @@ import zlib from 'zlib';
import Stream, {PassThrough, pipeline as pump} from 'stream';
import dataUriToBuffer from 'data-uri-to-buffer';
import {writeToStream, getTotalBytes} from './body.js';
import {writeToStream} from './body.js';
import Response from './response.js';
import Headers, {fromRawHeaders} from './headers.js';
import Request, {getNodeRequestOptions} from './request.js';
@ -153,7 +153,7 @@ export default async function fetch(url, options_) {
};
// HTTP-redirect fetch step 9
if (response_.statusCode !== 303 && request.body && getTotalBytes(request) === null) {
if (response_.statusCode !== 303 && request.body && options_.body instanceof Stream.Readable) {
reject(new FetchError('Cannot follow redirect with body being a readable stream', 'unsupported-redirect'));
finalize();
return;

View File

@ -1,4 +1,5 @@
// Test tools
/* eslint-disable node/no-unsupported-features/node-builtins */
import zlib from 'zlib';
import crypto from 'crypto';
import http from 'http';
@ -10,7 +11,6 @@ import chai from 'chai';
import chaiPromised from 'chai-as-promised';
import chaiIterator from 'chai-iterator';
import chaiString from 'chai-string';
import resumer from 'resumer';
import FormData from 'form-data';
import stringToArrayBuffer from 'string-to-arraybuffer';
import delay from 'delay';
@ -404,7 +404,7 @@ describe('node-fetch', () => {
const url = `${base}redirect/307`;
const options = {
method: 'PATCH',
body: resumer().queue('a=1').end()
body: stream.Readable.from('tada')
};
return expect(fetch(url, options)).to.eventually.be.rejected
.and.be.an.instanceOf(FetchError)
@ -1250,13 +1250,10 @@ describe('node-fetch', () => {
});
it('should allow POST request with readable stream as body', () => {
let body = resumer().queue('a=1').end();
body = body.pipe(new stream.PassThrough());
const url = `${base}inspect`;
const options = {
method: 'POST',
body
body: stream.Readable.from('a=1')
};
return fetch(url, options).then(res => {
return res.json();
@ -1971,27 +1968,16 @@ describe('node-fetch', () => {
// Issue #414
it('should reject if attempt to accumulate body stream throws', () => {
let body = resumer().queue('a=1').end();
body = body.pipe(new stream.PassThrough());
const res = new Response(body);
const bufferConcat = Buffer.concat;
const restoreBufferConcat = () => {
Buffer.concat = bufferConcat;
};
const res = new Response(stream.Readable.from((async function * () {
yield Buffer.from('tada');
await new Promise(resolve => setTimeout(resolve, 200));
yield {tada: 'yes'};
})()));
Buffer.concat = () => {
throw new Error('embedded error');
};
const textPromise = res.text();
// Ensure that `Buffer.concat` is always restored:
textPromise.then(restoreBufferConcat, restoreBufferConcat);
return expect(textPromise).to.eventually.be.rejected
return expect(res.text()).to.eventually.be.rejected
.and.be.an.instanceOf(FetchError)
.and.include({type: 'system'})
.and.have.property('message').that.includes('Could not create Buffer')
.and.that.includes('embedded error');
.and.have.property('message').that.include('Could not create Buffer');
});
it('supports supplying a lookup function to the agent', () => {
@ -2053,8 +2039,7 @@ describe('node-fetch', () => {
const url = `${base}hello`;
const bodyContent = 'a=1';
let streamBody = resumer().queue(bodyContent).end();
streamBody = streamBody.pipe(new stream.PassThrough());
const streamBody = stream.Readable.from(bodyContent);
const streamRequest = new Request(url, {
method: 'POST',
body: streamBody,

View File

@ -1,10 +1,11 @@
/* eslint-disable node/no-unsupported-features/node-builtins */
import stream from 'stream';
import http from 'http';
import AbortController from 'abort-controller';
import chai from 'chai';
import FormData from 'form-data';
import Blob from 'fetch-blob';
import resumer from 'resumer';
import stringToArrayBuffer from 'string-to-arraybuffer';
import TestServer from './utils/server.js';
@ -200,8 +201,7 @@ describe('Request', () => {
it('should support clone() method', () => {
const url = base;
let body = resumer().queue('a=1').end();
body = body.pipe(new stream.PassThrough());
const body = stream.Readable.from('a=1');
const agent = new http.Agent();
const {signal} = new AbortController();
const request = new Request(url, {

View File

@ -1,6 +1,7 @@
/* eslint-disable node/no-unsupported-features/node-builtins */
import * as stream from 'stream';
import chai from 'chai';
import resumer from 'resumer';
import stringToArrayBuffer from 'string-to-arraybuffer';
import Blob from 'fetch-blob';
import {Response} from '../src/index.js';
@ -54,9 +55,7 @@ describe('Response', () => {
});
it('should support empty options', () => {
let body = resumer().queue('a=1').end();
body = body.pipe(new stream.PassThrough());
const res = new Response(body);
const res = new Response(stream.Readable.from('a=1'));
return res.text().then(result => {
expect(result).to.equal('a=1');
});
@ -107,8 +106,7 @@ describe('Response', () => {
});
it('should support clone() method', () => {
let body = resumer().queue('a=1').end();
body = body.pipe(new stream.PassThrough());
const body = stream.Readable.from('a=1');
const res = new Response(body, {
headers: {
a: '1'
@ -131,8 +129,7 @@ describe('Response', () => {
});
it('should support stream as body', () => {
let body = resumer().queue('a=1').end();
body = body.pipe(new stream.PassThrough());
const body = stream.Readable.from('a=1');
const res = new Response(body);
return res.text().then(result => {
expect(result).to.equal('a=1');