Skip to content

Commit 33a6bf3

Browse files
mcollinatargos
authored andcommitted
http: implement capture rejections for 'request' event
PR-URL: #27867 Reviewed-By: Benjamin Gruenbaum <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Jeremiah Senkpiel <[email protected]> Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Michaël Zasso <[email protected]>
1 parent 89bc571 commit 33a6bf3

File tree

2 files changed

+129
-0
lines changed

2 files changed

+129
-0
lines changed

lib/_http_server.js

+21
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ const {
2727
} = primordials;
2828

2929
const net = require('net');
30+
const EE = require('events');
3031
const assert = require('internal/assert');
3132
const {
3233
parsers,
@@ -357,6 +358,26 @@ Server.prototype.setTimeout = function setTimeout(msecs, callback) {
357358
return this;
358359
};
359360

361+
Server.prototype[EE.captureRejectionSymbol] = function(
362+
err, event, req, res) {
363+
364+
switch (event) {
365+
case 'request':
366+
if (!res.headersSent && !res.writableEnded) {
367+
// Don't leak headers.
368+
for (const name of res.getHeaderNames()) {
369+
res.removeHeader(name);
370+
}
371+
res.statusCode = 500;
372+
res.end(STATUS_CODES[500]);
373+
} else {
374+
res.destroy();
375+
}
376+
break;
377+
default:
378+
this.emit('error', err);
379+
}
380+
};
360381

361382
function connectionListener(socket) {
362383
defaultTriggerAsyncIdScope(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const events = require('events');
5+
const { createServer, request } = require('http');
6+
const assert = require('assert');
7+
8+
events.captureRejections = true;
9+
10+
{
11+
const server = createServer(common.mustCall(async (req, res) => {
12+
// We will test that this header is cleaned up before forwarding.
13+
res.setHeader('content-type', 'application/json');
14+
throw new Error('kaboom');
15+
}));
16+
17+
server.listen(0, common.mustCall(() => {
18+
const req = request({
19+
method: 'GET',
20+
host: server.address().host,
21+
port: server.address().port
22+
});
23+
24+
req.end();
25+
26+
req.on('response', common.mustCall((res) => {
27+
assert.strictEqual(res.statusCode, 500);
28+
assert.strictEqual(res.headers.hasOwnProperty('content-type'), false);
29+
let data = '';
30+
res.setEncoding('utf8');
31+
res.on('data', common.mustCall((chunk) => {
32+
data += chunk;
33+
}));
34+
res.on('end', common.mustCall(() => {
35+
assert.strictEqual(data, 'Internal Server Error');
36+
server.close();
37+
}));
38+
}));
39+
}));
40+
}
41+
42+
{
43+
let resolve;
44+
const latch = new Promise((_resolve) => {
45+
resolve = _resolve;
46+
});
47+
const server = createServer(common.mustCall(async (req, res) => {
48+
server.close();
49+
50+
// We will test that this header is cleaned up before forwarding.
51+
res.setHeader('content-type', 'application/json');
52+
res.write('{');
53+
req.resume();
54+
55+
// Wait so the data is on the wire
56+
await latch;
57+
58+
throw new Error('kaboom');
59+
}));
60+
61+
server.listen(0, common.mustCall(() => {
62+
const req = request({
63+
method: 'GET',
64+
host: server.address().host,
65+
port: server.address().port
66+
});
67+
68+
req.end();
69+
70+
req.on('response', common.mustCall((res) => {
71+
assert.strictEqual(res.statusCode, 200);
72+
assert.strictEqual(res.headers['content-type'], 'application/json');
73+
resolve();
74+
75+
let data = '';
76+
res.setEncoding('utf8');
77+
res.on('data', common.mustCall((chunk) => {
78+
data += chunk;
79+
}));
80+
81+
req.on('close', common.mustCall(() => {
82+
assert.strictEqual(data, '{');
83+
}));
84+
}));
85+
}));
86+
}
87+
88+
{
89+
const server = createServer(common.mustCall(async (req, res) => {
90+
// We will test that this header is cleaned up before forwarding.
91+
res.writeHead(200);
92+
throw new Error('kaboom');
93+
}));
94+
95+
server.listen(0, common.mustCall(() => {
96+
const req = request({
97+
method: 'GET',
98+
host: server.address().host,
99+
port: server.address().port
100+
});
101+
102+
req.end();
103+
req.on('error', common.mustCall((err) => {
104+
assert.strictEqual(err.code, 'ECONNRESET');
105+
server.close();
106+
}));
107+
}));
108+
}

0 commit comments

Comments
 (0)