Skip to content

Commit e4fc520

Browse files
RaisinTenaduh95
authored andcommitted
http2: set Http2Stream#sentHeaders for raw headers
When #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: #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 7c8d7fa commit e4fc520

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
@@ -252,6 +252,7 @@ const kProceed = Symbol('proceed');
252252
const kRemoteSettings = Symbol('remote-settings');
253253
const kRequestAsyncResource = Symbol('requestAsyncResource');
254254
const kSentHeaders = Symbol('sent-headers');
255+
const kRawHeaders = Symbol('raw-headers');
255256
const kSentTrailers = Symbol('sent-trailers');
256257
const kServer = Symbol('server');
257258
const kState = Symbol('state');
@@ -1813,12 +1814,14 @@ class ClientHttp2Session extends Http2Session {
18131814

18141815
let headersList;
18151816
let headersObject;
1817+
let rawHeaders;
18161818
let scheme;
18171819
let authority;
18181820
let method;
18191821

18201822
if (ArrayIsArray(headersParam)) {
18211823
({
1824+
rawHeaders,
18221825
headersList,
18231826
scheme,
18241827
authority,
@@ -1865,6 +1868,7 @@ class ClientHttp2Session extends Http2Session {
18651868
// eslint-disable-next-line no-use-before-define
18661869
const stream = new ClientHttp2Stream(this, undefined, undefined, {});
18671870
stream[kSentHeaders] = headersObject; // N.b. Only set for object headers, not raw headers
1871+
stream[kRawHeaders] = rawHeaders; // N.b. Only set for raw headers, not object headers
18681872
stream[kOrigin] = `${scheme}://${authority}`;
18691873
const reqAsync = new AsyncResource('PendingRequest');
18701874
stream[kRequestAsyncResource] = reqAsync;
@@ -2134,6 +2138,33 @@ class Http2Stream extends Duplex {
21342138
}
21352139

21362140
get sentHeaders() {
2141+
if (this[kSentHeaders] || !this[kRawHeaders]) {
2142+
return this[kSentHeaders];
2143+
}
2144+
2145+
const rawHeaders = this[kRawHeaders];
2146+
const headersObject = { __proto__: null };
2147+
2148+
for (let i = 0; i < rawHeaders.length; i += 2) {
2149+
const key = rawHeaders[i];
2150+
const value = rawHeaders[i + 1];
2151+
2152+
const existing = headersObject[key];
2153+
if (existing === undefined) {
2154+
headersObject[key] = value;
2155+
} else if (ArrayIsArray(existing)) {
2156+
existing.push(value);
2157+
} else {
2158+
headersObject[key] = [existing, value];
2159+
}
2160+
}
2161+
2162+
if (rawHeaders[kSensitiveHeaders] !== undefined) {
2163+
headersObject[kSensitiveHeaders] = rawHeaders[kSensitiveHeaders];
2164+
}
2165+
2166+
this[kSentHeaders] = headersObject;
2167+
21372168
return this[kSentHeaders];
21382169
}
21392170

lib/internal/http2/util.js

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

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

688695
return {
696+
rawHeaders,
689697
headersList,
690698
scheme,
691699
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)