Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 137aa5c

Browse filesBrowse files
orgadsRafaelGSS
authored andcommitted
http2: fix client async storage persistence
Create and store an AsyncResource for each stream, following a similar approach as used in HttpAgent. Fixes: #55376 PR-URL: #55460 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Stephen Belanger <admin@stephenbelanger.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Gerhard Stöbich <deb2001-github@yahoo.de>
1 parent 56c46ab commit 137aa5c
Copy full SHA for 137aa5c

File tree

Expand file treeCollapse file tree

2 files changed

+66
-2
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

2 files changed

+66
-2
lines changed
Open diff view settings
Collapse file

‎lib/internal/http2/core.js‎

Copy file name to clipboardExpand all lines: lib/internal/http2/core.js
+11-2Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ const {
6060
owner_symbol,
6161
},
6262
} = require('internal/async_hooks');
63+
const { AsyncResource } = require('async_hooks');
64+
6365
const {
6466
AbortError,
6567
aggregateTwoErrors,
@@ -241,6 +243,7 @@ const kPendingRequestCalls = Symbol('kPendingRequestCalls');
241243
const kProceed = Symbol('proceed');
242244
const kProtocol = Symbol('protocol');
243245
const kRemoteSettings = Symbol('remote-settings');
246+
const kRequestAsyncResource = Symbol('requestAsyncResource');
244247
const kSelectPadding = Symbol('select-padding');
245248
const kSentHeaders = Symbol('sent-headers');
246249
const kSentTrailers = Symbol('sent-trailers');
@@ -408,7 +411,11 @@ function onSessionHeaders(handle, id, cat, flags, headers, sensitiveHeaders) {
408411
originSet.delete(stream[kOrigin]);
409412
}
410413
debugStream(id, type, "emitting stream '%s' event", event);
411-
process.nextTick(emit, stream, event, obj, flags, headers);
414+
const reqAsync = stream[kRequestAsyncResource];
415+
if (reqAsync)
416+
reqAsync.runInAsyncScope(process.nextTick, null, emit, stream, event, obj, flags, headers);
417+
else
418+
process.nextTick(emit, stream, event, obj, flags, headers);
412419
}
413420
if (endOfStream) {
414421
stream.push(null);
@@ -1797,6 +1804,8 @@ class ClientHttp2Session extends Http2Session {
17971804
stream[kSentHeaders] = headers;
17981805
stream[kOrigin] = `${headers[HTTP2_HEADER_SCHEME]}://` +
17991806
`${getAuthority(headers)}`;
1807+
const reqAsync = new AsyncResource('PendingRequest');
1808+
stream[kRequestAsyncResource] = reqAsync;
18001809

18011810
// Close the writable side of the stream if options.endStream is set.
18021811
if (options.endStream)
@@ -1819,7 +1828,7 @@ class ClientHttp2Session extends Http2Session {
18191828
}
18201829
}
18211830

1822-
const onConnect = requestOnConnect.bind(stream, headersList, options);
1831+
const onConnect = reqAsync.bind(requestOnConnect.bind(stream, headersList, options));
18231832
if (this.connecting) {
18241833
if (this[kPendingRequestCalls] !== null) {
18251834
this[kPendingRequestCalls].push(onConnect);
Collapse file
+55Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
if (!common.hasCrypto)
5+
common.skip('missing crypto');
6+
const assert = require('assert');
7+
const http2 = require('http2');
8+
const async_hooks = require('async_hooks');
9+
10+
const storage = new async_hooks.AsyncLocalStorage();
11+
12+
const {
13+
HTTP2_HEADER_CONTENT_TYPE,
14+
HTTP2_HEADER_PATH,
15+
HTTP2_HEADER_STATUS,
16+
} = http2.constants;
17+
18+
const server = http2.createServer();
19+
server.on('stream', (stream) => {
20+
stream.respond({
21+
[HTTP2_HEADER_CONTENT_TYPE]: 'text/plain; charset=utf-8',
22+
[HTTP2_HEADER_STATUS]: 200
23+
});
24+
stream.on('error', common.mustNotCall());
25+
stream.end('data');
26+
});
27+
28+
server.listen(0, async () => {
29+
const client = storage.run({ id: 0 }, () => http2.connect(`http://localhost:${server.address().port}`));
30+
31+
async function doReq(id) {
32+
const req = client.request({ [HTTP2_HEADER_PATH]: '/' });
33+
34+
req.on('response', common.mustCall((headers) => {
35+
assert.strictEqual(headers[HTTP2_HEADER_STATUS], 200);
36+
assert.strictEqual(id, storage.getStore().id);
37+
}));
38+
req.on('data', common.mustCall((data) => {
39+
assert.strictEqual(data.toString(), 'data');
40+
assert.strictEqual(id, storage.getStore().id);
41+
}));
42+
req.on('end', common.mustCall(() => {
43+
assert.strictEqual(id, storage.getStore().id);
44+
server.close();
45+
client.close();
46+
}));
47+
}
48+
49+
function doReqWith(id) {
50+
storage.run({ id }, () => doReq(id));
51+
}
52+
53+
doReqWith(1);
54+
doReqWith(2);
55+
});

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.