6

I'm trying out Node.js by writing a very basic http/web caching proxy, and have hit something I haven't managed to break through.

Assuming I have a very basic proxy functionality (listen to request, pipe it to external server, wait for response, pipe it back to client), how do I detect when the client (web browser) cancels the request? When the user clicks "Stop"/Esc on his browser, the browser doesn't send me any "request" or info and attaching a callback for when the "response" connection ends doesn't get called.

Here's what I mean:

http.createServer (clientRequest, clientResponse) {  
    var client = http.createClient (port, hostname);
    var request = client.request (method, url, headers);  

    request.addListener ('response', function(response){  
        response.addListener ('data', function(chunk){  
           // forward data to clientResponse..
        }  
        response.addListener ('end', function(){   
           // end clientResponse..  
        }  
    });  
    clientResponse.addListener('end', function(){  
        // this never gets called :(
        // I want it to terminate the request/response created just above  
    }
}
Zach Saucier
  • 24,871
  • 12
  • 85
  • 147
Cyclonus
  • 507
  • 5
  • 13
  • Have you considered using a WebSocket implementation like Socket.IO? Managing (start/stop) connections is really easy using Socket.IO – 0xff0000 Apr 25 '11 at 06:41
  • Shouldn't those params in `createServer` be `(serverRequest, serverResponse)` (http://nodejs.org/api/http.html#http_event_request)? And it's the `serverRequest` that you should be binding to ('close' event as you say below). Also why are you creating a *client* inside the *server* request handler? Unless you are calling an external API, it looks like you have a server which creates an internal client which calls itself (recursively) when initially triggered from an *external* client (ie a browser)? – Hari Honor Jan 27 '13 at 16:28
  • @Hari: Like I mentioned, this was for a proxy. My goal was to receive a request from an external client (the browser, which I called "clientRequest") and then to analyze/modify the request and forward it. So after analyzing/modifying/caching/whatever, I need to create a new request: _client.request_. So: _clientRequest_ is the request from the browser, and _client.request_ is the new forwarded request. I hope that clears it up. (No recursion here!) – Cyclonus Jan 29 '13 at 09:44
  • Thx @Cyclonus. For clarity's sake, I'd suggest it ceases to be a 'client' request and becomes a 'server' request once the server receives it. Anyway the best name is up to you but what you call `clientResponse` (aka response *to* the client or *from* the server) is under your control so no events should ever be called on it unless your code initiates it. It's your `clientRequest` to which you want to bind for detecting browser cancellations, I'm pretty sure. Have you gotten this to work another way? – Hari Honor Jan 29 '13 at 13:46
  • @Hari: It will take some time for me to find the code (this question is almost 2 years old at this point :)), but I believe I ended up binding to the _close_ event of all requests and responses. I think you might be right about binding to the _clientRequest_ for detecting when the user cancels his request, but I needed to bind to all requests&responses anyway for other purposes as well (logging, statistics, etc.). – Cyclonus Feb 04 '13 at 10:16

1 Answers1

5

Turns out I should be binding to the "close" event instead of the "end" event of the request. That does actually make sense.
I'm posting this here for anyone else who might encounter the same issue:

clientResponse.addListener('close', function(){  
    // this gets called when the user terminates his request  
}
Shef
  • 44,808
  • 15
  • 79
  • 90
Cyclonus
  • 507
  • 5
  • 13