diff --git a/lib/core.js b/lib/core.js index 202f6dbe0..d44c577d6 100755 --- a/lib/core.js +++ b/lib/core.js @@ -44,7 +44,9 @@ const internals = { 'closing', 'stop' ], - badRequestResponse: Buffer.from('HTTP/1.1 400 Bad Request\r\n\r\n', 'ascii') + badRequestResponse: Buffer.from('HTTP/1.1 400 Bad Request\r\n\r\n', 'ascii'), + requestTimeoutResponse: Buffer.from('HTTP/1.1 408 Request Timeout\r\nConnection: close\r\n\r\n', 'ascii'), + clientTimeoutCodes: new Set(['ERR_HTTP_REQUEST_TIMEOUT', 'HPE_HEADER_TIMEOUT']) }; @@ -575,7 +577,7 @@ exports = module.exports = internals.Core = class { request._reply(error); } else { - socket.end(internals.badRequestResponse); + socket.end(internals.clientTimeoutCodes.has(err.code) ? internals.requestTimeoutResponse : internals.badRequestResponse); } } else { diff --git a/test/request.js b/test/request.js index d2f1760e8..dafc67d55 100755 --- a/test/request.js +++ b/test/request.js @@ -2369,6 +2369,46 @@ describe('Request', () => { await server.stop({ timeout: 1 }); }); + it('returns a request timeout when the client sends no headers', async () => { + + const listener = Http.createServer({ + connectionsCheckingInterval: 20, + headersTimeout: 50, + requestTimeout: 0 + }); + + const server = Hapi.server({ listener, routes: { timeout: { server: false } } }); + await server.start(); + + let responseCount = 0; + server.events.on('response', () => { + + responseCount += 1; + }); + + const client = Net.connect(server.info.port); + const clientEnded = new Promise((resolve, reject) => { + + let response = ''; + client.on('data', (chunk) => { + + response = response + chunk.toString(); + }); + + client.on('end', () => resolve(response)); + client.on('error', reject); + }); + + await new Promise((resolve) => client.on('connect', resolve)); + + const clientResponse = await clientEnded; + expect(clientResponse).to.contain('408 Request Timeout'); + expect(clientResponse).to.contain('Connection: close'); + expect(responseCount).to.equal(0); + + await server.stop({ timeout: 1 }); + }); + it('returns normal response when parser fails with bad method after request is setup', async () => { const server = Hapi.server({ routes: { timeout: { server: false } } });