Skip to content

Commit 94d6f69

Browse files
committed
http2: compat head request should not start finished
http2 streams for HEAD requests are never writable, thus writableState is not interesting for checking whether a response is ended or aborted. Refs: #24283 PR-URL: #24339
1 parent b2e4cb7 commit 94d6f69

File tree

3 files changed

+45
-4
lines changed

3 files changed

+45
-4
lines changed

lib/internal/http2/compat.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -436,9 +436,10 @@ class Http2ServerResponse extends Stream {
436436

437437
get finished() {
438438
const stream = this[kStream];
439+
const state = this[kState];
439440
return stream.destroyed ||
440-
stream._writableState.ended ||
441-
this[kState].closed;
441+
state.closed ||
442+
(stream.headRequest ? state.ending : stream._writableState.ended);
442443
}
443444

444445
get socket() {
@@ -630,7 +631,7 @@ class Http2ServerResponse extends Stream {
630631
if (chunk !== null && chunk !== undefined)
631632
this.write(chunk, encoding);
632633

633-
const isFinished = this.finished;
634+
const isFinished = stream._writableState.ended;
634635
state.headRequest = stream.headRequest;
635636
state.ending = true;
636637

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
if (!common.hasCrypto)
5+
common.skip('missing crypto');
6+
const { strictEqual } = require('assert');
7+
const h2 = require('http2');
8+
9+
// Http2ServerResponse.finished cannot be true before res.end() is
10+
// called or the request is aborted.
11+
const server = h2
12+
.createServer()
13+
.listen(0, common.mustCall(function() {
14+
const port = server.address().port;
15+
server.once('request', common.mustCall((req, res) => {
16+
strictEqual(res.finished, false);
17+
res.writeHead(400);
18+
strictEqual(res.finished, false);
19+
strictEqual(res.headersSent, true);
20+
res.end();
21+
strictEqual(res.finished, true);
22+
}));
23+
24+
const url = `http://localhost:${port}`;
25+
const client = h2.connect(url, common.mustCall(function() {
26+
const headers = {
27+
':path': '/',
28+
':method': 'HEAD',
29+
':scheme': 'http',
30+
':authority': `localhost:${port}`
31+
};
32+
const request = client.request(headers);
33+
request.on('end', common.mustCall(function() {
34+
client.close();
35+
server.close();
36+
}));
37+
request.end();
38+
request.resume();
39+
}));
40+
}));

test/parallel/test-http2-compat-serverresponse-end.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ const {
121121
// Http2ServerResponse.end is necessary on HEAD requests in compat
122122
// for http1 compatibility
123123
const server = createServer(mustCall((request, response) => {
124-
strictEqual(response.finished, true);
124+
strictEqual(response.finished, false);
125125
response.writeHead(HTTP_STATUS_OK, { foo: 'bar' });
126126
response.end('data', mustCall());
127127
}));

0 commit comments

Comments
 (0)