From 4d92fe73f65fa9ea75e1b4fa436e8e5e528b95fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gerg=C5=91=20Lengyel?= Date: Mon, 24 Jan 2022 14:46:55 +0100 Subject: [PATCH 1/7] feat: aborted request handling in reply.send --- lib/reply.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/reply.js b/lib/reply.js index bee18b3fa3..525c4d1583 100644 --- a/lib/reply.js +++ b/lib/reply.js @@ -116,6 +116,10 @@ Reply.prototype.send = function (payload) { return this } + if (this.request.raw && this.request.raw.aborted === true) { + return this + } + if (payload === undefined) { onSendHook(this, payload) return this From c16bf1b54adea536fee229f0fe9a92650da7bc18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gerg=C5=91=20Lengyel?= Date: Mon, 24 Jan 2022 14:48:00 +0100 Subject: [PATCH 2/7] feat (test): aborted request handling in reply.send --- test/internals/reply.test.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/internals/reply.test.js b/test/internals/reply.test.js index be99f61df6..974cdba5e0 100644 --- a/test/internals/reply.test.js +++ b/test/internals/reply.test.js @@ -121,6 +121,19 @@ test('reply.serializer should set a custom serializer', t => { t.equal(reply[kReplySerializer], 'serializer') }) +test('reply.send handles aborted requests', t => { + t.plan(1) + const response = { + setHeader: () => {}, + hasHeader: () => false, + getHeader: () => undefined, + writeHead: () => {}, + end: () => {} + } + const reply = new Reply(response, { raw: { aborted: true } }) + t.equal(reply.send('hello'), reply) +}) + test('reply.serializer should support running preSerialization hooks', t => { t.plan(3) const fastify = require('../..')() From 2893f8df69ff2c3f94c1d99ee11ccf000daedd79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gerg=C5=91=20Lengyel?= Date: Fri, 25 Feb 2022 13:23:42 +0100 Subject: [PATCH 3/7] Revert "feat (test): aborted request handling in reply.send" This reverts commit 3a628f5ce951b064454709370b0907b819fa2e18. --- test/internals/reply.test.js | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/test/internals/reply.test.js b/test/internals/reply.test.js index 974cdba5e0..be99f61df6 100644 --- a/test/internals/reply.test.js +++ b/test/internals/reply.test.js @@ -121,19 +121,6 @@ test('reply.serializer should set a custom serializer', t => { t.equal(reply[kReplySerializer], 'serializer') }) -test('reply.send handles aborted requests', t => { - t.plan(1) - const response = { - setHeader: () => {}, - hasHeader: () => false, - getHeader: () => undefined, - writeHead: () => {}, - end: () => {} - } - const reply = new Reply(response, { raw: { aborted: true } }) - t.equal(reply.send('hello'), reply) -}) - test('reply.serializer should support running preSerialization hooks', t => { t.plan(3) const fastify = require('../..')() From 8c885672656d3f0578a7ea23b46e90ac6e06014c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gerg=C5=91=20Lengyel?= Date: Fri, 25 Feb 2022 13:23:51 +0100 Subject: [PATCH 4/7] Revert "feat: aborted request handling in reply.send" This reverts commit 172c3ed608081520f7b67e98c5a119c194958589. --- lib/reply.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/reply.js b/lib/reply.js index 525c4d1583..bee18b3fa3 100644 --- a/lib/reply.js +++ b/lib/reply.js @@ -116,10 +116,6 @@ Reply.prototype.send = function (payload) { return this } - if (this.request.raw && this.request.raw.aborted === true) { - return this - } - if (payload === undefined) { onSendHook(this, payload) return this From a9a17f48a0450488ccb42393262d6253ba5bfb76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gerg=C5=91=20Lengyel?= Date: Fri, 25 Feb 2022 13:54:55 +0100 Subject: [PATCH 5/7] feat: handle stream errors from aborted requests --- lib/reply.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/reply.js b/lib/reply.js index bee18b3fa3..51bfc1b55e 100644 --- a/lib/reply.js +++ b/lib/reply.js @@ -457,7 +457,7 @@ function sendStream (payload, res, reply) { eos(payload, { readable: true, writable: false }, function (err) { sourceOpen = false if (err != null) { - if (res.headersSent) { + if (res.headersSent || reply.request.raw.aborted === true) { if (!errorLogged) { errorLogged = true logStreamError(reply.log, err, res) From 7ddde9c9c2fcc3ec8e88020b40845a86d3100a64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gerg=C5=91=20Lengyel?= Date: Fri, 25 Feb 2022 13:59:19 +0100 Subject: [PATCH 6/7] test: handle stream errors from aborted requests --- test/stream.test.js | 48 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/test/stream.test.js b/test/stream.test.js index 95f440ef02..363f9dd3d5 100644 --- a/test/stream.test.js +++ b/test/stream.test.js @@ -694,3 +694,51 @@ test('should mark reply as sent before pumping the payload stream into response fastify.close() }) }) + +test('reply.send handles aborted requests', t => { + t.plan(2) + + const spyLogger = { + level: 'error', + fatal: () => { }, + error: () => { + t.fail('should not log an error') + }, + warn: () => { }, + info: () => { }, + debug: () => { }, + trace: () => { }, + child: () => { return spyLogger } + } + const fastify = Fastify({ + logger: spyLogger + }) + + fastify.get('/', (req, reply) => { + setTimeout(() => { + const stream = new Readable({ + read: function () { + this.push(null) + } + }) + reply.send(stream) + }, 6) + }) + + fastify.listen(0, err => { + t.error(err) + fastify.server.unref() + + const port = fastify.server.address().port + const http = require('http') + const req = http.get(`http://localhost:${port}`) + .on('error', (err) => { + t.equal(err.code, 'ECONNRESET') + fastify.close() + }) + + setTimeout(() => { + req.abort() + }, 1) + }) +}) From 52a42a2d2e7c3a8ddd9661f19211152593dfbb06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gerg=C5=91=20Lengyel?= Date: Fri, 25 Feb 2022 15:07:59 +0100 Subject: [PATCH 7/7] fix: requested change of using the port parameter --- test/stream.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/stream.test.js b/test/stream.test.js index 363f9dd3d5..da36519d85 100644 --- a/test/stream.test.js +++ b/test/stream.test.js @@ -725,7 +725,7 @@ test('reply.send handles aborted requests', t => { }, 6) }) - fastify.listen(0, err => { + fastify.listen({ port: 0 }, err => { t.error(err) fastify.server.unref()