|
| 1 | +// Flags: --experimental-quic --no-warnings |
| 2 | + |
| 3 | +// Test: HTTP/3 can't start when the peer allows fewer than the three |
| 4 | +// unidirectional streams it needs for its control and QPACK streams. That |
| 5 | +// must close the session, rather than leave it running without HTTP/3. |
| 6 | + |
| 7 | +import { hasQuic, skip, mustCall } from '../common/index.mjs'; |
| 8 | +import assert from 'node:assert'; |
| 9 | +import * as fixtures from '../common/fixtures.mjs'; |
| 10 | + |
| 11 | +if (!hasQuic) { |
| 12 | + skip('QUIC is not enabled'); |
| 13 | +} |
| 14 | + |
| 15 | +const { listen, connect } = await import('node:quic'); |
| 16 | +const { createPrivateKey } = await import('node:crypto'); |
| 17 | + |
| 18 | +const key = createPrivateKey(fixtures.readKey('agent1-key.pem')); |
| 19 | +const cert = fixtures.readKey('agent1-cert.pem'); |
| 20 | +const headers = { |
| 21 | + ':method': 'GET', |
| 22 | + ':path': '/', |
| 23 | + ':scheme': 'https', |
| 24 | + ':authority': 'localhost', |
| 25 | +}; |
| 26 | +const internalError = { |
| 27 | + code: 'ERR_QUIC_TRANSPORT_ERROR', |
| 28 | + message: /INTERNAL_ERROR/, |
| 29 | +}; |
| 30 | + |
| 31 | +async function attachToLowUniServer() { |
| 32 | + const endpoint = await listen(mustCall((quicSession) => { |
| 33 | + quicSession.onerror = () => {}; |
| 34 | + }), { |
| 35 | + alpn: ['h3'], |
| 36 | + sni: { '*': { keys: [key], certs: [cert] } }, |
| 37 | + transportParams: { initialMaxStreamsUni: 2 }, |
| 38 | + }); |
| 39 | + const client = await connect(endpoint.address, { |
| 40 | + alpn: 'h3', |
| 41 | + servername: 'localhost', |
| 42 | + verifyPeer: 'manual', |
| 43 | + }); |
| 44 | + return { endpoint, client }; |
| 45 | +} |
| 46 | + |
| 47 | +// Nothing opened: the session closes when the handshake completes. |
| 48 | +{ |
| 49 | + const { endpoint, client } = await attachToLowUniServer(); |
| 50 | + await assert.rejects(client.closed, internalError); |
| 51 | + await endpoint.close(); |
| 52 | +} |
| 53 | + |
| 54 | +// A request opened as soon as the session opens fails, and the session |
| 55 | +// closes rather than accepting further requests. |
| 56 | +{ |
| 57 | + const { endpoint, client } = await attachToLowUniServer(); |
| 58 | + client.onerror = mustCall((err) => { |
| 59 | + assert.strictEqual(err.code, internalError.code); |
| 60 | + }); |
| 61 | + await client.opened; |
| 62 | + await assert.rejects(client.createBidirectionalStream({ headers }), |
| 63 | + { code: 'ERR_QUIC_OPEN_STREAM_FAILED' }); |
| 64 | + await assert.rejects(client.closed, internalError); |
| 65 | + await assert.rejects(client.createBidirectionalStream({ headers }), |
| 66 | + { code: 'ERR_INVALID_STATE' }); |
| 67 | + await endpoint.close(); |
| 68 | +} |
0 commit comments