Skip to content

Commit c6e6518

Browse files
RaisinTenpanva
authored andcommitted
http2: set Http2Stream#sentHeaders for raw headers
When nodejs#57917 added support for sending raw header arrays, Http2Stream#sentHeaders was set only for header objects. This change also sets it for raw headers by lazily instantiating the property to avoid any performance impact on the fast path. Signed-off-by: Darshan Sen <raisinten@gmail.com> PR-URL: nodejs#59244 Reviewed-By: Tim Perry <pimterry@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
1 parent 0d26c93 commit c6e6518

File tree

4 files changed

+61
-2
lines changed

4 files changed

+61
-2
lines changed

lib/internal/http2/core.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ const kProceed = Symbol('proceed');
254254
const kRemoteSettings = Symbol('remote-settings');
255255
const kRequestAsyncResource = Symbol('requestAsyncResource');
256256
const kSentHeaders = Symbol('sent-headers');
257+
const kRawHeaders = Symbol('raw-headers');
257258
const kSentTrailers = Symbol('sent-trailers');
258259
const kServer = Symbol('server');
259260
const kState = Symbol('state');
@@ -1807,12 +1808,14 @@ class ClientHttp2Session extends Http2Session {
18071808

18081809
let headersList;
18091810
let headersObject;
1811+
let rawHeaders;
18101812
let scheme;
18111813
let authority;
18121814
let method;
18131815

18141816
if (ArrayIsArray(headersParam)) {
18151817
({
1818+
rawHeaders,
18161819
headersList,
18171820
scheme,
18181821
authority,
@@ -1859,6 +1862,7 @@ class ClientHttp2Session extends Http2Session {
18591862
// eslint-disable-next-line no-use-before-define
18601863
const stream = new ClientHttp2Stream(this, undefined, undefined, {});
18611864
stream[kSentHeaders] = headersObject; // N.b. Only set for object headers, not raw headers
1865+
stream[kRawHeaders] = rawHeaders; // N.b. Only set for raw headers, not object headers
18621866
stream[kOrigin] = `${scheme}://${authority}`;
18631867
const reqAsync = new AsyncResource('PendingRequest');
18641868
stream[kRequestAsyncResource] = reqAsync;
@@ -2128,6 +2132,33 @@ class Http2Stream extends Duplex {
21282132
}
21292133

21302134
get sentHeaders() {
2135+
if (this[kSentHeaders] || !this[kRawHeaders]) {
2136+
return this[kSentHeaders];
2137+
}
2138+
2139+
const rawHeaders = this[kRawHeaders];
2140+
const headersObject = { __proto__: null };
2141+
2142+
for (let i = 0; i < rawHeaders.length; i += 2) {
2143+
const key = rawHeaders[i];
2144+
const value = rawHeaders[i + 1];
2145+
2146+
const existing = headersObject[key];
2147+
if (existing === undefined) {
2148+
headersObject[key] = value;
2149+
} else if (ArrayIsArray(existing)) {
2150+
existing.push(value);
2151+
} else {
2152+
headersObject[key] = [existing, value];
2153+
}
2154+
}
2155+
2156+
if (rawHeaders[kSensitiveHeaders] !== undefined) {
2157+
headersObject[kSensitiveHeaders] = rawHeaders[kSensitiveHeaders];
2158+
}
2159+
2160+
this[kSentHeaders] = headersObject;
2161+
21312162
return this[kSentHeaders];
21322163
}
21332164

lib/internal/http2/util.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -678,15 +678,23 @@ function prepareRequestHeadersArray(headers, session) {
678678
throw new ERR_HTTP2_CONNECT_PATH();
679679
}
680680

681-
const headersList = buildNgHeaderString(
681+
const rawHeaders =
682682
additionalPsuedoHeaders.length ?
683683
additionalPsuedoHeaders.concat(headers) :
684-
headers,
684+
headers;
685+
686+
if (headers[kSensitiveHeaders] !== undefined) {
687+
rawHeaders[kSensitiveHeaders] = headers[kSensitiveHeaders];
688+
}
689+
690+
const headersList = buildNgHeaderString(
691+
rawHeaders,
685692
assertValidPseudoHeader,
686693
headers[kSensitiveHeaders],
687694
);
688695

689696
return {
697+
rawHeaders,
690698
headersList,
691699
scheme,
692700
authority: authority ?? headers[HTTP2_HEADER_HOST],

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,16 @@ const http2 = require('http2');
3939
'a', 'c',
4040
]).end();
4141

42+
assert.deepStrictEqual(req.sentHeaders, {
43+
'__proto__': null,
44+
':path': '/foobar',
45+
':scheme': 'http',
46+
':authority': `localhost:${server.address().port}`,
47+
':method': 'GET',
48+
'a': [ 'b', 'c' ],
49+
'x-FOO': 'bar',
50+
});
51+
4252
req.on('response', common.mustCall((headers) => {
4353
assert.strictEqual(headers[':status'], 200);
4454
client.close();

test/parallel/test-http2-sensitive-headers.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,16 @@ const { duplexPair } = require('stream');
7272

7373
const req = client.request(rawHeaders);
7474

75+
assert.deepStrictEqual(req.sentHeaders, {
76+
'__proto__': null,
77+
':method': 'GET',
78+
':authority': 'localhost:80',
79+
':scheme': 'http',
80+
':path': '/',
81+
'secret': 'secret-value',
82+
[http2.sensitiveHeaders]: [ 'secret' ],
83+
});
84+
7585
req.on('response', common.mustCall((headers) => {
7686
assert.strictEqual(headers[':status'], 200);
7787
}));

0 commit comments

Comments
 (0)