Skip to content

Commit

Permalink
http: do not emit end after aborted
Browse files Browse the repository at this point in the history
IncomingMessage will no longer emit end after aborted.

PR-URL: #27984
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
  • Loading branch information
ronag authored and Trott committed Oct 14, 2019
1 parent 4ca61f4 commit 5f80df8
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 11 deletions.
20 changes: 19 additions & 1 deletion doc/api/http.md
Original file line number Diff line number Diff line change
Expand Up @@ -2252,6 +2252,25 @@ In the case of a connection error, the following events will be emitted:
* `'error'`
* `'close'`

In the case of a premature connection close before the response is received,
the following events will be emitted in the following order:

* `'socket'`
* `'error'` with an error with message `'Error: socket hang up'` and code
`'ECONNRESET'`
* `'close'`

In the case of a premature connection close after the response is received,
the following events will be emitted in the following order:

* `'socket'`
* `'response'`
* `'data'` any number of times, on the `res` object
* (connection closed here)
* `'aborted'` on the `res` object
* `'close'`
* `'close'` on the `res` object

If `req.abort()` is called before the connection succeeds, the following events
will be emitted in the following order:

Expand All @@ -2272,7 +2291,6 @@ will be emitted in the following order:
* `'abort'`
* `'aborted'` on the `res` object
* `'close'`
* `'end'` on the `res` object
* `'close'` on the `res` object

Setting the `timeout` option or using the `setTimeout()` function will
Expand Down
2 changes: 1 addition & 1 deletion lib/_http_client.js
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ function socketCloseListener() {
res.emit('aborted');
}
req.emit('close');
if (res.readable) {
if (!res.aborted && res.readable) {
res.on('end', function() {
this.emit('close');
});
Expand Down
2 changes: 1 addition & 1 deletion test/parallel/test-http-abort-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ server.listen(0, common.mustCall(() => {
serverRes.destroy();

res.resume();
res.on('end', common.mustCall());
res.on('end', common.mustNotCall());
res.on('aborted', common.mustCall());
res.on('close', common.mustCall());
res.socket.on('close', common.mustCall());
Expand Down
18 changes: 12 additions & 6 deletions test/parallel/test-http-client-spurious-aborted.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,18 @@ function download() {
if (res.complete) res.readable = true;
callback();
};
res.on('end', common.mustCall(() => {
reqCountdown.dec();
}));
res.on('aborted', () => {
aborted = true;
});
if (!abortRequest) {
res.on('end', common.mustCall(() => {
reqCountdown.dec();
}));
} else {
res.on('aborted', common.mustCall(() => {
aborted = true;
reqCountdown.dec();
writable.end();
}));
}

res.on('error', common.mustNotCall());
writable.on('finish', () => {
assert.strictEqual(aborted, abortRequest);
Expand Down
9 changes: 8 additions & 1 deletion test/parallel/test-http-header-overflow.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
// Flags: --expose-internals

'use strict';
const { expectsError, mustCall } = require('../common');
const assert = require('assert');
const { createServer, maxHeaderSize } = require('http');
const { createConnection } = require('net');

const { getOptionValue } = require('internal/options');

const CRLF = '\r\n';
const DUMMY_HEADER_NAME = 'Cookie: ';
const DUMMY_HEADER_VALUE = 'a'.repeat(
Expand All @@ -17,11 +21,14 @@ const PAYLOAD = PAYLOAD_GET + CRLF +
const server = createServer();

server.on('connection', mustCall((socket) => {
// Legacy parser gives sligthly different response.
// This discripancy is not fixed on purpose.
const legacy = getOptionValue('--http-parser') === 'legacy';
socket.on('error', expectsError({
type: Error,
message: 'Parse Error: Header overflow',
code: 'HPE_HEADER_OVERFLOW',
bytesParsed: maxHeaderSize + PAYLOAD_GET.length,
bytesParsed: maxHeaderSize + PAYLOAD_GET.length - (legacy ? -1 : 0),
rawPacket: Buffer.from(PAYLOAD)
}));
}));
Expand Down
1 change: 1 addition & 0 deletions test/parallel/test-http-response-no-headers.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ function test(httpVersion, callback) {
body += data;
});

res.on('aborted', common.mustNotCall());
res.on('end', common.mustCall(function() {
assert.strictEqual(body, expected[httpVersion]);
server.close();
Expand Down
3 changes: 2 additions & 1 deletion test/parallel/test-http-response-status-message.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
// USE OR OTHER DEALINGS IN THE SOFTWARE.

'use strict';
require('../common');
const common = require('../common');
const assert = require('assert');
const http = require('http');
const net = require('net');
Expand Down Expand Up @@ -71,6 +71,7 @@ function runTest(testCaseIndex) {
console.log(`client: actual status message: ${response.statusMessage}`);
assert.strictEqual(testCase.statusMessage, response.statusMessage);

response.on('aborted', common.mustNotCall());
response.on('end', function() {
countdown.dec();
if (testCaseIndex + 1 < testCases.length) {
Expand Down

0 comments on commit 5f80df8

Please sign in to comment.