Skip to content

Commit dfc962f

Browse files
dnlupdanielleadams
authored andcommitted
http: add test case for req-res close ordering
Since 55e83cb has changed the ordering of the close event, add a test case. IncomingMessage will emit close before the response is sent in case the server is consuming data from it. Refs: #33035 (comment) PR-URL: #36645 Reviewed-By: Rich Trott <[email protected]> Reviewed-By: Robert Nagy <[email protected]> Reviewed-By: Matteo Collina <[email protected]>
1 parent cc28d2f commit dfc962f

File tree

1 file changed

+119
-25
lines changed

1 file changed

+119
-25
lines changed

test/parallel/test-http-req-res-close.js

+119-25
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,128 @@ const common = require('../common');
44
const http = require('http');
55
const assert = require('assert');
66

7-
const server = http.Server(common.mustCall((req, res) => {
8-
let resClosed = false;
9-
10-
res.end();
11-
let resFinished = false;
12-
res.on('finish', common.mustCall(() => {
13-
resFinished = true;
14-
assert.strictEqual(resClosed, false);
15-
assert.strictEqual(res.destroyed, false);
16-
assert.strictEqual(resClosed, false);
7+
// When the response is ended immediately, `req` should emit `close`
8+
// after `res`
9+
{
10+
const server = http.Server(common.mustCall((req, res) => {
11+
let resClosed = false;
12+
let reqClosed = false;
13+
14+
res.end();
15+
let resFinished = false;
16+
res.on('finish', common.mustCall(() => {
17+
resFinished = true;
18+
assert.strictEqual(resClosed, false);
19+
assert.strictEqual(res.destroyed, false);
20+
assert.strictEqual(resClosed, false);
21+
}));
22+
assert.strictEqual(req.destroyed, false);
23+
res.on('close', common.mustCall(() => {
24+
resClosed = true;
25+
assert.strictEqual(resFinished, true);
26+
assert.strictEqual(reqClosed, false);
27+
assert.strictEqual(res.destroyed, true);
28+
}));
29+
assert.strictEqual(req.destroyed, false);
30+
req.on('end', common.mustCall(() => {
31+
assert.strictEqual(req.destroyed, false);
32+
}));
33+
req.on('close', common.mustCall(() => {
34+
reqClosed = true;
35+
assert.strictEqual(resClosed, true);
36+
assert.strictEqual(req.destroyed, true);
37+
assert.strictEqual(req._readableState.ended, true);
38+
}));
39+
res.socket.on('close', () => server.close());
1740
}));
18-
assert.strictEqual(req.destroyed, false);
19-
res.on('close', common.mustCall(() => {
20-
resClosed = true;
21-
assert.strictEqual(resFinished, true);
22-
assert.strictEqual(res.destroyed, true);
41+
42+
server.listen(0, common.mustCall(() => {
43+
http.get({ port: server.address().port }, common.mustCall());
2344
}));
24-
assert.strictEqual(req.destroyed, false);
25-
req.on('end', common.mustCall(() => {
45+
}
46+
47+
// When there's no `data` handler attached to `req`,
48+
// `req` should emit `close` after `res`.
49+
{
50+
const server = http.Server(common.mustCall((req, res) => {
51+
let resClosed = false;
52+
let reqClosed = false;
53+
54+
// This time, don't end the response immediately
55+
setTimeout(() => res.end(), 100);
56+
let resFinished = false;
57+
res.on('finish', common.mustCall(() => {
58+
resFinished = true;
59+
assert.strictEqual(resClosed, false);
60+
assert.strictEqual(res.destroyed, false);
61+
assert.strictEqual(resClosed, false);
62+
}));
63+
assert.strictEqual(req.destroyed, false);
64+
res.on('close', common.mustCall(() => {
65+
resClosed = true;
66+
assert.strictEqual(resFinished, true);
67+
assert.strictEqual(reqClosed, false);
68+
assert.strictEqual(res.destroyed, true);
69+
}));
2670
assert.strictEqual(req.destroyed, false);
71+
req.on('end', common.mustCall(() => {
72+
assert.strictEqual(req.destroyed, false);
73+
}));
74+
req.on('close', common.mustCall(() => {
75+
reqClosed = true;
76+
assert.strictEqual(resClosed, true);
77+
assert.strictEqual(req.destroyed, true);
78+
assert.strictEqual(req._readableState.ended, true);
79+
}));
80+
res.socket.on('close', () => server.close());
2781
}));
28-
req.on('close', common.mustCall(() => {
29-
assert.strictEqual(req.destroyed, true);
30-
assert.strictEqual(req._readableState.ended, true);
82+
83+
server.listen(0, common.mustCall(() => {
84+
http.get({ port: server.address().port }, common.mustCall());
3185
}));
32-
res.socket.on('close', () => server.close());
33-
}));
86+
}
87+
88+
// When a `data` handler is `attached` to `req`
89+
// (i.e. the server is consuming data from it), `req` should emit `close`
90+
// before `res`.
91+
// https://github.com/nodejs/node/pull/33035 introduced this change in behavior.
92+
// See https://github.com/nodejs/node/pull/33035#issuecomment-751482764
93+
{
94+
const server = http.Server(common.mustCall((req, res) => {
95+
let resClosed = false;
96+
let reqClosed = false;
3497

35-
server.listen(0, common.mustCall(() => {
36-
http.get({ port: server.address().port }, common.mustCall());
37-
}));
98+
// Don't end the response immediately
99+
setTimeout(() => res.end(), 100);
100+
let resFinished = false;
101+
req.on('data', () => {});
102+
res.on('finish', common.mustCall(() => {
103+
resFinished = true;
104+
assert.strictEqual(resClosed, false);
105+
assert.strictEqual(res.destroyed, false);
106+
assert.strictEqual(resClosed, false);
107+
}));
108+
assert.strictEqual(req.destroyed, false);
109+
res.on('close', common.mustCall(() => {
110+
resClosed = true;
111+
assert.strictEqual(resFinished, true);
112+
assert.strictEqual(reqClosed, true);
113+
assert.strictEqual(res.destroyed, true);
114+
}));
115+
assert.strictEqual(req.destroyed, false);
116+
req.on('end', common.mustCall(() => {
117+
assert.strictEqual(req.destroyed, false);
118+
}));
119+
req.on('close', common.mustCall(() => {
120+
reqClosed = true;
121+
assert.strictEqual(resClosed, false);
122+
assert.strictEqual(req.destroyed, true);
123+
assert.strictEqual(req._readableState.ended, true);
124+
}));
125+
res.socket.on('close', () => server.close());
126+
}));
127+
128+
server.listen(0, common.mustCall(() => {
129+
http.get({ port: server.address().port }, common.mustCall());
130+
}));
131+
}

0 commit comments

Comments
 (0)