|
|
|
'use strict';
|
http client: pull last chunk on socket close
When the socket closes, the client's http incoming message object was
emitting an 'aborted' event if it had not yet been ended.
However, it's possible, when a response is being repeatedly paused and
resumed (eg, if piped to a slow FS write stream), that there will be a
final chunk remaining in the js-land buffer when the socket is torn
down.
When that happens, the socketCloseListener function detects that we have
not yet reached the end of the response message data, and treats this as
an abrupt abort, immediately (and forcibly) ending the incoming message
data stream, and discarding that final chunk of data.
The result is that, for example, npm will have problems because tarballs
are missing a few bytes off the end, every time.
Closes GH-6402
11 years ago
|
|
|
var common = require('../common');
|
|
|
|
var assert = require('assert');
|
|
|
|
|
|
|
|
if (!common.hasCrypto) {
|
|
|
|
console.log('1..0 # Skipped: missing crypto');
|
|
|
|
return;
|
|
|
|
}
|
http client: pull last chunk on socket close
When the socket closes, the client's http incoming message object was
emitting an 'aborted' event if it had not yet been ended.
However, it's possible, when a response is being repeatedly paused and
resumed (eg, if piped to a slow FS write stream), that there will be a
final chunk remaining in the js-land buffer when the socket is torn
down.
When that happens, the socketCloseListener function detects that we have
not yet reached the end of the response message data, and treats this as
an abrupt abort, immediately (and forcibly) ending the incoming message
data stream, and discarding that final chunk of data.
The result is that, for example, npm will have problems because tarballs
are missing a few bytes off the end, every time.
Closes GH-6402
11 years ago
|
|
|
var https = require('https');
|
|
|
|
|
|
|
|
var fs = require('fs');
|
http client: pull last chunk on socket close
When the socket closes, the client's http incoming message object was
emitting an 'aborted' event if it had not yet been ended.
However, it's possible, when a response is being repeatedly paused and
resumed (eg, if piped to a slow FS write stream), that there will be a
final chunk remaining in the js-land buffer when the socket is torn
down.
When that happens, the socketCloseListener function detects that we have
not yet reached the end of the response message data, and treats this as
an abrupt abort, immediately (and forcibly) ending the incoming message
data stream, and discarding that final chunk of data.
The result is that, for example, npm will have problems because tarballs
are missing a few bytes off the end, every time.
Closes GH-6402
11 years ago
|
|
|
|
|
|
|
var key = fs.readFileSync(common.fixturesDir + '/keys/agent1-key.pem');
|
|
|
|
var cert = fs.readFileSync(common.fixturesDir + '/keys/agent1-cert.pem');
|
|
|
|
|
|
|
|
var PORT = common.PORT;
|
|
|
|
|
|
|
|
// number of bytes discovered empirically to trigger the bug
|
|
|
|
var data = Buffer.allocUnsafe(1024 * 32 + 1);
|
http client: pull last chunk on socket close
When the socket closes, the client's http incoming message object was
emitting an 'aborted' event if it had not yet been ended.
However, it's possible, when a response is being repeatedly paused and
resumed (eg, if piped to a slow FS write stream), that there will be a
final chunk remaining in the js-land buffer when the socket is torn
down.
When that happens, the socketCloseListener function detects that we have
not yet reached the end of the response message data, and treats this as
an abrupt abort, immediately (and forcibly) ending the incoming message
data stream, and discarding that final chunk of data.
The result is that, for example, npm will have problems because tarballs
are missing a few bytes off the end, every time.
Closes GH-6402
11 years ago
|
|
|
|
|
|
|
httpsTest();
|
|
|
|
|
|
|
|
function httpsTest() {
|
|
|
|
var sopt = { key: key, cert: cert };
|
|
|
|
|
|
|
|
var server = https.createServer(sopt, function(req, res) {
|
|
|
|
res.setHeader('content-length', data.length);
|
|
|
|
res.end(data);
|
|
|
|
server.close();
|
|
|
|
});
|
|
|
|
|
|
|
|
server.listen(PORT, function() {
|
|
|
|
var opts = { port: PORT, rejectUnauthorized: false };
|
|
|
|
https.get(opts).on('response', function(res) {
|
|
|
|
test(res);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function test(res) {
|
|
|
|
res.on('end', function() {
|
|
|
|
assert.equal(res._readableState.length, 0);
|
|
|
|
assert.equal(bytes, data.length);
|
|
|
|
console.log('ok');
|
|
|
|
});
|
|
|
|
|
|
|
|
// Pause and then resume on each chunk, to ensure that there will be
|
|
|
|
// a lone byte hanging out at the very end.
|
|
|
|
var bytes = 0;
|
|
|
|
res.on('data', function(chunk) {
|
|
|
|
bytes += chunk.length;
|
|
|
|
this.pause();
|
|
|
|
setTimeout(this.resume.bind(this));
|
|
|
|
});
|
|
|
|
}
|