Skip to content

Commit 702294e

Browse files
Copilotfengmk2
andauthored
test: Add test for http2.server.stream.finish diagnostics channel (#740)
Node.js added the `http2.server.stream.finish` diagnostics channel in [nodejs/node#58560](nodejs/node#58560), which fires when `ServerHttp2Stream.respond()` succeeds. This adds test coverage verifying urllib works correctly with this channel. - Subscribe to `http2.server.stream.finish` in an H2 test server scenario - Make HEAD and GET requests via `HttpClient` with `allowH2: true` - Assert published messages contain valid `stream` (ServerHttp2Stream), `headers` (object), and `flags` (number) --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: fengmk2 <156269+fengmk2@users.noreply.github.com>
1 parent fdb513b commit 702294e

1 file changed

Lines changed: 62 additions & 0 deletions

File tree

test/diagnostics_channel.test.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import diagnosticsChannel from 'node:diagnostics_channel';
33
import { once } from 'node:events';
44
import { createSecureServer } from 'node:http2';
55
import type { AddressInfo } from 'node:net';
6+
import { Duplex } from 'node:stream';
67
import { setTimeout as sleep } from 'node:timers/promises';
78

89
import selfsigned from 'selfsigned';
@@ -282,6 +283,67 @@ describe('diagnostics_channel.test.ts', () => {
282283
server.close();
283284
});
284285

286+
it('should support http2.server.stream.finish diagnostics channel', async () => {
287+
const pem = selfsigned.generate([], {
288+
keySize: 2048,
289+
});
290+
const server = createSecureServer({
291+
key: pem.private,
292+
cert: pem.cert,
293+
});
294+
server.on('stream', (stream, headers) => {
295+
stream.respond({
296+
'content-type': 'text/plain; charset=utf-8',
297+
'x-custom-h2': 'hello',
298+
':status': 200,
299+
});
300+
if (headers[':method'] !== 'HEAD') {
301+
stream.end('hello h2!');
302+
}
303+
});
304+
305+
server.listen(0);
306+
await once(server, 'listening');
307+
308+
const finishMessages: { stream: any; headers: any; flags: any }[] = [];
309+
function onFinishMessage(message: any) {
310+
finishMessages.push(message);
311+
}
312+
diagnosticsChannel.subscribe('http2.server.stream.finish', onFinishMessage);
313+
314+
const httpClient = new HttpClient({
315+
allowH2: true,
316+
connect: {
317+
rejectUnauthorized: false,
318+
},
319+
});
320+
321+
// HEAD request
322+
let response = await httpClient.request(`https://localhost:${(server.address() as AddressInfo).port}?head=true`, {
323+
method: 'HEAD',
324+
});
325+
assert.equal(response.status, 200);
326+
327+
await sleep(1);
328+
329+
// GET request
330+
response = await httpClient.request(`https://localhost:${(server.address() as AddressInfo).port}`, {
331+
method: 'GET',
332+
});
333+
assert.equal(response.status, 200);
334+
335+
assert.equal(finishMessages.length, 2);
336+
for (const msg of finishMessages) {
337+
assert.ok(msg.stream instanceof Duplex);
338+
assert.equal(msg.stream.constructor.name, 'ServerHttp2Stream');
339+
assert.ok(msg.headers && typeof msg.headers === 'object' && !Array.isArray(msg.headers));
340+
assert.equal(typeof msg.flags, 'number');
341+
}
342+
343+
diagnosticsChannel.unsubscribe('http2.server.stream.finish', onFinishMessage);
344+
server.close();
345+
});
346+
285347
it('should support trace request by urllib:request and urllib:response', async () => {
286348
let lastRequestOpaque: any;
287349
let socket: any;

0 commit comments

Comments
 (0)