On the client, add verifyPeer: 'auto', 'strict', and 'manual' modes. The 'strict' mode will reject invalid certs at the handshake layer, while the 'manual' mode allows the application to inspect the peer cert and decide whether to trust it or not. The 'auto' mode is the default and will reject invalid certs at a middle layer after the onhandshake event. Signed-off-by: James M Snell <jasnell@gmail.com> Assisted-by: Opencode/Opus 4.6 PR-URL: https://github.com/nodejs/node/pull/63483 Reviewed-By: Stephen Belanger <admin@stephenbelanger.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
78 lines
2.5 KiB
JavaScript
78 lines
2.5 KiB
JavaScript
// Flags: --experimental-quic --no-warnings
|
|
|
|
// Test: Headers support detection for non-H3 sessions.
|
|
// headersSupported is UNSUPPORTED for non-H3 sessions
|
|
// Sending headers on non-H3 session throws ERR_INVALID_STATE
|
|
// Setting header callbacks on non-H3 stream throws ERR_INVALID_STATE
|
|
|
|
import { hasQuic, skip, mustCall } from '../common/index.mjs';
|
|
import assert from 'node:assert';
|
|
import * as fixtures from '../common/fixtures.mjs';
|
|
const { readKey } = fixtures;
|
|
|
|
const { throws } = assert;
|
|
|
|
if (!hasQuic) {
|
|
skip('QUIC is not enabled');
|
|
}
|
|
|
|
const { listen, connect } = await import('node:quic');
|
|
const { createPrivateKey } = await import('node:crypto');
|
|
|
|
const key = createPrivateKey(readKey('agent1-key.pem'));
|
|
const cert = readKey('agent1-cert.pem');
|
|
const encoder = new TextEncoder();
|
|
|
|
const serverDone = Promise.withResolvers();
|
|
const serverEndpoint = await listen(mustCall(async (serverSession) => {
|
|
serverSession.onstream = mustCall(async (stream) => {
|
|
// Sending headers on non-H3 stream throws.
|
|
throws(() => stream.sendHeaders({ ':status': '200' }), { code: 'ERR_INVALID_STATE' });
|
|
|
|
// Setting onheaders on non-H3 stream throws.
|
|
throws(() => stream.onheaders = () => {}, { code: 'ERR_INVALID_STATE' });
|
|
|
|
// Setting ontrailers on non-H3 stream throws.
|
|
throws(() => stream.ontrailers = () => {}, { code: 'ERR_INVALID_STATE' });
|
|
|
|
// Setting oninfo on non-H3 stream throws.
|
|
throws(() => stream.oninfo = () => {}, { code: 'ERR_INVALID_STATE' });
|
|
|
|
// Setting onwanttrailers on non-H3 stream throws.
|
|
throws(() => stream.onwanttrailers = () => {}, { code: 'ERR_INVALID_STATE' });
|
|
|
|
// sendInformationalHeaders throws on non-H3.
|
|
throws(() => stream.sendInformationalHeaders({ ':status': '103' }), {
|
|
code: 'ERR_INVALID_STATE',
|
|
});
|
|
|
|
// sendTrailers throws on non-H3.
|
|
throws(() => stream.sendTrailers({ 'x-trailer': 'value' }), { code: 'ERR_INVALID_STATE' });
|
|
|
|
stream.writer.endSync();
|
|
|
|
serverSession.close();
|
|
serverDone.resolve();
|
|
});
|
|
}), {
|
|
sni: { '*': { keys: [key], certs: [cert] } },
|
|
alpn: 'quic-test',
|
|
});
|
|
|
|
const clientSession = await connect(serverEndpoint.address, {
|
|
servername: 'localhost',
|
|
verifyPeer: 'manual',
|
|
alpn: 'quic-test',
|
|
});
|
|
await clientSession.opened;
|
|
|
|
const stream = await clientSession.createBidirectionalStream({
|
|
body: encoder.encode('ping'),
|
|
});
|
|
|
|
// Client side — sending headers on non-H3 stream throws.
|
|
throws(() => stream.sendHeaders({ ':method': 'GET' }), { code: 'ERR_INVALID_STATE' });
|
|
|
|
await serverDone.promise;
|
|
await clientSession.close();
|
|
await serverEndpoint.close();
|