Skip to content

Commit 8c7c040

Browse files
committed
http2/compat: make req.trailers have a null prototype
In HTTP/2 compatibility mode, make request trailers have a null prototype, matching the behavior of regular headers and trailers.
1 parent 0a071d8 commit 8c7c040

10 files changed

Lines changed: 59 additions & 61 deletions

lib/internal/http2/compat.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ class Http2ServerRequest extends Readable {
319319
// initialization using Object.create(null) in HTTP/2 is intentional.
320320
this[kHeaders] = headers;
321321
this[kRawHeaders] = rawHeaders;
322-
this[kTrailers] = {};
322+
this[kTrailers] = { __proto__: null };
323323
this[kRawTrailers] = [];
324324
this[kStream] = stream;
325325
this[kAborted] = false;

test/parallel/test-http-blank-header.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,9 @@ const server = http.createServer(common.mustCall((req, res) => {
2929
assert.strictEqual(req.method, 'GET');
3030
assert.strictEqual(req.url, '/blah');
3131
assert.deepStrictEqual(req.headers, { __proto__: null,
32-
host: 'example.org:443',
33-
origin: 'http://example.org',
34-
cookie: ''
35-
});
32+
host: 'example.org:443',
33+
origin: 'http://example.org',
34+
cookie: '' });
3635
}));
3736

3837

test/parallel/test-http-client-headers-array.js

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,11 @@ const http = require('http');
77

88
function execute(options) {
99
http.createServer(common.mustCall(function(req, res) {
10-
const expectHeaders = { __proto__: null,
11-
'x-foo': 'boom',
12-
'cookie': 'a=1; b=2; c=3',
13-
'connection': 'keep-alive',
14-
'host': 'example.com',
15-
};
10+
const expectHeaders = { '__proto__': null,
11+
'x-foo': 'boom',
12+
'cookie': 'a=1; b=2; c=3',
13+
'connection': 'keep-alive',
14+
'host': 'example.com' };
1615

1716
// no Host header when you set headers an array
1817
if (!Array.isArray(options.headers)) {

test/parallel/test-http-content-length.js

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,17 @@ const assert = require('assert');
44
const http = require('http');
55
const Countdown = require('../common/countdown');
66

7-
const expectedHeadersMultipleWrites = { __proto__: null,
8-
'connection': 'keep-alive',
9-
'transfer-encoding': 'chunked',
10-
};
7+
const expectedHeadersMultipleWrites = { '__proto__': null,
8+
'connection': 'keep-alive',
9+
'transfer-encoding': 'chunked' };
1110

12-
const expectedHeadersEndWithData = { __proto__: null,
13-
'connection': 'keep-alive',
14-
'content-length': String('hello world'.length),
15-
};
11+
const expectedHeadersEndWithData = { '__proto__': null,
12+
'connection': 'keep-alive',
13+
'content-length': String('hello world'.length) };
1614

17-
const expectedHeadersEndNoData = { __proto__: null,
18-
'connection': 'keep-alive',
19-
'content-length': '0',
20-
};
15+
const expectedHeadersEndNoData = { '__proto__': null,
16+
'connection': 'keep-alive',
17+
'content-length': '0' };
2118

2219

2320
const countdown = new Countdown(3, () => server.close());
@@ -62,7 +59,9 @@ server.listen(0, common.mustCall(function() {
6259
req.write('hello ');
6360
req.end('world');
6461
req.on('response', common.mustCall((res) => {
65-
assert.deepStrictEqual(res.headers, { __proto__: null, ...expectedHeadersMultipleWrites, 'keep-alive': 'timeout=1' });
62+
assert.deepStrictEqual(res.headers, {
63+
'__proto__': null, ...expectedHeadersMultipleWrites, 'keep-alive': 'timeout=1',
64+
});
6665
res.resume();
6766
}));
6867

@@ -74,7 +73,9 @@ server.listen(0, common.mustCall(function() {
7473
req.removeHeader('Date');
7574
req.end('hello world');
7675
req.on('response', common.mustCall((res) => {
77-
assert.deepStrictEqual(res.headers, { __proto__: null, ...expectedHeadersEndWithData, 'keep-alive': 'timeout=1' });
76+
assert.deepStrictEqual(res.headers, {
77+
'__proto__': null, ...expectedHeadersEndWithData, 'keep-alive': 'timeout=1',
78+
});
7879
res.resume();
7980
}));
8081

@@ -86,7 +87,7 @@ server.listen(0, common.mustCall(function() {
8687
req.removeHeader('Date');
8788
req.end();
8889
req.on('response', common.mustCall((res) => {
89-
assert.deepStrictEqual(res.headers, { __proto__: null, ...expectedHeadersEndNoData, 'keep-alive': 'timeout=1' });
90+
assert.deepStrictEqual(res.headers, { '__proto__': null, ...expectedHeadersEndNoData, 'keep-alive': 'timeout=1' });
9091
res.resume();
9192
}));
9293

test/parallel/test-http-multiple-headers.js

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,12 @@ const server = createServer(
1919
'Host', host,
2020
'Transfer-Encoding', 'chunked',
2121
]);
22-
assert.deepStrictEqual(req.headers, { __proto__: null,
23-
'connection': 'close',
24-
'x-req-a': 'eee, fff, ggg, hhh',
25-
'x-req-b': 'iii; jjj; kkk; lll',
26-
host,
27-
'transfer-encoding': 'chunked'
28-
});
22+
assert.deepStrictEqual(req.headers, { '__proto__': null,
23+
'connection': 'close',
24+
'x-req-a': 'eee, fff, ggg, hhh',
25+
'x-req-b': 'iii; jjj; kkk; lll',
26+
host,
27+
'transfer-encoding': 'chunked' });
2928
assert.deepStrictEqual(req.headersDistinct, Object.assign({ __proto__: null }, {
3029
'connection': ['close'],
3130
'x-req-a': ['eee', 'fff', 'ggg', 'hhh'],
@@ -41,7 +40,7 @@ const server = createServer(
4140
'X-req-Y', 'zzz; www',
4241
]);
4342
assert.deepStrictEqual(
44-
req.trailers, { __proto__: null, 'x-req-x': 'xxx, yyy', 'x-req-y': 'zzz; www' }
43+
req.trailers, { '__proto__': null, 'x-req-x': 'xxx, yyy', 'x-req-y': 'zzz; www' }
4544
);
4645
assert.deepStrictEqual(
4746
req.trailersDistinct,
@@ -124,14 +123,13 @@ server.listen(0, common.mustCall(() => {
124123
'x-res-d', 'JJJ; KKK; LLL',
125124
'Transfer-Encoding', 'chunked',
126125
]);
127-
assert.deepStrictEqual(res.headers, { __proto__: null,
128-
'x-res-a': 'AAA, BBB, CCC',
129-
'x-res-b': 'DDD; EEE; FFF; GGG',
130-
'connection': 'close',
131-
'x-res-c': 'HHH, III',
132-
'x-res-d': 'JJJ; KKK; LLL',
133-
'transfer-encoding': 'chunked'
134-
});
126+
assert.deepStrictEqual(res.headers, { '__proto__': null,
127+
'x-res-a': 'AAA, BBB, CCC',
128+
'x-res-b': 'DDD; EEE; FFF; GGG',
129+
'connection': 'close',
130+
'x-res-c': 'HHH, III',
131+
'x-res-d': 'JJJ; KKK; LLL',
132+
'transfer-encoding': 'chunked' });
135133
assert.deepStrictEqual(res.headersDistinct, Object.assign({ __proto__: null }, {
136134
'x-res-a': [ 'AAA', 'BBB', 'CCC' ],
137135
'x-res-b': [ 'DDD; EEE; FFF; GGG' ],
@@ -149,7 +147,7 @@ server.listen(0, common.mustCall(() => {
149147
]);
150148
assert.deepStrictEqual(
151149
res.trailers,
152-
{ __proto__: null, 'x-res-x': 'XXX, YYY', 'x-res-y': 'ZZZ; WWW' }
150+
{ '__proto__': null, 'x-res-x': 'XXX, YYY', 'x-res-y': 'ZZZ; WWW' }
153151
);
154152
assert.deepStrictEqual(
155153
res.trailersDistinct,

test/parallel/test-http-raw-headers.js

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,11 @@ http.createServer(common.mustCall(function(req, res) {
3636
'Connection',
3737
'keep-alive',
3838
];
39-
const expectHeaders = { __proto__: null,
40-
'host': `localhost:${this.address().port}`,
41-
'transfer-encoding': 'CHUNKED',
42-
'x-bar': 'yoyoyo',
43-
'connection': 'keep-alive'
44-
};
39+
const expectHeaders = { '__proto__': null,
40+
'host': `localhost:${this.address().port}`,
41+
'transfer-encoding': 'CHUNKED',
42+
'x-bar': 'yoyoyo',
43+
'connection': 'keep-alive' };
4544
const expectRawTrailers = [
4645
'x-bAr',
4746
'yOyOyOy',
@@ -52,7 +51,7 @@ http.createServer(common.mustCall(function(req, res) {
5251
'X-baR',
5352
'OyOyOyO',
5453
];
55-
const expectTrailers = { __proto__: null, 'x-bar': 'yOyOyOy, OyOyOyO, yOyOyOy, OyOyOyO' };
54+
const expectTrailers = { '__proto__': null, 'x-bar': 'yOyOyOy, OyOyOyO, yOyOyOy, OyOyOyO' };
5655

5756
this.close();
5857

@@ -98,13 +97,12 @@ http.createServer(common.mustCall(function(req, res) {
9897
'Transfer-Encoding',
9998
'chunked',
10099
];
101-
const expectHeaders = { __proto__: null,
102-
'keep-alive': 'timeout=1',
103-
'trailer': 'x-foo',
104-
'date': null,
105-
'connection': 'keep-alive',
106-
'transfer-encoding': 'chunked'
107-
};
100+
const expectHeaders = { '__proto__': null,
101+
'keep-alive': 'timeout=1',
102+
'trailer': 'x-foo',
103+
'date': null,
104+
'connection': 'keep-alive',
105+
'transfer-encoding': 'chunked' };
108106
res.rawHeaders[5] = null;
109107
res.headers.date = null;
110108
assert.deepStrictEqual(res.rawHeaders, expectRawHeaders);
@@ -120,7 +118,7 @@ http.createServer(common.mustCall(function(req, res) {
120118
'X-foO',
121119
'OxOxOxO',
122120
];
123-
const expectTrailers = { __proto__: null, 'x-foo': 'xOxOxOx, OxOxOxO, xOxOxOx, OxOxOxO' };
121+
const expectTrailers = { '__proto__': null, 'x-foo': 'xOxOxOx, OxOxOxO, xOxOxOx, OxOxOxO' };
124122

125123
assert.deepStrictEqual(res.rawTrailers, expectRawTrailers);
126124
assert.deepStrictEqual(res.trailers, expectTrailers);

test/parallel/test-http-server-headers-null-proto.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,9 @@ const net = require('net');
6969
const server = http.createServer(common.mustCall((req, res) => {
7070
assert.strictEqual(Object.getPrototypeOf(req.headers), null);
7171
// The __proto__ header should be stored as a regular property
72-
assert.strictEqual(req.headers['__proto__'], 'test');
72+
assert.strictEqual(
73+
Object.getOwnPropertyDescriptor(req.headers, '__proto__').value, 'test',
74+
);
7375
res.end();
7476
}));
7577

test/parallel/test-http-upgrade-agent.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ server.listen(0, '127.0.0.1', common.mustCall(function() {
7676
assert.strictEqual(recvData.toString(), 'nurtzo');
7777
}));
7878

79-
const expectedHeaders = { __proto__: null, 'hello': 'world',
79+
const expectedHeaders = { '__proto__': null, 'hello': 'world',
8080
'connection': 'upgrade',
8181
'upgrade': 'websocket' };
8282
assert.deepStrictEqual(expectedHeaders, res.headers);

test/parallel/test-http-upgrade-server-with-body-and-extras.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ server.on('upgrade', common.mustCall(function(req, socket, upgradeHead) {
2424
req.on('end', common.mustCall(() => {
2525
assert.strictEqual(reqBodyLength, EXPECTED_BODY_LENGTH);
2626

27-
assert.deepStrictEqual(req.trailers, { __proto__: null, 'extra-data': 'abc' });
27+
assert.deepStrictEqual(req.trailers, { '__proto__': null, 'extra-data': 'abc' });
2828

2929
// Defer upgrade stream read slightly to make sure it doesn't start
3030
// streaming along with the request body, until we actually read it:

test/parallel/test-http2-compat-serverrequest-trailers.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ server.listen(0, common.mustCall(function() {
2222
request.on('data', common.mustCallAtLeast((chunk) => data += chunk));
2323
request.on('end', common.mustCall(() => {
2424
const trailers = request.trailers;
25+
assert.strictEqual(Object.getPrototypeOf(trailers), null);
2526
for (const [name, value] of Object.entries(expectedTrailers)) {
2627
assert.strictEqual(trailers[name], value);
2728
}

0 commit comments

Comments
 (0)