From 33f7b3c35b3947c2a63b8811aff00f3e97850e42 Mon Sep 17 00:00:00 2001 From: Samy Alzahrani Date: Wed, 24 Aug 2022 16:40:27 +0300 Subject: [PATCH] fix: backport reused connection fix --- fastify.js | 4 ++-- test/request-error.test.js | 45 +++++++++++++++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/fastify.js b/fastify.js index 20451947bcc..48b2cbead1b 100644 --- a/fastify.js +++ b/fastify.js @@ -1,6 +1,6 @@ 'use strict' -const VERSION = '3.29.0' +const VERSION = '3.29.1' const Avvio = require('avvio') const http = require('http') @@ -584,7 +584,7 @@ function fastify (options) { // https://github.com/nodejs/node/blob/6ca23d7846cb47e84fd344543e394e50938540be/lib/_http_server.js#L666 // If the socket is not writable, there is no reason to try to send data. - if (socket.writable && socket.bytesWritten === 0) { + if (socket.writable) { socket.write(`HTTP/1.1 400 Bad Request\r\nContent-Length: ${body.length}\r\nContent-Type: application/json\r\n\r\n${body}`) } socket.destroy(err) diff --git a/test/request-error.test.js b/test/request-error.test.js index 33d8262aa54..022cc878966 100644 --- a/test/request-error.test.js +++ b/test/request-error.test.js @@ -153,7 +153,7 @@ test('default clientError handler ignores sockets in destroyed state', t => { }) test('default clientError handler destroys sockets in writable state', t => { - t.plan(1) + t.plan(2) const fastify = Fastify({ bodyLimit: 1, @@ -169,6 +169,9 @@ test('default clientError handler destroys sockets in writable state', t => { }, destroy () { t.pass('destroy should be called') + }, + write (response) { + t.match(response, /^HTTP\/1.1 400 Bad Request/) } }) }) @@ -189,6 +192,9 @@ test('default clientError handler destroys http sockets in non-writable state', }, destroy () { t.pass('destroy should be called') + }, + write (response) { + t.fail('write should not be called') } }) }) @@ -273,3 +279,40 @@ test('encapsulated error handler binding', t => { t.equal(fastify.hello, undefined) }) }) + +test('default clientError replies with bad request on reused keep-alive connection', t => { + t.plan(2) + + let response = '' + + const fastify = Fastify({ + bodyLimit: 1, + keepAliveTimeout: 100 + }) + + fastify.get('/', (request, reply) => { + reply.send('OK\n') + }) + + fastify.listen({ port: 0 }, function (err) { + t.error(err) + fastify.server.unref() + + const client = connect(fastify.server.address().port) + + client.on('data', chunk => { + response += chunk.toString('utf-8') + }) + + client.on('end', () => { + t.match(response, /^HTTP\/1.1 200 OK.*HTTP\/1.1 400 Bad Request/s) + }) + + client.resume() + client.write('GET / HTTP/1.1\r\n') + client.write('\r\n\r\n') + client.write('GET /?a b HTTP/1.1\r\n') + client.write('Connection: close\r\n') + client.write('\r\n\r\n') + }) +})