mirror of
https://github.com/nodejs/node.git
synced 2025-05-20 23:55:47 +00:00

Although most of the time openStream will be able to create the stream immediately, when a stream is opened before the handshake is complete we have to wait for the handshake to be complete before continuing. PR-URL: https://github.com/nodejs/node/pull/34351 Reviewed-By: Robert Nagy <ronagy@icloud.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
152 lines
4.1 KiB
JavaScript
152 lines
4.1 KiB
JavaScript
// Flags: --expose-internals --no-warnings
|
|
'use strict';
|
|
|
|
// Tests a simple QUIC HTTP/3 client/server round-trip
|
|
|
|
const common = require('../common');
|
|
if (!common.hasQuic)
|
|
common.skip('missing quic');
|
|
|
|
const Countdown = require('../common/countdown');
|
|
const assert = require('assert');
|
|
const fs = require('fs');
|
|
|
|
const {
|
|
key,
|
|
cert,
|
|
ca,
|
|
debug,
|
|
kHttp3Alpn,
|
|
kServerPort,
|
|
kClientPort,
|
|
setupKeylog,
|
|
} = require('../common/quic');
|
|
|
|
const filedata = fs.readFileSync(__filename, { encoding: 'utf8' });
|
|
|
|
const { createQuicSocket } = require('net');
|
|
const kServerName = 'agent2'; // Intentionally the wrong servername
|
|
|
|
const options = { key, cert, ca, alpn: kHttp3Alpn };
|
|
|
|
const client = createQuicSocket({
|
|
endpoint: { port: kClientPort },
|
|
client: options
|
|
});
|
|
const server = createQuicSocket({
|
|
endpoint: { port: kServerPort },
|
|
server: options
|
|
});
|
|
|
|
client.on('close', common.mustCall());
|
|
server.on('close', common.mustCall());
|
|
|
|
const countdown = new Countdown(1, () => {
|
|
debug('Countdown expired. Destroying sockets');
|
|
server.close();
|
|
client.close();
|
|
});
|
|
|
|
(async function() {
|
|
server.on('session', common.mustCall((session) => {
|
|
debug('QuicServerSession Created');
|
|
|
|
assert.strictEqual(session.maxStreams.bidi, 100);
|
|
assert.strictEqual(session.maxStreams.uni, 3);
|
|
|
|
setupKeylog(session);
|
|
|
|
session.on('secure', common.mustCall((_, alpn) => {
|
|
debug('QuicServerSession handshake completed');
|
|
assert.strictEqual(session.alpnProtocol, alpn);
|
|
}));
|
|
|
|
session.on('stream', common.mustCall((stream) => {
|
|
debug('Bidirectional, Client-initiated stream %d received', stream.id);
|
|
const file = fs.createReadStream(__filename);
|
|
let data = '';
|
|
|
|
assert(stream.submitInitialHeaders({ ':status': '200' }));
|
|
|
|
file.pipe(stream);
|
|
stream.setEncoding('utf8');
|
|
|
|
stream.on('initialHeaders', common.mustCall((headers) => {
|
|
const expected = [
|
|
[ ':path', '/' ],
|
|
[ ':authority', 'localhost' ],
|
|
[ ':scheme', 'https' ],
|
|
[ ':method', 'POST' ]
|
|
];
|
|
assert.deepStrictEqual(expected, headers);
|
|
debug('Received expected request headers');
|
|
}));
|
|
stream.on('informationalHeaders', common.mustNotCall());
|
|
stream.on('trailingHeaders', common.mustNotCall());
|
|
|
|
stream.on('data', (chunk) => {
|
|
data += chunk;
|
|
});
|
|
stream.on('end', common.mustCall(() => {
|
|
assert.strictEqual(data, filedata);
|
|
debug('Server received expected data for stream %d', stream.id);
|
|
}));
|
|
stream.on('close', common.mustCall());
|
|
stream.on('finish', common.mustCall());
|
|
}));
|
|
|
|
session.on('close', common.mustCall());
|
|
}));
|
|
|
|
await server.listen();
|
|
|
|
debug('Server is listening on port %d', server.endpoints[0].address.port);
|
|
|
|
const req = await client.connect({
|
|
address: 'localhost',
|
|
port: server.endpoints[0].address.port,
|
|
servername: kServerName,
|
|
h3: { maxPushes: 10 }
|
|
});
|
|
debug('QuicClientSession Created');
|
|
|
|
req.on('close', common.mustCall());
|
|
|
|
const file = fs.createReadStream(__filename);
|
|
const stream = await req.openStream();
|
|
|
|
assert(stream.submitInitialHeaders({
|
|
':method': 'POST',
|
|
':scheme': 'https',
|
|
':authority': 'localhost',
|
|
':path': '/',
|
|
}));
|
|
file.pipe(stream);
|
|
let data = '';
|
|
stream.resume();
|
|
stream.setEncoding('utf8');
|
|
|
|
stream.on('initialHeaders', common.mustCall((headers) => {
|
|
const expected = [
|
|
[ ':status', '200' ]
|
|
];
|
|
assert.deepStrictEqual(expected, headers);
|
|
debug('Received expected response headers');
|
|
}));
|
|
stream.on('informationalHeaders', common.mustNotCall());
|
|
stream.on('trailingHeaders', common.mustNotCall());
|
|
|
|
stream.on('data', (chunk) => data += chunk);
|
|
stream.on('finish', common.mustCall());
|
|
stream.on('end', common.mustCall(() => {
|
|
assert.strictEqual(data, filedata);
|
|
debug('Client received expected data for stream %d', stream.id);
|
|
}));
|
|
stream.on('close', common.mustCall(() => {
|
|
debug('Bidirectional, Client-initiated stream %d closed', stream.id);
|
|
countdown.dec();
|
|
}));
|
|
debug('Bidirectional, Client-initiated stream %d opened', stream.id);
|
|
|
|
})().then(common.mustCall());
|