mirror of
https://github.com/zebrajr/node.git
synced 2026-01-15 12:15:26 +00:00
This does not fix occurrences in test/parallel/test-dns-* because those tests contain unrelated pre-existing bugs that would cause the tests to fail with this fix. This unrelated bug in those tests should be fixed separately before the use of mustNotCall() can be fixed in those files. PR-URL: https://github.com/nodejs/node/pull/44022 Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Juan José Arboleda <soyjuanarbol@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
173 lines
4.6 KiB
JavaScript
173 lines
4.6 KiB
JavaScript
'use strict';
|
|
|
|
const common = require('../common');
|
|
const fixtures = require('../common/fixtures');
|
|
|
|
if (!common.hasCrypto)
|
|
common.skip('missing crypto');
|
|
|
|
const { strictEqual, ok } = require('assert');
|
|
const { createSecureContext } = require('tls');
|
|
const { createSecureServer, connect } = require('http2');
|
|
const { get } = require('https');
|
|
const { parse } = require('url');
|
|
const { connect: tls } = require('tls');
|
|
const { Duplex } = require('stream');
|
|
|
|
const countdown = (count, done) => () => --count === 0 && done();
|
|
|
|
const key = fixtures.readKey('agent8-key.pem');
|
|
const cert = fixtures.readKey('agent8-cert.pem');
|
|
const ca = fixtures.readKey('fake-startcom-root-cert.pem');
|
|
|
|
const clientOptions = { secureContext: createSecureContext({ ca }) };
|
|
|
|
function onRequest(request, response) {
|
|
const { socket: { alpnProtocol } } = request.httpVersion === '2.0' ?
|
|
request.stream.session : request;
|
|
response.writeHead(200, { 'content-type': 'application/json' });
|
|
response.end(JSON.stringify({
|
|
alpnProtocol,
|
|
httpVersion: request.httpVersion
|
|
}));
|
|
}
|
|
|
|
function onSession(session, next) {
|
|
const headers = {
|
|
':path': '/',
|
|
':method': 'GET',
|
|
':scheme': 'https',
|
|
':authority': `localhost:${this.server.address().port}`
|
|
};
|
|
|
|
const request = session.request(headers);
|
|
request.on('response', common.mustCall((headers) => {
|
|
strictEqual(headers[':status'], 200);
|
|
strictEqual(headers['content-type'], 'application/json');
|
|
}));
|
|
request.setEncoding('utf8');
|
|
let raw = '';
|
|
request.on('data', (chunk) => { raw += chunk; });
|
|
request.on('end', common.mustCall(() => {
|
|
const { alpnProtocol, httpVersion } = JSON.parse(raw);
|
|
strictEqual(alpnProtocol, 'h2');
|
|
strictEqual(httpVersion, '2.0');
|
|
|
|
session.close();
|
|
this.cleanup();
|
|
|
|
if (typeof next === 'function') {
|
|
next();
|
|
}
|
|
}));
|
|
request.end();
|
|
}
|
|
|
|
// HTTP/2 & HTTP/1.1 server
|
|
{
|
|
const server = createSecureServer(
|
|
{ cert, key, allowHTTP1: true },
|
|
common.mustCall(onRequest, 2)
|
|
);
|
|
|
|
server.listen(0);
|
|
|
|
server.on('listening', common.mustCall(() => {
|
|
const { port } = server.address();
|
|
const origin = `https://localhost:${port}`;
|
|
|
|
const cleanup = countdown(2, () => server.close());
|
|
|
|
// HTTP/2 client
|
|
connect(
|
|
origin,
|
|
clientOptions,
|
|
common.mustCall(onSession.bind({ cleanup, server }))
|
|
);
|
|
|
|
// HTTP/1.1 client
|
|
get(
|
|
Object.assign(parse(origin), clientOptions),
|
|
common.mustCall((response) => {
|
|
strictEqual(response.statusCode, 200);
|
|
strictEqual(response.statusMessage, 'OK');
|
|
strictEqual(response.headers['content-type'], 'application/json');
|
|
|
|
response.setEncoding('utf8');
|
|
let raw = '';
|
|
response.on('data', (chunk) => { raw += chunk; });
|
|
response.on('end', common.mustCall(() => {
|
|
const { alpnProtocol, httpVersion } = JSON.parse(raw);
|
|
strictEqual(alpnProtocol, false);
|
|
strictEqual(httpVersion, '1.1');
|
|
|
|
cleanup();
|
|
}));
|
|
})
|
|
);
|
|
}));
|
|
}
|
|
|
|
// HTTP/2-only server
|
|
{
|
|
const server = createSecureServer(
|
|
{ cert, key },
|
|
common.mustCall(onRequest)
|
|
);
|
|
|
|
server.once('unknownProtocol', common.mustCall((socket) => {
|
|
strictEqual(socket instanceof Duplex, true);
|
|
socket.destroy();
|
|
}));
|
|
|
|
server.listen(0);
|
|
|
|
server.on('listening', common.mustCall(() => {
|
|
const { port } = server.address();
|
|
const origin = `https://localhost:${port}`;
|
|
|
|
const cleanup = countdown(4, () => server.close());
|
|
|
|
// HTTP/2 client
|
|
connect(
|
|
origin,
|
|
clientOptions,
|
|
common.mustCall(function(session) {
|
|
onSession.call({ cleanup, server },
|
|
session,
|
|
common.mustCall(testNoTls));
|
|
})
|
|
);
|
|
|
|
function testNoTls() {
|
|
// HTTP/1.1 client
|
|
get(Object.assign(parse(origin), clientOptions), common.mustNotCall())
|
|
.on('error', common.mustCall(cleanup))
|
|
.on('error', common.mustCall(testWrongALPN))
|
|
.end();
|
|
}
|
|
|
|
function testWrongALPN() {
|
|
// Incompatible ALPN TLS client
|
|
tls(Object.assign({ port, ALPNProtocols: ['fake'] }, clientOptions))
|
|
.on('error', common.mustCall((err) => {
|
|
strictEqual(err.code, 'ECONNRESET');
|
|
cleanup();
|
|
testNoALPN();
|
|
}));
|
|
}
|
|
|
|
function testNoALPN() {
|
|
// TLS client does not send an ALPN extension
|
|
let text = '';
|
|
tls(Object.assign({ port }, clientOptions))
|
|
.setEncoding('utf8')
|
|
.on('data', (chunk) => text += chunk)
|
|
.on('end', common.mustCall(() => {
|
|
ok(/Missing ALPN Protocol, expected `h2` to be available/.test(text));
|
|
cleanup();
|
|
}));
|
|
}
|
|
}));
|
|
}
|