Backport v3 handling of chunked transfer end
The v2 backport produced invalid errors in some situations.
This commit is contained in:
parent
afb36f6c17
commit
2a2dffa882
51
src/index.js
51
src/index.js
|
@ -352,26 +352,47 @@ export default function fetch(url, opts) {
|
||||||
};
|
};
|
||||||
|
|
||||||
function fixResponseChunkedTransferBadEnding(request, errorCallback) {
|
function fixResponseChunkedTransferBadEnding(request, errorCallback) {
|
||||||
let socket;
|
const LAST_CHUNK = Buffer.from('0\r\n\r\n');
|
||||||
|
|
||||||
request.on('socket', s => {
|
let isChunkedTransfer = false;
|
||||||
socket = s;
|
let properLastChunkReceived = false;
|
||||||
});
|
let previousChunk;
|
||||||
|
|
||||||
request.on('response', response => {
|
request.on('response', response => {
|
||||||
const {headers} = response;
|
const {headers} = response;
|
||||||
if (headers['transfer-encoding'] === 'chunked' && !headers['content-length']) {
|
isChunkedTransfer = headers['transfer-encoding'] === 'chunked' && !headers['content-length'];
|
||||||
response.once('close', hadError => {
|
});
|
||||||
// if a data listener is still present we didn't end cleanly
|
|
||||||
const hasDataListener = socket.listenerCount('data') > 0;
|
|
||||||
|
|
||||||
if (hasDataListener && !hadError) {
|
request.on('socket', socket => {
|
||||||
const err = new Error('Premature close');
|
const onSocketClose = () => {
|
||||||
err.code = 'ERR_STREAM_PREMATURE_CLOSE';
|
if (isChunkedTransfer && !properLastChunkReceived) {
|
||||||
errorCallback(err);
|
const error = new Error('Premature close');
|
||||||
}
|
error.code = 'ERR_STREAM_PREMATURE_CLOSE';
|
||||||
});
|
errorCallback(error);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onData = buf => {
|
||||||
|
properLastChunkReceived = Buffer.compare(buf.slice(-5), LAST_CHUNK) === 0;
|
||||||
|
|
||||||
|
// Sometimes final 0-length chunk and end of message code are in separate packets
|
||||||
|
if (!properLastChunkReceived && previousChunk) {
|
||||||
|
properLastChunkReceived = (
|
||||||
|
Buffer.compare(previousChunk.slice(-3), LAST_CHUNK.slice(0, 3)) === 0 &&
|
||||||
|
Buffer.compare(buf.slice(-2), LAST_CHUNK.slice(3)) === 0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
previousChunk = buf;
|
||||||
|
};
|
||||||
|
|
||||||
|
socket.prependListener('close', onSocketClose);
|
||||||
|
socket.on('data', onData);
|
||||||
|
|
||||||
|
request.on('close', () => {
|
||||||
|
socket.removeListener('close', onSocketClose);
|
||||||
|
socket.removeListener('data', onData);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue