Skip to content

Commit 269a1ef

Browse files
y1d7ngguangwong
authored andcommitted
http2: compat support for array headers
PR-URL: nodejs/node#42901 Reviewed-By: Robert Nagy <[email protected]> Reviewed-By: Paolo Insogna <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Ricky Zhou <[email protected]> Reviewed-By: Rafael Gonzaga <[email protected]>
1 parent 49cf76c commit 269a1ef

File tree

3 files changed

+99
-37
lines changed

3 files changed

+99
-37
lines changed

doc/api/http2.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -3922,7 +3922,7 @@ changes:
39223922

39233923
* `statusCode` {number}
39243924
* `statusMessage` {string}
3925-
* `headers` {Object}
3925+
* `headers` {Object|Array}
39263926
* Returns: {http2.Http2ServerResponse}
39273927

39283928
Sends a response header to the request. The status code is a 3-digit HTTP

lib/internal/http2/compat.js

+13-3
Original file line numberDiff line numberDiff line change
@@ -682,9 +682,19 @@ class Http2ServerResponse extends Stream {
682682

683683
let i;
684684
if (ArrayIsArray(headers)) {
685-
for (i = 0; i < headers.length; i++) {
686-
const header = headers[i];
687-
this[kSetHeader](header[0], header[1]);
685+
if (headers.length && ArrayIsArray(headers[0])) {
686+
for (i = 0; i < headers.length; i++) {
687+
const header = headers[i];
688+
this[kSetHeader](header[0], header[1]);
689+
}
690+
} else {
691+
if (headers.length % 2 !== 0) {
692+
throw new ERR_INVALID_ARG_VALUE('headers', headers);
693+
}
694+
695+
for (i = 0; i < headers.length; i += 2) {
696+
this[kSetHeader](headers[i], headers[i + 1]);
697+
}
688698
}
689699
} else if (typeof headers === 'object') {
690700
const keys = ObjectKeys(headers);

test/parallel/test-http2-compat-serverresponse-writehead-array.js

+85-33
Original file line numberDiff line numberDiff line change
@@ -4,40 +4,92 @@ const common = require('../common');
44
if (!common.hasCrypto)
55
common.skip('missing crypto');
66
const assert = require('assert');
7-
const h2 = require('http2');
8-
9-
// Http2ServerResponse.writeHead should support nested arrays
10-
11-
const server = h2.createServer();
12-
server.listen(0, common.mustCall(() => {
13-
const port = server.address().port;
14-
server.once('request', common.mustCall((request, response) => {
15-
const returnVal = response.writeHead(200, [
16-
['foo', 'bar'],
17-
['ABC', 123],
18-
]);
19-
assert.strictEqual(returnVal, response);
20-
response.end(common.mustCall(() => { server.close(); }));
7+
const http2 = require('http2');
8+
9+
// Http2ServerResponse.writeHead should support arrays and nested arrays
10+
11+
{
12+
const server = http2.createServer();
13+
server.listen(0, common.mustCall(() => {
14+
const port = server.address().port;
15+
16+
server.once('request', common.mustCall((request, response) => {
17+
const returnVal = response.writeHead(200, [
18+
['foo', 'bar'],
19+
['ABC', 123],
20+
]);
21+
assert.strictEqual(returnVal, response);
22+
response.end(common.mustCall(() => { server.close(); }));
23+
}));
24+
25+
const client = http2.connect(`http://localhost:${port}`, common.mustCall(() => {
26+
const request = client.request();
27+
28+
request.on('response', common.mustCall((headers) => {
29+
assert.strictEqual(headers.foo, 'bar');
30+
assert.strictEqual(headers.abc, '123');
31+
assert.strictEqual(headers[':status'], 200);
32+
}, 1));
33+
request.on('end', common.mustCall(() => {
34+
client.close();
35+
}));
36+
request.end();
37+
request.resume();
38+
}));
2139
}));
40+
}
41+
42+
{
43+
const server = http2.createServer();
44+
server.listen(0, common.mustCall(() => {
45+
const port = server.address().port;
46+
47+
server.once('request', common.mustCall((request, response) => {
48+
const returnVal = response.writeHead(200, ['foo', 'bar', 'ABC', 123]);
49+
assert.strictEqual(returnVal, response);
50+
response.end(common.mustCall(() => { server.close(); }));
51+
}));
52+
53+
const client = http2.connect(`http://localhost:${port}`, common.mustCall(() => {
54+
const request = client.request();
55+
56+
request.on('response', common.mustCall((headers) => {
57+
assert.strictEqual(headers.foo, 'bar');
58+
assert.strictEqual(headers.abc, '123');
59+
assert.strictEqual(headers[':status'], 200);
60+
}, 1));
61+
request.on('end', common.mustCall(() => {
62+
client.close();
63+
}));
64+
request.end();
65+
request.resume();
66+
}));
67+
}));
68+
}
69+
70+
{
71+
const server = http2.createServer();
72+
server.listen(0, common.mustCall(() => {
73+
const port = server.address().port;
74+
75+
server.once('request', common.mustCall((request, response) => {
76+
try {
77+
response.writeHead(200, ['foo', 'bar', 'ABC', 123, 'extra']);
78+
} catch (err) {
79+
assert.strictEqual(err.code, 'ERR_INVALID_ARG_VALUE');
80+
}
81+
82+
response.end(common.mustCall(() => { server.close(); }));
83+
}));
84+
85+
const client = http2.connect(`http://localhost:${port}`, common.mustCall(() => {
86+
const request = client.request();
2287

23-
const url = `http://localhost:${port}`;
24-
const client = h2.connect(url, common.mustCall(() => {
25-
const headers = {
26-
':path': '/',
27-
':method': 'GET',
28-
':scheme': 'http',
29-
':authority': `localhost:${port}`
30-
};
31-
const request = client.request(headers);
32-
request.on('response', common.mustCall((headers) => {
33-
assert.strictEqual(headers.foo, 'bar');
34-
assert.strictEqual(headers.abc, '123');
35-
assert.strictEqual(headers[':status'], 200);
36-
}, 1));
37-
request.on('end', common.mustCall(() => {
38-
client.close();
88+
request.on('end', common.mustCall(() => {
89+
client.close();
90+
}));
91+
request.end();
92+
request.resume();
3993
}));
40-
request.end();
41-
request.resume();
4294
}));
43-
}));
95+
}

0 commit comments

Comments
 (0)