Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

http: abort tcp connection in the middle of request handling #8775

Closed
pps83 opened this issue Sep 25, 2016 · 5 comments
Closed

http: abort tcp connection in the middle of request handling #8775

pps83 opened this issue Sep 25, 2016 · 5 comments
Labels
http Issues or PRs related to the http subsystem.

Comments

@pps83
Copy link

pps83 commented Sep 25, 2016

What is a proper api to abort http reply in the middle? Suppose http server started reply, wrote Content-Length header and then in the middle of serving body there was some event that made that reply invalid or impossible to complete. res.end() isn't acceptable if full body wasn't written yet (as it would cause havoc if keep-alive was in effect), so TCP connection has to be closed (and there is no api provided for that?).
The problem is that on receiver side there is no 'error' event triggered even though full body wasn't received. It seems that if TCP is aborted with RST then there is an 'error' event triggered (this happens on Win10, but not on ubuntu, however I didn't check if there is actual tcp RST sent on ubuntu).
Is there any api to abort http request so that on client side there would be an 'error' event? The other point: what if chunked transfer encoding was used and server had to abort reply in the middle? on client side 'error' event should be emitted if response finished before handling final 0\r\n\r\n, otherwise how is the client supposed to know that the body wasn't complete?

Shouldn't node check for content-length header and trigger 'error' event if body size doesn't match content length? Same for sender side: shouldn't it trigger exception if response body size doesn't match content-length header? At least this behavior should be configurable perhaps?

Below is a simple example for simplicity: server starts serving reply, says that it's 10-bytes long and then after serving 9 bytes simply closes the connection after 500ms. I wasn't able to find a way to abort http connection on server side so that client gets an error instead of thinking that request was properly served.

// node server.js
var http = require('http');
var server = http.createServer(function(req, res){
    res.setHeader('Content-Length', 10);
    res.writeHead(200);
    // res.end('1234567890'); return;
    res.write('123456789');
    // thrown error causes client to emit 'error' event on Win10, but not on ubuntu
    //setTimeout(function() { throw new Error('no data'); }, 500);
    //setTimeout(function() { res.socket.end(); }, 500);
    //setTimeout(function() { res.connection.destroy(); }, 500);
    setTimeout(function() { res.connection.end(); }, 500);
});
server.listen(8123);

and then

// node client.js
var http = require('http');
var keep_alive = new http.Agent({keepAlive: true, keepAliveMsecs: 30000});
var count = 0;
function request()
{
    http.get({hostname: 'localhost', port: 8123, path: '/', agent: keep_alive}, function(res){
       var length = 0;
       console.log('response on port: ', res.connection.localPort, ', 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);
    });
}
request();
setTimeout(request, 1000);

On Win10 if I throw exception before ending reply then on client side I do get the 'error' event, however, on ubuntu there is no error events posted.

It seems that there was something related posted a while ago: nodejs/node-v0.x-archive#1776

@mscdex mscdex added the http Issues or PRs related to the http subsystem. label Sep 25, 2016
@RoobinGood
Copy link

@pps83, looks like your issue may be related to #8102.
On client side you can check res.complete to make sure that request successfully ended.
With Node v4.4.1 in client end handler I have res.complete === false in your example that means that request ended without success.
But anyway it cannot explain different behavior on windows and linux.

@Trott
Copy link
Member

Trott commented Jul 10, 2017

@nodejs/http @nodejs/platform-windows Is there anything to do on the Node.js side on this one? Any helpful information to provide @pps83? Should this remain open?

@stefhak
Copy link

stefhak commented Oct 5, 2017

Just taking the opportunity to ask a question: is it possible to make the server send TCP RST? (socket.end() seems to generate TCP FIN).

@apapirovski
Copy link
Member

ping @nodejs/http @nodejs/http2

@mcollina
Copy link
Member

mcollina commented Jul 5, 2018

@pps83 @Trott

I think we can close this one. By design our client does not validate that the body size matches the given content-length. It's clearly written in the docs:

Node.js does not check whether Content-Length and the length of the body which has been transmitted are equal or not.

@stefhak

is it possible to make the server send TCP RST?

No, libuv does not support this. My guess is that would be very hard to support in a cross-platform manner.

@mcollina mcollina closed this as completed Jul 5, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
http Issues or PRs related to the http subsystem.
Projects
None yet
Development

No branches or pull requests

7 participants