Skip to content

Commit 02b82d8

Browse files
committed
http: added closed property
1 parent c1f0cbe commit 02b82d8

10 files changed

+50
-8
lines changed

doc/api/http.md

+18
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,15 @@ changes:
553553
The `request.aborted` property will be `true` if the request has
554554
been aborted.
555555

556+
### request.closed
557+
<!-- YAML
558+
added: CHANGEME
559+
-->
560+
561+
* {boolean}
562+
563+
The `request.closed` property indicates whether the request has been closed.
564+
556565
### request.connection
557566
<!-- YAML
558567
added: v0.3.0
@@ -1130,6 +1139,15 @@ response.end();
11301139
Attempting to set a header field name or value that contains invalid characters
11311140
will result in a [`TypeError`][] being thrown.
11321141

1142+
### response.closed
1143+
<!-- YAML
1144+
added: CHANGEME
1145+
-->
1146+
1147+
* {boolean}
1148+
1149+
The `response.closed` property indicates whether the response has been closed.
1150+
11331151
### response.connection
11341152
<!-- YAML
11351153
added: v0.3.0

lib/_http_client.js

+6
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ function ClientRequest(input, options, cb) {
191191
this._ended = false;
192192
this.res = null;
193193
this.aborted = false;
194+
this.closed = false;
194195
this.timeoutCb = null;
195196
this.upgradeOrConnect = false;
196197
this.parser = null;
@@ -358,13 +359,16 @@ function socketCloseListener() {
358359
res.aborted = true;
359360
res.emit('aborted');
360361
}
362+
req.closed = true;
361363
req.emit('close');
362364
if (res.readable) {
363365
res.on('end', function() {
366+
this.closed = true;
364367
this.emit('close');
365368
});
366369
res.push(null);
367370
} else {
371+
res.closed = true;
368372
res.emit('close');
369373
}
370374
} else {
@@ -375,6 +379,7 @@ function socketCloseListener() {
375379
req.socket._hadError = true;
376380
req.emit('error', connResetException('socket hang up'));
377381
}
382+
req.closed = true;
378383
req.emit('close');
379384
}
380385

@@ -487,6 +492,7 @@ function socketOnData(d) {
487492
socket.readableFlowing = null;
488493

489494
req.emit(eventName, res, socket, bodyHead);
495+
req.closed = true;
490496
req.emit('close');
491497
} else {
492498
// Requested Upgrade or used CONNECT method, but have no handler.

lib/_http_incoming.js

+1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ function IncomingMessage(socket) {
5656
this.readable = true;
5757

5858
this.aborted = false;
59+
this.closed = false;
5960

6061
this.upgrade = null;
6162

lib/_http_outgoing.js

+1
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ function OutgoingMessage() {
9696
this._trailer = '';
9797

9898
this.finished = false;
99+
this.closed = false;
99100
this._headerSent = false;
100101
this[kIsCorked] = false;
101102

lib/_http_server.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,10 @@ function onServerResponseClose() {
178178
// Ergo, we need to deal with stale 'close' events and handle the case
179179
// where the ServerResponse object has already been deconstructed.
180180
// Fortunately, that requires only a single if check. :-)
181-
if (this._httpMessage) this._httpMessage.emit('close');
181+
if (this._httpMessage) {
182+
this._httpMessage.closed = true;
183+
this._httpMessage.emit('close');
184+
}
182185
}
183186

184187
ServerResponse.prototype.assignSocket = function assignSocket(socket) {
@@ -468,6 +471,7 @@ function abortIncoming(incoming) {
468471
while (incoming.length) {
469472
var req = incoming.shift();
470473
req.aborted = true;
474+
req.closed = true;
471475
req.emit('aborted');
472476
req.emit('close');
473477
}
@@ -609,6 +613,7 @@ function resOnFinish(req, res, socket, state, server) {
609613
req._dump();
610614

611615
res.detachSocket(socket);
616+
req.closed = true;
612617
req.emit('close');
613618
process.nextTick(emitCloseNT, res);
614619

@@ -633,6 +638,7 @@ function resOnFinish(req, res, socket, state, server) {
633638
}
634639

635640
function emitCloseNT(self) {
641+
self.closed = true;
636642
self.emit('close');
637643
}
638644

lib/internal/http2/compat.js

+8
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,10 @@ class Http2ServerRequest extends Readable {
297297
this.on('resume', onRequestResume);
298298
}
299299

300+
get closed() {
301+
return this[kState].closed;
302+
}
303+
300304
get aborted() {
301305
return this[kAborted];
302306
}
@@ -446,6 +450,10 @@ class Http2ServerResponse extends Stream {
446450
stream.on('timeout', onStreamTimeout(kResponse));
447451
}
448452

453+
get closed() {
454+
return this[kState].closed;
455+
}
456+
449457
// User land modules such as finalhandler just check truthiness of this
450458
// but if someone is actually trying to use this for more than that
451459
// then we simply can't support such use cases

test/parallel/test-http-client-close-event.js

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ server.listen(0, common.mustCall(() => {
2323

2424
req.on('close', common.mustCall(() => {
2525
assert.strictEqual(errorEmitted, true);
26+
assert.strictEqual(req.closed, true);
2627
server.close();
2728
}));
2829

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

+3-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ server.listen(0, common.mustCall(function() {
3333
path: 'example.com:443'
3434
}, common.mustNotCall());
3535

36-
req.on('close', common.mustCall());
36+
req.on('close', common.mustCall(() => {
37+
assert.strictEqual(req.closed, true);
38+
}));
3739

3840
req.on('connect', common.mustCall(function(res, socket, firstBodyChunk) {
3941
console.error('Client got CONNECT request');

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

+3-6
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,13 @@ const http = require('http');
55
const assert = require('assert');
66

77
const server = http.Server(common.mustCall((req, res) => {
8-
let resClosed = false;
9-
108
res.end();
11-
res.on('finish', common.mustCall(() => {
12-
assert.strictEqual(resClosed, false);
13-
}));
9+
res.on('finish', common.mustCall());
1410
res.on('close', common.mustCall(() => {
15-
resClosed = true;
11+
assert.strictEqual(res.closed, true);
1612
}));
1713
req.on('close', common.mustCall(() => {
14+
assert.strictEqual(req.closed, true);
1815
assert.strictEqual(req._readableState.ended, true);
1916
}));
2017
res.socket.on('close', () => server.close());

test/parallel/test-http-response-close.js

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
'use strict';
2323
const common = require('../common');
2424
const http = require('http');
25+
const assert = require('assert');
2526

2627
{
2728
const server = http.createServer(
@@ -40,6 +41,7 @@ const http = require('http');
4041
res.destroy();
4142
}));
4243
res.on('close', common.mustCall(() => {
44+
assert.strictEqual(res.closed, true);
4345
server.close();
4446
}));
4547
})

0 commit comments

Comments
 (0)