From ed3604cd64765cb6dfb0b7160ce1b829666d3194 Mon Sep 17 00:00:00 2001 From: wwwzbwcom Date: Fri, 9 Jul 2021 15:59:35 +0800 Subject: [PATCH] http: server check Host header, to meet RFC 7230 5.4 requirement PR-URL: https://github.com/nodejs/node/pull/45597 Fixes: https://github.com/nodejs/node/issues/39033 Co-authored-by: Luigi Pinca Co-authored-by: mscdex Reviewed-By: Robert Nagy Reviewed-By: Paolo Insogna Reviewed-By: Yagiz Nizipli Reviewed-By: Matteo Collina --- doc/api/http.md | 4 ++ lib/_http_server.js | 20 ++++++++- lib/http.js | 1 + test/parallel/test-http-chunked-304.js | 2 +- .../test-http-client-headers-array.js | 17 ++++++-- test/parallel/test-http-content-length.js | 6 +-- test/parallel/test-http-header-badrequest.js | 2 +- .../test-http-insecure-parser-per-stream.js | 4 ++ test/parallel/test-http-insecure-parser.js | 1 + .../test-http-keep-alive-drop-requests.js | 1 + .../test-http-keep-alive-max-requests.js | 2 + ...t-http-keep-alive-pipeline-max-requests.js | 1 + test/parallel/test-http-malformed-request.js | 2 +- .../test-http-max-header-size-per-stream.js | 1 + test/parallel/test-http-max-headers-count.js | 8 ++-- ...est-http-pipeline-assertionerror-finish.js | 2 +- ...-http-pipeline-requests-connection-leak.js | 2 +- ...t-http-pipeline-socket-parser-typeerror.js | 2 +- ...st-http-req-close-robust-from-tampering.js | 1 + .../parallel/test-http-request-host-header.js | 41 +++++++++++++++++++ test/parallel/test-http-response-splitting.js | 2 +- test/parallel/test-http-server-close-all.js | 2 +- test/parallel/test-http-server-close-idle.js | 2 +- ...t-http-server-headers-timeout-keepalive.js | 2 +- ...-http-server-headers-timeout-pipelining.js | 3 +- .../test-http-server-keep-alive-defaults.js | 1 + ...ttp-server-keep-alive-max-requests-null.js | 1 + ...ttp-server-request-timeout-delayed-body.js | 1 + ...server-request-timeout-interrupted-body.js | 1 + ...t-http-server-request-timeout-keepalive.js | 2 +- ...-http-server-request-timeout-pipelining.js | 3 +- ...test-http-server-request-timeouts-mixed.js | 2 +- test/parallel/test-http-server-unconsume.js | 2 +- test/parallel/test-http-server.js | 13 ++++-- test/parallel/test-http-set-trailers.js | 2 +- test/parallel/test-http-status-message.js | 5 ++- test/parallel/test-http-upgrade-server.js | 4 +- test/parallel/test-http.js | 4 +- .../test-https-agent-create-connection.js | 2 +- test/parallel/test-https-host-headers.js | 2 +- .../test-https-insecure-parse-per-stream.js | 4 ++ .../test-https-keep-alive-drop-requests.js | 2 +- .../test-https-max-header-size-per-stream.js | 4 ++ test/parallel/test-https-max-headers-count.js | 8 ++-- test/parallel/test-https-server-close-all.js | 2 +- test/parallel/test-https-server-close-idle.js | 2 +- 46 files changed, 156 insertions(+), 42 deletions(-) create mode 100644 test/parallel/test-http-request-host-header.js diff --git a/doc/api/http.md b/doc/api/http.md index 276739366328b0..0355df275f4138 100644 --- a/doc/api/http.md +++ b/doc/api/http.md @@ -3185,6 +3185,10 @@ changes: * `uniqueHeaders` {Array} A list of response headers that should be sent only once. If the header's value is an array, the items will be joined using `; `. + * `requireHostHeader` {boolean} It forces the server to respond with + a 400 (Bad Request) status code to any HTTP/1.1 request message + that lacks a Host header (as mandated by the specification). + **Default:** `true`. * `requestListener` {Function} diff --git a/lib/_http_server.js b/lib/_http_server.js index 1783a407370656..3c85d343bda53c 100644 --- a/lib/_http_server.js +++ b/lib/_http_server.js @@ -473,6 +473,14 @@ function storeHTTPOptions(options) { } else { this.connectionsCheckingInterval = 30_000; // 30 seconds } + + const requireHostHeader = options.requireHostHeader; + if (requireHostHeader !== undefined) { + validateBoolean(requireHostHeader, 'options.requireHostHeader'); + this.requireHostHeader = requireHostHeader; + } else { + this.requireHostHeader = true; + } } function setupConnectionsTracking(server) { @@ -1022,7 +1030,18 @@ function parserOnIncoming(server, socket, state, req, keepAlive) { let handled = false; + if (req.httpVersionMajor === 1 && req.httpVersionMinor === 1) { + + // From RFC 7230 5.4 https://datatracker.ietf.org/doc/html/rfc7230#section-5.4 + // A server MUST respond with a 400 (Bad Request) status code to any + // HTTP/1.1 request message that lacks a Host header field + if (server.requireHostHeader && req.headers.host === undefined) { + res.writeHead(400, ['Connection', 'close']); + res.end(); + return 0; + } + const isRequestsLimitSet = ( typeof server.maxRequestsPerSocket === 'number' && server.maxRequestsPerSocket > 0 @@ -1045,7 +1064,6 @@ function parserOnIncoming(server, socket, state, req, keepAlive) { if (RegExpPrototypeExec(continueExpression, req.headers.expect) !== null) { res._expect_continue = true; - if (server.listenerCount('checkContinue') > 0) { server.emit('checkContinue', req, res); } else { diff --git a/lib/http.js b/lib/http.js index 6835789836d66b..9e99048a0b6504 100644 --- a/lib/http.js +++ b/lib/http.js @@ -52,6 +52,7 @@ let maxHeaderSize; * ServerResponse?: ServerResponse; * insecureHTTPParser?: boolean; * maxHeaderSize?: number; + * requireHostHeader?: boolean * }} [opts] * @param {Function} [requestListener] * @returns {Server} diff --git a/test/parallel/test-http-chunked-304.js b/test/parallel/test-http-chunked-304.js index b94d776595f89d..8328642fc737c5 100644 --- a/test/parallel/test-http-chunked-304.js +++ b/test/parallel/test-http-chunked-304.js @@ -47,7 +47,7 @@ function test(statusCode) { const conn = net.createConnection( server.address().port, common.mustCall(() => { - conn.write('GET / HTTP/1.1\r\n\r\n'); + conn.write('GET / HTTP/1.1\r\nHost: example.com\r\n\r\n'); let resp = ''; conn.setEncoding('utf8'); diff --git a/test/parallel/test-http-client-headers-array.js b/test/parallel/test-http-client-headers-array.js index d7e8d39c3c2560..4b78256bcaf8e2 100644 --- a/test/parallel/test-http-client-headers-array.js +++ b/test/parallel/test-http-client-headers-array.js @@ -10,7 +10,8 @@ function execute(options) { const expectHeaders = { 'x-foo': 'boom', 'cookie': 'a=1; b=2; c=3', - 'connection': 'keep-alive' + 'connection': 'keep-alive', + 'host': 'example.com', }; // no Host header when you set headers an array @@ -43,13 +44,20 @@ function execute(options) { // Should be the same except for implicit Host header on the first two execute({ headers: { 'x-foo': 'boom', 'cookie': 'a=1; b=2; c=3' } }); execute({ headers: { 'x-foo': 'boom', 'cookie': [ 'a=1', 'b=2', 'c=3' ] } }); -execute({ headers: [[ 'x-foo', 'boom' ], [ 'cookie', 'a=1; b=2; c=3' ]] }); execute({ headers: [ - [ 'x-foo', 'boom' ], [ 'cookie', [ 'a=1', 'b=2', 'c=3' ]], + [ 'x-foo', 'boom' ], + [ 'cookie', 'a=1; b=2; c=3' ], + [ 'Host', 'example.com' ], +] }); +execute({ headers: [ + [ 'x-foo', 'boom' ], + [ 'cookie', [ 'a=1', 'b=2', 'c=3' ]], + [ 'Host', 'example.com' ], ] }); execute({ headers: [ [ 'x-foo', 'boom' ], [ 'cookie', 'a=1' ], - [ 'cookie', 'b=2' ], [ 'cookie', 'c=3'], + [ 'cookie', 'b=2' ], [ 'cookie', 'c=3' ], + [ 'Host', 'example.com'], ] }); // Authorization and Host header both missing from the second @@ -58,4 +66,5 @@ execute({ auth: 'foo:bar', headers: execute({ auth: 'foo:bar', headers: [ [ 'x-foo', 'boom' ], [ 'cookie', 'a=1' ], [ 'cookie', 'b=2' ], [ 'cookie', 'c=3'], + [ 'Host', 'example.com'], ] }); diff --git a/test/parallel/test-http-content-length.js b/test/parallel/test-http-content-length.js index 193ee5a8831e60..eca32894f573a9 100644 --- a/test/parallel/test-http-content-length.js +++ b/test/parallel/test-http-content-length.js @@ -28,15 +28,18 @@ const server = http.createServer(function(req, res) { switch (req.url.substr(1)) { case 'multiple-writes': + delete req.headers.host; assert.deepStrictEqual(req.headers, expectedHeadersMultipleWrites); res.write('hello'); res.end('world'); break; case 'end-with-data': + delete req.headers.host; assert.deepStrictEqual(req.headers, expectedHeadersEndWithData); res.end('hello world'); break; case 'empty': + delete req.headers.host; assert.deepStrictEqual(req.headers, expectedHeadersEndNoData); res.end(); break; @@ -56,7 +59,6 @@ server.listen(0, function() { path: '/multiple-writes' }); req.removeHeader('Date'); - req.removeHeader('Host'); req.write('hello '); req.end('world'); req.on('response', function(res) { @@ -70,7 +72,6 @@ server.listen(0, function() { path: '/end-with-data' }); req.removeHeader('Date'); - req.removeHeader('Host'); req.end('hello world'); req.on('response', function(res) { assert.deepStrictEqual(res.headers, { ...expectedHeadersEndWithData, 'keep-alive': 'timeout=1' }); @@ -83,7 +84,6 @@ server.listen(0, function() { path: '/empty' }); req.removeHeader('Date'); - req.removeHeader('Host'); req.end(); req.on('response', function(res) { assert.deepStrictEqual(res.headers, { ...expectedHeadersEndNoData, 'keep-alive': 'timeout=1' }); diff --git a/test/parallel/test-http-header-badrequest.js b/test/parallel/test-http-header-badrequest.js index 8294ca9fe208ec..1e6fb6e3216499 100644 --- a/test/parallel/test-http-header-badrequest.js +++ b/test/parallel/test-http-header-badrequest.js @@ -17,7 +17,7 @@ server.listen(0, mustCall(() => { let received = ''; c.on('connect', mustCall(() => { - c.write('GET /blah HTTP/1.1\r\n\r\n'); + c.write('GET /blah HTTP/1.1\r\nHost: example.com\r\n\r\n'); })); c.on('data', mustCall((data) => { received += data.toString(); diff --git a/test/parallel/test-http-insecure-parser-per-stream.js b/test/parallel/test-http-insecure-parser-per-stream.js index 2ba245c8f419b1..daee5811724eb6 100644 --- a/test/parallel/test-http-insecure-parser-per-stream.js +++ b/test/parallel/test-http-insecure-parser-per-stream.js @@ -22,6 +22,7 @@ const MakeDuplexPair = require('../common/duplexpair'); serverSide.resume(); // Dump the request serverSide.end('HTTP/1.1 200 OK\r\n' + + 'Host: example.com\r\n' + 'Hello: foo\x08foo\r\n' + 'Content-Length: 0\r\n' + '\r\n\r\n'); @@ -39,6 +40,7 @@ const MakeDuplexPair = require('../common/duplexpair'); serverSide.resume(); // Dump the request serverSide.end('HTTP/1.1 200 OK\r\n' + + 'Host: example.com\r\n' + 'Hello: foo\x08foo\r\n' + 'Content-Length: 0\r\n' + '\r\n\r\n'); @@ -62,6 +64,7 @@ const MakeDuplexPair = require('../common/duplexpair'); server.emit('connection', serverSide); clientSide.write('GET / HTTP/1.1\r\n' + + 'Host: example.com\r\n' + 'Hello: foo\x08foo\r\n' + '\r\n\r\n'); } @@ -77,6 +80,7 @@ const MakeDuplexPair = require('../common/duplexpair'); server.emit('connection', serverSide); clientSide.write('GET / HTTP/1.1\r\n' + + 'Host: example.com\r\n' + 'Hello: foo\x08foo\r\n' + '\r\n\r\n'); } diff --git a/test/parallel/test-http-insecure-parser.js b/test/parallel/test-http-insecure-parser.js index c9a3aa23c142d9..7fad29f3eec4ba 100644 --- a/test/parallel/test-http-insecure-parser.js +++ b/test/parallel/test-http-insecure-parser.js @@ -19,6 +19,7 @@ server.listen(0, common.mustCall(function() { client.write( 'GET / HTTP/1.1\r\n' + 'Content-Type: text/te\x08t\r\n' + + 'Host: example.com' + 'Connection: close\r\n\r\n'); } ); diff --git a/test/parallel/test-http-keep-alive-drop-requests.js b/test/parallel/test-http-keep-alive-drop-requests.js index 2a4702d631e5f6..a69497a0c1a010 100644 --- a/test/parallel/test-http-keep-alive-drop-requests.js +++ b/test/parallel/test-http-keep-alive-drop-requests.js @@ -8,6 +8,7 @@ const assert = require('assert'); function request(socket) { socket.write('GET / HTTP/1.1\r\n'); socket.write('Connection: keep-alive\r\n'); + socket.write('Host: localhost\r\n'); socket.write('\r\n\r\n'); } diff --git a/test/parallel/test-http-keep-alive-max-requests.js b/test/parallel/test-http-keep-alive-max-requests.js index 160891e500e46a..0516a06da651d7 100644 --- a/test/parallel/test-http-keep-alive-max-requests.js +++ b/test/parallel/test-http-keep-alive-max-requests.js @@ -24,12 +24,14 @@ function writeRequest(socket, withBody) { socket.write('POST / HTTP/1.1\r\n'); socket.write('Connection: keep-alive\r\n'); socket.write('Content-Type: text/plain\r\n'); + socket.write('Host: localhost\r\n'); socket.write(`Content-Length: ${bodySent.length}\r\n\r\n`); socket.write(`${bodySent}\r\n`); socket.write('\r\n\r\n'); } else { socket.write('GET / HTTP/1.1\r\n'); socket.write('Connection: keep-alive\r\n'); + socket.write('Host: localhost\r\n'); socket.write('\r\n\r\n'); } } diff --git a/test/parallel/test-http-keep-alive-pipeline-max-requests.js b/test/parallel/test-http-keep-alive-pipeline-max-requests.js index 5549440d3dd5ae..6a07eb2638c86f 100644 --- a/test/parallel/test-http-keep-alive-pipeline-max-requests.js +++ b/test/parallel/test-http-keep-alive-pipeline-max-requests.js @@ -21,6 +21,7 @@ function assertResponse(headers, body, expectClosed) { function writeRequest(socket) { socket.write('POST / HTTP/1.1\r\n'); + socket.write('Host: localhost\r\n'); socket.write('Connection: keep-alive\r\n'); socket.write('Content-Type: text/plain\r\n'); socket.write(`Content-Length: ${bodySent.length}\r\n\r\n`); diff --git a/test/parallel/test-http-malformed-request.js b/test/parallel/test-http-malformed-request.js index 781c629bfacd17..1f2fecc11750be 100644 --- a/test/parallel/test-http-malformed-request.js +++ b/test/parallel/test-http-malformed-request.js @@ -41,7 +41,7 @@ server.listen(0); server.on('listening', function() { const c = net.createConnection(this.address().port); c.on('connect', function() { - c.write('GET /hello?foo=%99bar HTTP/1.1\r\n\r\n'); + c.write('GET /hello?foo=%99bar HTTP/1.1\r\nHost: example.com\r\n\r\n'); c.end(); }); }); diff --git a/test/parallel/test-http-max-header-size-per-stream.js b/test/parallel/test-http-max-header-size-per-stream.js index 5edb8d3a954cef..c043fce21a8425 100644 --- a/test/parallel/test-http-max-header-size-per-stream.js +++ b/test/parallel/test-http-max-header-size-per-stream.js @@ -62,6 +62,7 @@ const MakeDuplexPair = require('../common/duplexpair'); server.emit('connection', serverSide); clientSide.write('GET / HTTP/1.1\r\n' + + 'Host: example.com\r\n' + 'Hello: ' + 'A'.repeat(http.maxHeaderSize * 3) + '\r\n' + '\r\n\r\n'); } diff --git a/test/parallel/test-http-max-headers-count.js b/test/parallel/test-http-max-headers-count.js index 94685b228845aa..27bb1a1c3c04e8 100644 --- a/test/parallel/test-http-max-headers-count.js +++ b/test/parallel/test-http-max-headers-count.js @@ -27,7 +27,9 @@ const http = require('http'); let requests = 0; let responses = 0; -const headers = {}; +const headers = { + host: 'example.com' +}; const N = 100; for (let i = 0; i < N; ++i) { headers[`key${i}`] = i; @@ -56,8 +58,8 @@ server.maxHeadersCount = max; server.listen(0, function() { const maxAndExpected = [ // for client [20, 20], - [1200, 103], - [0, N + 3], // Connection, Date and Transfer-Encoding + [1200, 104], + [0, N + 4], // Host and Connection ]; doRequest(); diff --git a/test/parallel/test-http-pipeline-assertionerror-finish.js b/test/parallel/test-http-pipeline-assertionerror-finish.js index c82161bf00e28c..7721cb7fea3b75 100644 --- a/test/parallel/test-http-pipeline-assertionerror-finish.js +++ b/test/parallel/test-http-pipeline-assertionerror-finish.js @@ -27,7 +27,7 @@ const server = http .listen(0, function() { const s = net.connect(this.address().port); - const big = 'GET / HTTP/1.1\r\n\r\n'.repeat(COUNT); + const big = 'GET / HTTP/1.1\r\nHost: example.com\r\n\r\n'.repeat(COUNT); s.write(big); s.resume(); diff --git a/test/parallel/test-http-pipeline-requests-connection-leak.js b/test/parallel/test-http-pipeline-requests-connection-leak.js index aa5db56f77862b..cfbcef82b2c01c 100644 --- a/test/parallel/test-http-pipeline-requests-connection-leak.js +++ b/test/parallel/test-http-pipeline-requests-connection-leak.js @@ -26,7 +26,7 @@ const server = http }); }) .listen(0, function() { - const req = 'GET / HTTP/1.1\r\n\r\n'.repeat(COUNT); + const req = 'GET / HTTP/1.1\r\nHost: example.com\r\n\r\n'.repeat(COUNT); client = net.connect(this.address().port, function() { client.write(req); }); diff --git a/test/parallel/test-http-pipeline-socket-parser-typeerror.js b/test/parallel/test-http-pipeline-socket-parser-typeerror.js index 8987b822c26496..e092154b971f0a 100644 --- a/test/parallel/test-http-pipeline-socket-parser-typeerror.js +++ b/test/parallel/test-http-pipeline-socket-parser-typeerror.js @@ -50,7 +50,7 @@ const server = http .listen(0, () => { const s = net.connect(server.address().port); more = () => { - s.write('GET / HTTP/1.1\r\n\r\n'); + s.write('GET / HTTP/1.1\r\nHost: example.com\r\n\r\n'); }; done = () => { s.write( diff --git a/test/parallel/test-http-req-close-robust-from-tampering.js b/test/parallel/test-http-req-close-robust-from-tampering.js index 46ae0c0e297158..edfdb309a7e488 100644 --- a/test/parallel/test-http-req-close-robust-from-tampering.js +++ b/test/parallel/test-http-req-close-robust-from-tampering.js @@ -17,6 +17,7 @@ server.listen(0, common.mustCall(() => { const req = [ 'POST / HTTP/1.1', + 'Host: example.com', 'Content-Length: 11', '', 'hello world', diff --git a/test/parallel/test-http-request-host-header.js b/test/parallel/test-http-request-host-header.js new file mode 100644 index 00000000000000..1a66ccfc6fc013 --- /dev/null +++ b/test/parallel/test-http-request-host-header.js @@ -0,0 +1,41 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const http = require('http'); + +{ + const server = http.createServer(common.mustNotCall((req, res) => { + res.writeHead(200); + res.end(); + })); + + // From RFC 7230 5.4 https://datatracker.ietf.org/doc/html/rfc7230#section-5.4 + // A server MUST respond with a 400 (Bad Request) status code to any + // HTTP/1.1 request message that lacks a Host header field + server.listen(0, common.mustCall(() => { + http.get({ port: server.address().port, headers: [] }, (res) => { + assert.strictEqual(res.statusCode, 400); + assert.strictEqual(res.headers.connection, 'close'); + res.resume().on('end', common.mustCall(() => { + server.close(); + })); + }); + })); +} + +{ + const server = http.createServer({ requireHostHeader: false }, common.mustCall((req, res) => { + res.writeHead(200, ['test', '1']); + res.end(); + })); + + server.listen(0, common.mustCall(() => { + http.get({ port: server.address().port, headers: [] }, (res) => { + assert.strictEqual(res.statusCode, 200); + assert.strictEqual(res.headers.test, '1'); + res.resume().on('end', common.mustCall(() => { + server.close(); + })); + }); + })); +} diff --git a/test/parallel/test-http-response-splitting.js b/test/parallel/test-http-response-splitting.js index 88f94e6658b174..25d8348dd9a78d 100644 --- a/test/parallel/test-http-response-splitting.js +++ b/test/parallel/test-http-response-splitting.js @@ -53,7 +53,7 @@ const server = http.createServer((req, res) => { res.end('ok'); }); server.listen(0, () => { - const end = 'HTTP/1.1\r\n\r\n'; + const end = 'HTTP/1.1\r\nHost: example.com\r\n\r\n'; const client = net.connect({ port: server.address().port }, () => { client.write(`GET ${str} ${end}`); client.write(`GET / ${end}`); diff --git a/test/parallel/test-http-server-close-all.js b/test/parallel/test-http-server-close-all.js index c4c211d97979a0..7d4561dbe2be14 100644 --- a/test/parallel/test-http-server-close-all.js +++ b/test/parallel/test-http-server-close-all.js @@ -50,7 +50,7 @@ server.listen(0, function() { client2.on('close', common.mustCall()); - client2.write('GET / HTTP/1.1\r\n\r\n'); + client2.write('GET / HTTP/1.1\r\nHost: example.com\r\n\r\n'); })); client1.on('close', common.mustCall()); diff --git a/test/parallel/test-http-server-close-idle.js b/test/parallel/test-http-server-close-idle.js index 361ccf990fabcc..af99d1b42c20ea 100644 --- a/test/parallel/test-http-server-close-idle.js +++ b/test/parallel/test-http-server-close-idle.js @@ -60,7 +60,7 @@ server.listen(0, function() { client2Closed = true; })); - client2.write('GET / HTTP/1.1\r\n\r\n'); + client2.write('GET / HTTP/1.1\r\nHost: example.com\r\n\r\n'); })); client1.on('close', common.mustCall(() => { diff --git a/test/parallel/test-http-server-headers-timeout-keepalive.js b/test/parallel/test-http-server-headers-timeout-keepalive.js index 32c9aec071e815..493c730cb7a9b1 100644 --- a/test/parallel/test-http-server-headers-timeout-keepalive.js +++ b/test/parallel/test-http-server-headers-timeout-keepalive.js @@ -12,7 +12,7 @@ const { connect } = require('net'); function performRequestWithDelay(client, firstDelay, secondDelay, closeAfter) { client.resume(); - client.write('GET / HTTP/1.1\r\n'); + client.write('GET / HTTP/1.1\r\nHost: example.com\r\n'); setTimeout(() => { client.write('Connection: '); diff --git a/test/parallel/test-http-server-headers-timeout-pipelining.js b/test/parallel/test-http-server-headers-timeout-pipelining.js index d0329a95cb19d4..7e6c6626fafc2e 100644 --- a/test/parallel/test-http-server-headers-timeout-pipelining.js +++ b/test/parallel/test-http-server-headers-timeout-pipelining.js @@ -66,7 +66,8 @@ server.listen(0, common.mustCall(() => { // Send two requests using pipelining. Delay before finishing the second one client.resume(); - client.write('GET / HTTP/1.1\r\nConnection: keep-alive\r\n\r\nGET / HTTP/1.1\r\nConnection: '); + client.write('GET / HTTP/1.1\r\nHost: localhost\r\nConnection: keep-alive\r\n\r\n' + + 'GET / HTTP/1.1\r\nHost: localhost\r\nConnection: '); // Complete the request setTimeout(() => { diff --git a/test/parallel/test-http-server-keep-alive-defaults.js b/test/parallel/test-http-server-keep-alive-defaults.js index 6f3abc30b573a2..7efebd7862857f 100644 --- a/test/parallel/test-http-server-keep-alive-defaults.js +++ b/test/parallel/test-http-server-keep-alive-defaults.js @@ -16,6 +16,7 @@ function assertResponse(headers, body, expectClosed) { function writeRequest(socket) { socket.write('POST / HTTP/1.1\r\n'); socket.write('Connection: keep-alive\r\n'); + socket.write('Host: localhost\r\n'); socket.write('Content-Type: text/plain\r\n'); socket.write(`Content-Length: ${bodySent.length}\r\n\r\n`); socket.write(`${bodySent}\r\n`); diff --git a/test/parallel/test-http-server-keep-alive-max-requests-null.js b/test/parallel/test-http-server-keep-alive-max-requests-null.js index fee882be856290..0b5acfe4dc087d 100644 --- a/test/parallel/test-http-server-keep-alive-max-requests-null.js +++ b/test/parallel/test-http-server-keep-alive-max-requests-null.js @@ -16,6 +16,7 @@ function assertResponse(headers, body, expectClosed) { function writeRequest(socket) { socket.write('POST / HTTP/1.1\r\n'); socket.write('Connection: keep-alive\r\n'); + socket.write('Host: localhost\r\n'); socket.write('Content-Type: text/plain\r\n'); socket.write(`Content-Length: ${bodySent.length}\r\n\r\n`); socket.write(`${bodySent}\r\n`); diff --git a/test/parallel/test-http-server-request-timeout-delayed-body.js b/test/parallel/test-http-server-request-timeout-delayed-body.js index ac2120ef393719..fdfbbb2f4cb4e8 100644 --- a/test/parallel/test-http-server-request-timeout-delayed-body.js +++ b/test/parallel/test-http-server-request-timeout-delayed-body.js @@ -47,6 +47,7 @@ server.listen(0, common.mustCall(() => { client.resume(); client.write('POST / HTTP/1.1\r\n'); + client.write('Host: example.com\r\n'); client.write('Content-Length: 20\r\n'); client.write('Connection: close\r\n'); client.write('\r\n'); diff --git a/test/parallel/test-http-server-request-timeout-interrupted-body.js b/test/parallel/test-http-server-request-timeout-interrupted-body.js index aa4843a48373df..82c2f3171736a6 100644 --- a/test/parallel/test-http-server-request-timeout-interrupted-body.js +++ b/test/parallel/test-http-server-request-timeout-interrupted-body.js @@ -58,6 +58,7 @@ server.listen(0, common.mustCall(() => { client.resume(); client.write('POST / HTTP/1.1\r\n'); + client.write('Host: example.com\r\n'); client.write('Content-Length: 20\r\n'); client.write('Connection: close\r\n'); client.write('\r\n'); diff --git a/test/parallel/test-http-server-request-timeout-keepalive.js b/test/parallel/test-http-server-request-timeout-keepalive.js index a3f9bccc8deaa5..bc7384b5341164 100644 --- a/test/parallel/test-http-server-request-timeout-keepalive.js +++ b/test/parallel/test-http-server-request-timeout-keepalive.js @@ -12,7 +12,7 @@ const { connect } = require('net'); function performRequestWithDelay(client, firstDelay, secondDelay, closeAfter) { client.resume(); - client.write('GET / HTTP/1.1\r\n'); + client.write('GET / HTTP/1.1\r\nHost: example.com\r\n'); setTimeout(() => { client.write('Connection: '); diff --git a/test/parallel/test-http-server-request-timeout-pipelining.js b/test/parallel/test-http-server-request-timeout-pipelining.js index 0c7e87160fefc5..30b8875bc774f8 100644 --- a/test/parallel/test-http-server-request-timeout-pipelining.js +++ b/test/parallel/test-http-server-request-timeout-pipelining.js @@ -60,7 +60,8 @@ server.listen(0, common.mustCall(() => { // Send two requests using pipelining. Delay before finishing the second one client.resume(); - client.write('GET / HTTP/1.1\r\nConnection: keep-alive\r\n\r\nGET / HTTP/1.1\r\nConnection: '); + client.write('GET / HTTP/1.1\r\nHost: localhost\r\nConnection: keep-alive\r\n\r\n' + + 'GET / HTTP/1.1\r\nHost: localhost\r\nConnection: '); // Complete the request setTimeout(() => { diff --git a/test/parallel/test-http-server-request-timeouts-mixed.js b/test/parallel/test-http-server-request-timeouts-mixed.js index 918aa159b6b386..ec3cce9161151b 100644 --- a/test/parallel/test-http-server-request-timeouts-mixed.js +++ b/test/parallel/test-http-server-request-timeouts-mixed.js @@ -7,7 +7,7 @@ const { connect } = require('net'); // This test validates that request are correct checked for both requests and headers timeout in various situations. -const requestBodyPart1 = 'POST / HTTP/1.1\r\nContent-Length: 20\r\n'; +const requestBodyPart1 = 'POST / HTTP/1.1\r\nHost: localhost\r\nContent-Length: 20\r\n'; const requestBodyPart2 = 'Connection: close\r\n\r\n1234567890'; const requestBodyPart3 = '1234567890'; diff --git a/test/parallel/test-http-server-unconsume.js b/test/parallel/test-http-server-unconsume.js index a8a307e53b5a30..e19fd8b3875aad 100644 --- a/test/parallel/test-http-server-unconsume.js +++ b/test/parallel/test-http-server-unconsume.js @@ -18,7 +18,7 @@ const net = require('net'); server.close(); }).listen(0, function() { const socket = net.connect(this.address().port, function() { - socket.write('PUT / HTTP/1.1\r\n\r\n'); + socket.write('PUT / HTTP/1.1\r\nHost: example.com\r\n\r\n'); socket.once('data', function() { socket.end('hello world'); diff --git a/test/parallel/test-http-server.js b/test/parallel/test-http-server.js index fcbb8cd4b9178b..a26912c409a24c 100644 --- a/test/parallel/test-http-server.js +++ b/test/parallel/test-http-server.js @@ -89,7 +89,9 @@ server.on('listening', function() { c.setEncoding('utf8'); c.on('connect', function() { - c.write('GET /hello?hello=world&foo=b==ar HTTP/1.1\r\n\r\n'); + c.write( + 'GET /hello?hello=world&foo=b==ar HTTP/1.1\r\n' + + 'Host: example.com\r\n\r\n'); requests_sent += 1; }); @@ -97,13 +99,16 @@ server.on('listening', function() { server_response += chunk; if (requests_sent === 1) { - c.write('POST /quit HTTP/1.1\r\n\r\n'); + c.write( + 'POST /quit HTTP/1.1\r\n' + + 'Host: example.com\r\n\r\n' + ); requests_sent += 1; } if (requests_sent === 2) { - c.write('GET / HTTP/1.1\r\nX-X: foo\r\n\r\n' + - 'GET / HTTP/1.1\r\nX-X: bar\r\n\r\n'); + c.write('GET / HTTP/1.1\r\nX-X: foo\r\nHost: example.com\r\n\r\n' + + 'GET / HTTP/1.1\r\nX-X: bar\r\nHost: example.com\r\n\r\n'); // Note: we are making the connection half-closed here // before we've gotten the response from the server. This // is a pretty bad thing to do and not really supported diff --git a/test/parallel/test-http-set-trailers.js b/test/parallel/test-http-set-trailers.js index 17a936f528e96f..26b6c275588ddd 100644 --- a/test/parallel/test-http-set-trailers.js +++ b/test/parallel/test-http-set-trailers.js @@ -59,7 +59,7 @@ function testHttp11(port, callback) { let tid; c.on('connect', function() { - c.write('GET / HTTP/1.1\r\n\r\n'); + c.write('GET / HTTP/1.1\r\nHost: example.com\r\n\r\n'); tid = setTimeout(common.mustNotCall(), 2000, 'Couldn\'t find last chunk.'); }); diff --git a/test/parallel/test-http-status-message.js b/test/parallel/test-http-status-message.js index 29b31a35a5708a..bdb667ca4448d1 100644 --- a/test/parallel/test-http-status-message.js +++ b/test/parallel/test-http-status-message.js @@ -38,7 +38,10 @@ function test() { const client = net.connect( this.address().port, function() { - client.write('GET / HTTP/1.1\r\nConnection: close\r\n\r\n'); + client.write( + 'GET / HTTP/1.1\r\n' + + 'Host: example.com\r\n' + + 'Connection: close\r\n\r\n'); } ); client.on('data', function(chunk) { diff --git a/test/parallel/test-http-upgrade-server.js b/test/parallel/test-http-upgrade-server.js index 5a660c4072a9a3..b04d488b88a4ef 100644 --- a/test/parallel/test-http-upgrade-server.js +++ b/test/parallel/test-http-upgrade-server.js @@ -87,6 +87,7 @@ function test_upgrade_with_listener() { conn.on('connect', function() { writeReq(conn, 'GET / HTTP/1.1\r\n' + + 'Host: example.com\r\n' + 'Upgrade: WebSocket\r\n' + 'Connection: Upgrade\r\n' + '\r\n' + @@ -124,6 +125,7 @@ function test_upgrade_no_listener() { conn.on('connect', function() { writeReq(conn, 'GET / HTTP/1.1\r\n' + + 'Host: example.com\r\n' + 'Upgrade: WebSocket\r\n' + 'Connection: Upgrade\r\n' + '\r\n'); @@ -146,7 +148,7 @@ function test_standard_http() { conn.setEncoding('utf8'); conn.on('connect', function() { - writeReq(conn, 'GET / HTTP/1.1\r\n\r\n'); + writeReq(conn, 'GET / HTTP/1.1\r\nHost: example.com\r\n\r\n'); }); conn.once('data', function(data) { diff --git a/test/parallel/test-http.js b/test/parallel/test-http.js index 1d5b74b879750b..366fb42d1569d9 100644 --- a/test/parallel/test-http.js +++ b/test/parallel/test-http.js @@ -113,7 +113,9 @@ server.on('listening', () => { path: '/world', headers: [ ['Cookie', 'abc=123'], ['Cookie', 'def=456'], - ['Cookie', 'ghi=789'] ], + ['Cookie', 'ghi=789'], + ['Host', 'example.com'], + ], agent: agent }, common.mustCall((res) => { const cookieHeaders = req._header.match(/^Cookie: .+$/img); diff --git a/test/parallel/test-https-agent-create-connection.js b/test/parallel/test-https-agent-create-connection.js index 1ac2c840b0d5e2..c053b7f24b809e 100644 --- a/test/parallel/test-https-agent-create-connection.js +++ b/test/parallel/test-https-agent-create-connection.js @@ -22,7 +22,7 @@ const expectCertError = /^Error: unable to verify the first certificate$/; const checkRequest = (socket, server) => { let result = ''; socket.on('connect', common.mustCall((data) => { - socket.write('GET / HTTP/1.1\r\n\r\n'); + socket.write('GET / HTTP/1.1\r\nHost: example.com\r\n\r\n'); socket.end(); })); socket.on('data', common.mustCall((chunk) => { diff --git a/test/parallel/test-https-host-headers.js b/test/parallel/test-https-host-headers.js index b8dcda320fddc5..326294293018b3 100644 --- a/test/parallel/test-https-host-headers.js +++ b/test/parallel/test-https-host-headers.js @@ -25,7 +25,7 @@ const httpsServer = https.createServer({ } res.writeHead(200, {}); res.end('ok'); -}, 9)).listen(0, common.mustCall(function(err) { +}, 6)).listen(0, common.mustCall(function(err) { debug(`test https server listening on port ${this.address().port}`); assert.ifError(err); https.get({ diff --git a/test/parallel/test-https-insecure-parse-per-stream.js b/test/parallel/test-https-insecure-parse-per-stream.js index 645fbcf2637654..73e69d056913aa 100644 --- a/test/parallel/test-https-insecure-parse-per-stream.js +++ b/test/parallel/test-https-insecure-parse-per-stream.js @@ -37,6 +37,7 @@ const certFixture = { serverSide.resume(); // Dump the request serverSide.end('HTTP/1.1 200 OK\r\n' + + 'Host: example.com\r\n' + 'Hello: foo\x08foo\r\n' + 'Content-Length: 0\r\n' + '\r\n\r\n'); @@ -55,6 +56,7 @@ const certFixture = { serverSide.resume(); // Dump the request serverSide.end('HTTP/1.1 200 OK\r\n' + + 'Host: example.com\r\n' + 'Hello: foo\x08foo\r\n' + 'Content-Length: 0\r\n' + '\r\n\r\n'); @@ -81,6 +83,7 @@ const certFixture = { }); client.write( 'GET / HTTP/1.1\r\n' + + 'Host: example.com\r\n' + 'Hello: foo\x08foo\r\n' + '\r\n\r\n'); client.end(); @@ -107,6 +110,7 @@ const certFixture = { }); client.write( 'GET / HTTP/1.1\r\n' + + 'Host: example.com\r\n' + 'Hello: foo\x08foo\r\n' + '\r\n\r\n'); client.end(); diff --git a/test/parallel/test-https-keep-alive-drop-requests.js b/test/parallel/test-https-keep-alive-drop-requests.js index d2c7f78e0bff73..78ee0c199a8abb 100644 --- a/test/parallel/test-https-keep-alive-drop-requests.js +++ b/test/parallel/test-https-keep-alive-drop-requests.js @@ -13,7 +13,7 @@ const tls = require('tls'); const { readKey } = require('../common/fixtures'); function request(socket) { - socket.write('GET / HTTP/1.1\r\nConnection: keep-alive\r\n\r\n\r\n'); + socket.write('GET / HTTP/1.1\r\nHost: localhost\r\nConnection: keep-alive\r\n\r\n\r\n'); } // https options diff --git a/test/parallel/test-https-max-header-size-per-stream.js b/test/parallel/test-https-max-header-size-per-stream.js index 796af5e6e08793..f10fced777c2f4 100644 --- a/test/parallel/test-https-max-header-size-per-stream.js +++ b/test/parallel/test-https-max-header-size-per-stream.js @@ -38,6 +38,7 @@ const certFixture = { serverSide.resume(); // Dump the request serverSide.end('HTTP/1.1 200 OK\r\n' + + 'Host: example.com\r\n' + 'Hello: ' + 'A'.repeat(http.maxHeaderSize * 3) + '\r\n' + 'Content-Length: 0\r\n' + '\r\n\r\n'); @@ -55,6 +56,7 @@ const certFixture = { serverSide.resume(); // Dump the request serverSide.end('HTTP/1.1 200 OK\r\n' + + 'Host: example.com\r\n' + 'Hello: ' + 'A'.repeat(http.maxHeaderSize * 3) + '\r\n' + 'Content-Length: 0\r\n' + '\r\n\r\n'); @@ -81,6 +83,7 @@ const certFixture = { }); client.write( 'GET / HTTP/1.1\r\n' + + 'Host: example.com\r\n' + 'Hello: ' + 'A'.repeat(http.maxHeaderSize * 3) + '\r\n' + '\r\n\r\n'); client.end(); @@ -107,6 +110,7 @@ const certFixture = { }); client.write( 'GET / HTTP/1.1\r\n' + + 'Host: example.com\r\n' + 'Hello: ' + 'A'.repeat(http.maxHeaderSize * 3) + '\r\n' + '\r\n\r\n'); client.end(); diff --git a/test/parallel/test-https-max-headers-count.js b/test/parallel/test-https-max-headers-count.js index 0fdd38c73ed6f1..6b188b0780eb7c 100644 --- a/test/parallel/test-https-max-headers-count.js +++ b/test/parallel/test-https-max-headers-count.js @@ -16,7 +16,9 @@ const serverOptions = { let requests = 0; let responses = 0; -const headers = {}; +const headers = { + host: 'example.com' +}; const N = 100; for (let i = 0; i < N; ++i) { headers[`key${i}`] = i; @@ -45,8 +47,8 @@ server.maxHeadersCount = max; server.listen(0, common.mustCall(() => { const maxAndExpected = [ // for client [20, 20], - [1200, 103], - [0, N + 3], // Connection, Date and Transfer-Encoding + [1200, 104], + [0, N + 4], // Host and Connection ]; const doRequest = common.mustCall(() => { const max = maxAndExpected[responses][0]; diff --git a/test/parallel/test-https-server-close-all.js b/test/parallel/test-https-server-close-all.js index 1c9092ff5c9237..170d95db8f919e 100644 --- a/test/parallel/test-https-server-close-all.js +++ b/test/parallel/test-https-server-close-all.js @@ -60,7 +60,7 @@ server.listen(0, function() { client2.on('close', common.mustCall()); - client2.write('GET / HTTP/1.1\r\n\r\n'); + client2.write('GET / HTTP/1.1\r\nHost: example.com\r\n\r\n'); })); client1.on('close', common.mustCall()); diff --git a/test/parallel/test-https-server-close-idle.js b/test/parallel/test-https-server-close-idle.js index 7f093c47cd8609..62a01ac743f4b0 100644 --- a/test/parallel/test-https-server-close-idle.js +++ b/test/parallel/test-https-server-close-idle.js @@ -70,7 +70,7 @@ server.listen(0, function() { client2Closed = true; })); - client2.write('GET / HTTP/1.1\r\n\r\n'); + client2.write('GET / HTTP/1.1\r\nHost: localhost\r\n\r\n'); })); client1.on('close', common.mustCall(() => {