Skip to content

Commit

Permalink
[fix] Manage bookkeeping for incoming requests to the underlying sock…
Browse files Browse the repository at this point in the history
…ets behind reverse proxied websocket events. Only use the appropriate variables in the closure scope of the `upgrade` event from this bookkeeping
  • Loading branch information
indexzero committed May 13, 2011
1 parent 6c80177 commit 85223ea
Showing 1 changed file with 47 additions and 21 deletions.
68 changes: 47 additions & 21 deletions lib/node-http-proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -530,24 +530,30 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, options
}
}

function onUpgrade(reverseProxy) {
function onUpgrade(out, reverseProxy) {
if (!out) {
reverseProxy.end();
socket.end();
return;
}

var listeners = {};

// We're now connected to the server, so lets change server socket
reverseProxy.on('data', listeners._r_data = function(data) {
// Pass data to client
if (socket.writable) {
if (out.incoming.socket.writable) {
try {
socket.write(data);
out.incoming.socket.write(data);
}
catch (e) {
socket.end();
out.incoming.socket.end();
reverseProxy.end();
}
}
});

socket.on('data', listeners._data = function(data) {
out.incoming.socket.on('data', listeners._data = function(data) {
// Pass data from client to server
try {
reverseProxy.write(data);
Expand All @@ -562,13 +568,13 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, options
function detach() {
reverseProxy.removeListener('close', listeners._r_close);
reverseProxy.removeListener('data', listeners._r_data);
socket.removeListener('data', listeners._data);
socket.removeListener('close', listeners._close);
out.incoming.socket.removeListener('data', listeners._data);
out.incoming.socket.removeListener('close', listeners._close);
}

// Hook disconnections
reverseProxy.on('end', listeners._r_close = function() {
socket.end();
out.incoming.socket.end();
detach();
});

Expand All @@ -592,27 +598,47 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, options
outgoing = {
host: options.host,
port: options.port,
agent: agent,
method: 'GET',
path: req.url,
headers: req.headers
headers: req.headers,
};

// Make the outgoing WebSocket request
var request = http.request(outgoing, function () { });

// Not disconnect on update
agent.on('upgrade', function(request, remoteSocket, head) {
// Prepare socket
_socket(remoteSocket, true);
var request = agent.appendMessage(outgoing);

// Emit event
onUpgrade(remoteSocket);
});
//
// Here we set the incoming `req`, `socket` and `head` data to the outgoing
// request so that we can reuse this data later on in the closure scope
// available to the `upgrade` event. This bookkeeping is not tracked anywhere
// in nodejs core and is **very** specific to proxying WebSockets.
//
request.agent = agent;
request.incoming = {
request: req,
socket: socket,
head: head
};

//
// If the agent for this particular `host` and `port` combination
// is not already listening for the `upgrade` event, then do so once.
// This will force us not to disconnect.
//
// In addition, it's important to note the closure scope here. Since
// there is no mapping of the
//
if (!agent._events || agent._events['upgrade'].length === 0) {
agent.on('upgrade', function (out, remoteSocket, head) {
// Prepare socket
_socket(remoteSocket, true);

// Emit event
onUpgrade(remoteSocket._httpMessage, remoteSocket);
});
}

var handshake;
if (typeof request.socket !== 'undefined') {
request.socket.on('data', handshake = function(data) {
request.socket.on('data', function handshake (data) {
// Handshaking

// Ok, kind of harmfull part of code
Expand Down

0 comments on commit 85223ea

Please sign in to comment.