Reputation: 6445
How can my node.js Koa server detect and log that a client has disconnected before a response can be sent.
Normally the sequence is:
If the client disconnects after 2 is finished, but before 4 is complete, can node.js Koa detect and log this?
I have tested using this simple script and running curl from another terminal, then during the 10 second delay for node.js to sleep, I terminate (ctrl-c) the curl command.
const Koa = require('koa');
const app = new Koa();
/**
* synchronously delay/sleep/block for time ms
*/
const delay = time => new Promise(res=> {
console.log(`About to sleep for ${time} ms`)
setTimeout(res,time)
});
app.on('error', (err, ctx) => {
console.error('server error', err, ctx)
});
app.use(async ctx => {
ctx.req.on('close', () => {
console.log('Request closed');
});
console.log('Hello World Started')
await delay(10000)
console.log('Hello World Ended');
ctx.body = 'Hello World !!!';
});
app.listen(3000, () => console.log('running on port 3000'));
The
ctx.req.on('close'
event is emitted a single time in both cases:
I am using:
node --version
v13.8.0
Discussion on when different versions of node emit req.on('close') event here: https://github.com/nodejs/node/issues/31394.
Assuming there is no specific "the client has disconnected before you have sent a response" event, what is the best pattern, to detect that situation in general, so I can log it.
Upvotes: 1
Views: 1383
Reputation: 11
We could use a variable to assess this. Code mentioned below logs the error message when client is closed before the request processing is complete. This is kind of a dirty fix, but it works
const Koa = require('koa');
const app = new Koa();
/**
* synchronously delay/sleep/block for time ms
*/
const delay = time => new Promise(res=> {
console.log(`About to sleep for ${time} ms`)
setTimeout(res,time)
});
app.on('error', (err, ctx) => {
console.error('server error', err, ctx)
});
app.use(async ctx => {
let requestProcessingCompleted = false
ctx.req.on('close', () => {
console.log('Request closed');
if(!requestProcessingCompleted){
console.log("Client connection closed before request processing completed")
}
});
console.log('Hello World Started')
await delay(10000)
console.log('Hello World Ended');
ctx.body = 'Hello World !!!';
requestProcessingCompleted = true
});
app.listen(3000, () => console.log('running on port 3000'));
Upvotes: 1