Pavel Pavel - 2 months ago 19
Node.js Question

nodejs: abort http reply while in progress

How do I abort http reply with express in the middle?
In my case I serve data that's generated from externals source and before I start serving it I know the size (content-length). However, if external source stops feeding me the data before feeding me full content I want to abort the request so that on receiver end there would be error event triggered.

Here's simple code, server:

//server
var express = require('express');
var app = express();
app.use(function(req, res, next){
res.setHeader('Content-Length', 100);
res.writeHead(200);
res.write('1234567890');
setTimeout(function() { res.connection.destroy(); }, 500);
});
app.listen(8080);


and

//client
var http = require('http');
http.get('http://localhost:8080/', function(res){
var length = 0;
console.log('expected size: ', res.headers['content-length']);
res.on('data', function(chunk){ length += chunk.length; });
res.on('end', function(){ console.log('received: ', length); });
}).on('error', function(e){
console.log('error', e);
});


It's expected that client should show error that connection was reset and not behave as everything was ok even though only 10 bytes out of 100 were received.

How to abort connection on sender side when it's known that request cannot be fulfilled? One way I found out is to throw exception inside that timer, then receiver will log error, but I don't want to throw exception, I want to do it properly.

Answer

Ideally to end an HTTP response, you would call res.end(). In the cases of chunked transfer encoding or a connection without HTTP keep-alive, this will cleanly end the response.

However, most HTTP connections will support HTTP keep-alive, and since you have a Content-Length header, your transfer encoding isn't chunked. In your case, you will have to close the underlying socket. Check out the req.connection property, and call .end() on it. This is undocumented but has been there for years and probably is safe for now. More legitimate methods for getting the connection include listening for it on the server object, but then it's hard to associate the connection with the request.

You should be aware though that with most HTTP clients, this is a warning at best and not typically an error. If you are in control of the client code, you can detect this condition by comparing the length of the data you received, to the length you expected.