Sending an http response outside of the route function?

So, I have a route function like the following:

var http = require('http').createServer(start);

function start(req, res){
//routing stuff
}

and below that,I have a socket.io event listener:

io.sockets.on('connection', function(socket){

    socket.on('event', function(data){
        //perform an http response
    }

}

When the socket event 'event' is called, I would like to perform an http response like the following:

res.writeHead(200, {'Content-disposition': 'attachment; filename=file.zip'})
res.writeHead(200, { 'Content-Type': 'application/zip' });
var filestream = fs.createReadStream('file.zip');

filestream.on('data', function(chunk) {
    res.write(chunk);
});

filestream.on('end', function() {
    res.end();
});

This last part, when performed within the routing function works just fine, but unfortunately when it is called from the socket event, it of course does not work, because it has no reference to the 'req' or 'res' objects. How would I go about doing this? Thanks.

Hmmm... interesting problem:

  • It's not impossible to do something like what you're trying to do, the flow would be something like this:

    1. Receive http request, don't respond, keep res object saved somewhere.
    2. Receive websocket request, do your auth/"link" it to the res object saved earlier.
    3. Respond with file via res.
  • BUT it's not very pretty for a few reasons:

    1. You need to keep res objects saved, if your server restarts a whole bunch of response objects are lost.
    2. You need to figure out how to link websocket clients to http request clients. You could do something with cookies/localstorage to do this, I think.
    3. Scaling to another server will become a lot harder / will you proxy clients to always be served by the same server somehow? Otherwise the linking will get harder.

I would propose a different solution for you: You want to do some client/server steps using websockets before you let someone download a file?

Check here whether this solution is cross-browser enough for you: http://caniuse.com/#feat=datauri

Another option would be to generate a unique URL for the download, and only append it to the browser's window (either as a hidden iframe download, or as a simple download button) once you've done your logic via websocket. This option would be more available cross-browser and easier to code.