2

How do I abort http reply with express in the middle? In my case I serve data that's generated from external 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.

2
  • Hmm. I think you'd have to grab the full data from the external source before returning it from the node server. Commented Sep 24, 2016 at 23:46
  • @RobertMoskal not an option, I need to know hot to abort tcp connection. I can't believe there is no such method. I actually need to abort, no workarounds or other solutions. Commented Sep 25, 2016 at 0:12

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

11 Comments

did you check my code? I do req.connection.destroy(). Obviously I know about res.end(). You cannot do res.end(), you absolutely must close the connection. Do you realize that ?
Yes, I did check your code. Use .end() on your socket... .destroy() is not what you want. And, what do you think res.end() does in the situation of no keepalive? It closes the connection. I mention it because it might be relevant in your case. Please re-read my answer, the two options I suggested, and pick one that applies to you.
exactly, res.end() will cause havoc in case of keepalive if non-chunked transmission is used. I'll try socket.end, didn't try it yet.
@Pavel Also note, depending on your version of Node.js, socket.close() might be what you need. This API has been changed a bit over the years.
there is no socket.close in my version of node (I use latest). I tried these: req.socket.end(), 'req.connection.end()', 'req.connection.destroy()', req.connection.destroy(new Error('bad data')), none of them trigger error event on client side and client thinks that everything was ok. IMO node has to handle properly content-length header and trigger exception, currently you can send 10-byte with 100-byte content length and it handles it as everything went well.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.