From 2d102f4abf98cdad7e33f2b75c5e7dc577b2f1ef Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Sun, 25 Feb 2018 21:54:18 +0100 Subject: [PATCH] http2: send error text in case of ALPN mismatch Send a human-readable HTTP/1 response in case of an unexpected ALPN protocol. This helps with debugging this condition, since previously the only result of it would be a closed socket. --- lib/internal/http2/core.js | 13 +++++++++++-- test/parallel/test-http2-https-fallback.js | 13 ++++++++++--- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/lib/internal/http2/core.js b/lib/internal/http2/core.js index b7a56850a308c8..f3b23a6ec4f830 100644 --- a/lib/internal/http2/core.js +++ b/lib/internal/http2/core.js @@ -2472,8 +2472,17 @@ function connectionListener(socket) { return httpConnectionListener.call(this, socket); } // Let event handler deal with the socket - if (!this.emit('unknownProtocol', socket)) - socket.destroy(); + debug(`Unknown protocol from ${socket.remoteAddress}:${socket.remotePort}`); + if (!this.emit('unknownProtocol', socket)) { + // We don't know what to do, so let's just tell the other side what's + // going on in a format that they *might* understand. + socket.end('HTTP/1.0 403 Forbidden\r\n' + + 'Content-Type: text/plain\r\n\r\n' + + 'Unknown ALPN Protocol, expected `h2` to be available.\n' + + 'If this is a HTTP request: The server was not ' + + 'configured with the `allowHTTP1` option or a ' + + 'listener for the `unknownProtocol` event.\n'); + } return; } diff --git a/test/parallel/test-http2-https-fallback.js b/test/parallel/test-http2-https-fallback.js index 01b694e586dd49..5d9a7e17103e56 100644 --- a/test/parallel/test-http2-https-fallback.js +++ b/test/parallel/test-http2-https-fallback.js @@ -6,7 +6,7 @@ const fixtures = require('../common/fixtures'); if (!common.hasCrypto) common.skip('missing crypto'); -const { strictEqual } = require('assert'); +const { strictEqual, ok } = require('assert'); const { createSecureContext } = require('tls'); const { createSecureServer, connect } = require('http2'); const { get } = require('https'); @@ -131,10 +131,17 @@ function onSession(session) { // HTTP/1.1 client get(Object.assign(parse(origin), clientOptions), common.mustNotCall()) - .on('error', common.mustCall(cleanup)); + .on('error', common.mustCall(cleanup)) + .end(); // Incompatible ALPN TLS client + let text = ''; tls(Object.assign({ port, ALPNProtocols: ['fake'] }, clientOptions)) - .on('error', common.mustCall(cleanup)); + .setEncoding('utf8') + .on('data', (chunk) => text += chunk) + .on('end', common.mustCall(() => { + ok(/Unknown ALPN Protocol, expected `h2` to be available/.test(text)); + cleanup(); + })); })); }