-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Description
Prerequisites
- I have written a descriptive issue title
- I have searched existing issues to ensure the bug has not already been reported
Fastify version
4.15.0
Plugin version
No response
Node.js version
16.14.0
Operating system
macOS
Operating system version (i.e. 20.04, 11.3, 10)
Ventura 13.4
Description
When using reply.send() from an async handler, with an asynchronous onSend hook, it is possible that the hook can be called more than once per request.
Fastify still uses reply.request.raw.aborted in wrapThenable, which is not reliable since NodeJS v15.5.0: nodejs/node#41117
The comments in the code state that:
the request may be terminated during the reply. in this situation, it require an extra checking of request.aborted to see whether the request is killed by client.
However, since this flag is no longer reliable, the code will call reply.send twice, which will also trigger the onSend hook more than once.
Steps to Reproduce
import fastify from "fastify";
const sleep = (ms) => {
return new Promise((resolve) => setTimeout(resolve, ms));
};
const app = fastify({
logger: true,
disableRequestLogging: true,
});
app.decorateRequest('hasCalledHook', false);
app.addHook("onSend", async (request, reply) => {
await sleep(100);
if (request.hasCalledHook) {
request.log.error('Called hook twice!');
} else {
request.hasCalledHook = true;
}
});
app.post("/", async (request, reply) => {
await sleep(100);
await reply.send('test');
});
const start = async () => {
try {
await app.listen({ port: 3000 });
} catch (error) {
app.log.error(error);
process.exit(1);
}
};
start();Then call from autocannon and abort the request.
E.g.
autocannon -m POST -c 1 -d 0.1 http://localhost:3000/ -b {} -H Content-Type=application/json
Expected Behavior
The onSend hook should only be called a maximum of one time per request