Skip to content

Commit 02752e5

Browse files
committed
Include :status in HTTP/2 response event subscription data
1 parent 6283b1e commit 02752e5

File tree

2 files changed

+58
-1
lines changed

2 files changed

+58
-1
lines changed

src/util/request-utils.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,10 @@ export function trackResponse(
402402
writtenHeaders = objectHeadersToRaw(headersArg ?? {});
403403
}
404404

405+
if (isHttp2(trackedResponse)) {
406+
writtenHeaders.unshift([':status', args[0].toString()]);
407+
}
408+
405409
// Headers might also have been set with setHeader before. They'll be combined, with headers
406410
// here taking precendence. We simulate this by pulling in all values from getHeaders() and
407411
// remembering any of those that we're not about to override.

test/integration/http2.spec.ts

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import * as semver from 'semver';
88
import * as fs from 'fs';
99
import * as portfinder from 'portfinder';
1010

11-
import { CompletedRequest, getLocal } from "../..";
11+
import { CompletedRequest, CompletedResponse, getLocal } from "../..";
1212
import {
1313
expect,
1414
nodeOnly,
@@ -461,6 +461,59 @@ nodeOnly(() => {
461461
await cleanup(proxiedClient, client);
462462
});
463463

464+
it("should include should metadata in events for proxied HTTP/2 responses", async function() {
465+
if (!semver.satisfies(process.version, H2_TLS_ON_TLS_SUPPORTED)) this.skip();
466+
467+
let seenResponsePromise = getDeferred<CompletedResponse>();
468+
await server.on('response', (r) => seenResponsePromise.resolve(r));
469+
470+
await server.forGet('https://example.com/mocked-endpoint')
471+
.thenReply(200, "Proxied HTTP2 response!", {
472+
'TEST-header': 'value'
473+
});
474+
475+
const client = http2.connect(server.url);
476+
477+
const req = client.request({
478+
':method': 'CONNECT',
479+
':authority': 'example.com:443'
480+
});
481+
482+
// Initial response, the proxy has set up our tunnel:
483+
const responseHeaders = await getHttp2Response(req);
484+
expect(responseHeaders[':status']).to.equal(200);
485+
486+
// We can now read/write to req as a raw TCP socket to example.com:
487+
const proxiedClient = http2.connect('https://example.com', {
488+
// Tunnel this request through the proxy stream
489+
createConnection: () => tls.connect({
490+
socket: req as any,
491+
ALPNProtocols: ['h2']
492+
})
493+
});
494+
495+
const proxiedRequest = proxiedClient.request({
496+
':path': '/mocked-endpoint'
497+
});
498+
await getHttp2Response(proxiedRequest);
499+
await getHttp2Body(proxiedRequest)
500+
501+
const seenResponse = await seenResponsePromise;
502+
expect(seenResponse.statusCode).to.equal(200);
503+
expect(seenResponse.statusMessage).to.equal('');
504+
expect(seenResponse.headers).to.deep.equal({
505+
':status': '200',
506+
'test-header': 'value'
507+
});
508+
expect(seenResponse.rawHeaders).to.deep.equal([
509+
[':status', '200'],
510+
['TEST-header', 'value']
511+
]);
512+
expect(await seenResponse.body.getText()).to.equal('Proxied HTTP2 response!');
513+
514+
await cleanup(proxiedClient, client);
515+
});
516+
464517
it("can respond to HTTP1-proxied HTTP/2 requests", async function() {
465518
if (!semver.satisfies(process.version, H2_TLS_ON_TLS_SUPPORTED)) this.skip();
466519

0 commit comments

Comments
 (0)