From 8d701bb20b593c6cdf0ff1bc35cf83051b21a35e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Ma=C5=82ecki?= Date: Tue, 25 Oct 2011 09:38:38 +0200 Subject: [PATCH 1/6] [example] Replace `sys` usages with `util` --- examples/websocket/latent-websocket-proxy.js | 8 ++++---- examples/websocket/standalone-websocket-proxy.js | 8 ++++---- examples/websocket/websocket-proxy.js | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/examples/websocket/latent-websocket-proxy.js b/examples/websocket/latent-websocket-proxy.js index 3112f6b..338d7ea 100644 --- a/examples/websocket/latent-websocket-proxy.js +++ b/examples/websocket/latent-websocket-proxy.js @@ -24,7 +24,7 @@ */ -var sys = require('sys'), +var util = require('util'), http = require('http'), colors = require('colors'), websocket = require('../../vendor/websocket'), @@ -55,10 +55,10 @@ server.listen(8080); // var socket = io.listen(server); socket.on('connection', function (client) { - sys.debug('Got websocket connection'); + util.debug('Got websocket connection'); client.on('message', function (msg) { - sys.debug('Got message from client: ' + msg); + util.debug('Got message from client: ' + msg); }); socket.broadcast('from server'); @@ -101,5 +101,5 @@ ws.on('open', function () { }); ws.on('message', function (msg) { - sys.debug('Got message: ' + utils.decode(msg)); + util.debug('Got message: ' + utils.decode(msg)); }); diff --git a/examples/websocket/standalone-websocket-proxy.js b/examples/websocket/standalone-websocket-proxy.js index bfbc252..cd4a855 100644 --- a/examples/websocket/standalone-websocket-proxy.js +++ b/examples/websocket/standalone-websocket-proxy.js @@ -24,7 +24,7 @@ */ -var sys = require('sys'), +var util = require('util'), http = require('http'), colors = require('colors'), websocket = require('../../vendor/websocket'), @@ -55,10 +55,10 @@ server.listen(8080); // var socket = io.listen(server); socket.on('connection', function (client) { - sys.debug('Got websocket connection'); + util.debug('Got websocket connection'); client.on('message', function (msg) { - sys.debug('Got message from client: ' + msg); + util.debug('Got message from client: ' + msg); }); socket.broadcast('from server'); @@ -97,5 +97,5 @@ ws.on('open', function () { }); ws.on('message', function (msg) { - sys.debug('Got message: ' + utils.decode(msg)); + util.debug('Got message: ' + utils.decode(msg)); }); diff --git a/examples/websocket/websocket-proxy.js b/examples/websocket/websocket-proxy.js index 975fab0..0b76b8a 100644 --- a/examples/websocket/websocket-proxy.js +++ b/examples/websocket/websocket-proxy.js @@ -24,7 +24,7 @@ */ -var sys = require('sys'), +var util = require('util'), http = require('http'), colors = require('colors'), websocket = require('../../vendor/websocket'), @@ -55,10 +55,10 @@ server.listen(8080); // var socket = io.listen(server); socket.on('connection', function (client) { - sys.debug('Got websocket connection'); + util.debug('Got websocket connection'); client.on('message', function (msg) { - sys.debug('Got message from client: ' + msg); + util.debug('Got message from client: ' + msg); }); socket.broadcast('from server'); @@ -80,5 +80,5 @@ ws.on('open', function () { }); ws.on('message', function (msg) { - sys.debug('Got message: ' + utils.decode(msg)); + util.debug('Got message: ' + utils.decode(msg)); }); From 6655e0164216449a97090651230266da8ced0150 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Ma=C5=82ecki?= Date: Thu, 27 Oct 2011 19:36:05 +0200 Subject: [PATCH 2/6] [v0.6] Don't use `agent.appendMessage()` Instead, just perform a request. --- lib/node-http-proxy/http-proxy.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/node-http-proxy/http-proxy.js b/lib/node-http-proxy/http-proxy.js index 227948d..7ae8b6c 100644 --- a/lib/node-http-proxy/http-proxy.js +++ b/lib/node-http-proxy/http-proxy.js @@ -590,11 +590,12 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, buffer) // outgoing.host = this.target.host; outgoing.port = this.target.port; + outgoing.agent = agent; outgoing.method = 'GET'; outgoing.path = req.url; outgoing.headers = req.headers; - var reverseProxy = agent.appendMessage(outgoing); + var reverseProxy = this.target.protocol.request(outgoing); // // On any errors from the `reverseProxy` emit the From 86b4122323ca32d455714b1149b99acce49a9e45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Ma=C5=82ecki?= Date: Wed, 2 Nov 2011 13:23:40 +0100 Subject: [PATCH 3/6] [v0.6] `http.Agent` uses different structure for sockets --- lib/node-http-proxy/http-proxy.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/node-http-proxy/http-proxy.js b/lib/node-http-proxy/http-proxy.js index 7ae8b6c..9e5e545 100644 --- a/lib/node-http-proxy/http-proxy.js +++ b/lib/node-http-proxy/http-proxy.js @@ -753,9 +753,11 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, buffer) HttpProxy.prototype.close = function () { [this.forward, this.target].forEach(function (proxy) { if (proxy && proxy.agent) { - proxy.agent.sockets.forEach(function (socket) { - socket.end(); - }); + for (var host in proxy.agent.sockets) { + proxy.agent.sockets[host].forEach(function (socket) { + socket.end(); + }); + } } }); }; From 5b52c896947db42ac01e6038c9170d8859d33aea Mon Sep 17 00:00:00 2001 From: indexzero Date: Sat, 10 Sep 2011 06:31:45 -0400 Subject: [PATCH 4/6] [refactor] Updates to support http2 from @mikeal Conflicts: lib/node-http-proxy/http-proxy.js --- lib/node-http-proxy/http-proxy.js | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/lib/node-http-proxy/http-proxy.js b/lib/node-http-proxy/http-proxy.js index 9e5e545..476b16c 100644 --- a/lib/node-http-proxy/http-proxy.js +++ b/lib/node-http-proxy/http-proxy.js @@ -25,6 +25,7 @@ */ var events = require('events'), + http = require('http'), util = require('util'), httpProxy = require('../node-http-proxy'); @@ -594,6 +595,7 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, buffer) outgoing.method = 'GET'; outgoing.path = req.url; outgoing.headers = req.headers; + outgoing.agent = agent; var reverseProxy = this.target.protocol.request(outgoing); @@ -617,7 +619,6 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, buffer) // available to the `upgrade` event. This bookkeeping is not tracked anywhere // in nodejs core and is **very** specific to proxying WebSockets. // - reverseProxy.agent = agent; reverseProxy.incoming = { request: req, socket: socket, @@ -632,17 +633,15 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, buffer) // In addition, it's important to note the closure scope here. Since // there is no mapping of the socket to the request bound to it. // - if (!agent._events || agent._events['upgrade'].length === 0) { - agent.on('upgrade', function (_, remoteSocket, head) { - // - // Prepare the socket for the reverseProxy request and begin to - // stream data between the two sockets. Here it is important to - // note that `remoteSocket._httpMessage === reverseProxy`. - // - _socket(remoteSocket, true); - onUpgrade(remoteSocket._httpMessage, remoteSocket); - }); - } + reverseProxy.on('upgrade', function (_, remoteSocket, head) { + // + // Prepare the socket for the reverseProxy request and begin to + // stream data between the two sockets. Here it is important to + // note that `remoteSocket._httpMessage === reverseProxy`. + // + _socket(remoteSocket, true); + onUpgrade(remoteSocket._httpMessage, remoteSocket); + }); // // If the reverseProxy connection has an underlying socket, From ea7fea627255ed34d39902438b55e740c7c9b08c Mon Sep 17 00:00:00 2001 From: indexzero Date: Fri, 23 Dec 2011 01:32:49 -0500 Subject: [PATCH 5/6] [refactor minor] Update vendor/websocket.js to be compatible with node@0.6.x --- vendor/websocket.js | 198 ++++++++++++++++++++++---------------------- 1 file changed, 98 insertions(+), 100 deletions(-) diff --git a/vendor/websocket.js b/vendor/websocket.js index d8c5eeb..406023c 100644 --- a/vendor/websocket.js +++ b/vendor/websocket.js @@ -496,7 +496,7 @@ var WebSocket = function(url, proto, opts) { if (u.protocol === 'ws:' || u.protocol === 'wss:') { protocol = u.protocol === 'ws:' ? http : https; port = u.protocol === 'ws:' ? 80 : 443; - agent = u.protocol === 'ws:' ? protocol.getAgent(u.hostname, u.port || port) : protocol.getAgent({ + agent = u.protocol === new protocol.Agent({ host: u.hostname, port: u.port || port }); @@ -514,105 +514,6 @@ var WebSocket = function(url, proto, opts) { throw new Error('Invalid URL scheme \'' + urlScheme + '\' specified.'); } - if (!agent._events || agent._events['upgrade'].length === 0) { - agent.on('upgrade', (function() { - var data = undefined; - - return function(res, s, head) { - stream = s; - - // - // Emit the `wsupgrade` event to inspect the raw - // arguments returned from the websocket request. - // - self.emit('wsupgrade', httpHeaders, res, s, head); - - stream.on('data', function(d) { - if (d.length <= 0) { - return; - } - - if (!data) { - data = d; - } else { - var data2 = new buffer.Buffer(data.length + d.length); - - data.copy(data2, 0, 0, data.length); - d.copy(data2, data.length, 0, d.length); - - data = data2; - } - - if (data.length >= 16) { - var expected = computeSecretKeySignature(key1, key2, challenge); - var actual = data.slice(0, 16).toString('binary'); - - // Handshaking fails; we're donezo - if (actual != expected) { - debug( - 'expected=\'' + str2hex(expected) + '\'; ' + - 'actual=\'' + str2hex(actual) + '\'' - ); - - process.nextTick(function() { - // N.B. Emit 'wserror' here, as 'error' is a reserved word in the - // EventEmitter world, and gets thrown. - self.emit( - 'wserror', - new Error('Invalid handshake from server:' + - 'expected \'' + str2hex(expected) + '\', ' + - 'actual \'' + str2hex(actual) + '\'' - ) - ); - - if (self.onerror) { - self.onerror(); - } - - finishClose(); - }); - } - - // - // Un-register our data handler and add the one to be used - // for the normal, non-handshaking case. If we have extra - // data left over, manually fire off the handler on - // whatever remains. - // - stream.removeAllListeners('data'); - stream.on('data', dataListener); - - readyState = OPEN; - - process.nextTick(function() { - self.emit('open'); - - if (self.onopen) { - self.onopen(); - } - }); - - // Consume any leftover data - if (data.length > 16) { - stream.emit('data', data.slice(16, data.length)); - } - } - }); - stream.on('fd', fdListener); - stream.on('error', errorListener); - stream.on('close', function() { - errorListener(new Error('Stream closed unexpectedly.')); - }); - - stream.emit('data', head); - }; - })()); - } - - agent.on('error', function (e) { - errorListener(e); - }); - var httpReq = protocol.request({ host: u.hostname, method: 'GET', @@ -622,6 +523,103 @@ var WebSocket = function(url, proto, opts) { headers: httpHeaders }); + httpReq.on('error', function (e) { + errorListener(e); + }); + + httpReq.on('upgrade', (function() { + var data = undefined; + + return function(res, s, head) { + stream = s; + + // + // Emit the `wsupgrade` event to inspect the raw + // arguments returned from the websocket request. + // + self.emit('wsupgrade', httpHeaders, res, s, head); + + stream.on('data', function(d) { + if (d.length <= 0) { + return; + } + + if (!data) { + data = d; + } else { + var data2 = new buffer.Buffer(data.length + d.length); + + data.copy(data2, 0, 0, data.length); + d.copy(data2, data.length, 0, d.length); + + data = data2; + } + + if (data.length >= 16) { + var expected = computeSecretKeySignature(key1, key2, challenge); + var actual = data.slice(0, 16).toString('binary'); + + // Handshaking fails; we're donezo + if (actual != expected) { + debug( + 'expected=\'' + str2hex(expected) + '\'; ' + + 'actual=\'' + str2hex(actual) + '\'' + ); + + process.nextTick(function() { + // N.B. Emit 'wserror' here, as 'error' is a reserved word in the + // EventEmitter world, and gets thrown. + self.emit( + 'wserror', + new Error('Invalid handshake from server:' + + 'expected \'' + str2hex(expected) + '\', ' + + 'actual \'' + str2hex(actual) + '\'' + ) + ); + + if (self.onerror) { + self.onerror(); + } + + finishClose(); + }); + } + + // + // Un-register our data handler and add the one to be used + // for the normal, non-handshaking case. If we have extra + // data left over, manually fire off the handler on + // whatever remains. + // + stream.removeAllListeners('data'); + stream.on('data', dataListener); + + readyState = OPEN; + + process.nextTick(function() { + self.emit('open'); + + if (self.onopen) { + self.onopen(); + } + }); + + // Consume any leftover data + if (data.length > 16) { + stream.emit('data', data.slice(16, data.length)); + } + } + }); + stream.on('fd', fdListener); + stream.on('error', errorListener); + stream.on('close', function() { + errorListener(new Error('Stream closed unexpectedly.')); + }); + + stream.emit('data', head); + }; + })()); + httpReq.write(challenge, 'binary'); httpReq.end(); })(); From 38286168161d4f4ad24d2ad95ccd8335e9ed08a4 Mon Sep 17 00:00:00 2001 From: indexzero Date: Fri, 23 Dec 2011 01:33:24 -0500 Subject: [PATCH 6/6] [refactor] Listen for `socket` events since reverseProxy.socket is no longer set synchronously --- lib/node-http-proxy/http-proxy.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/node-http-proxy/http-proxy.js b/lib/node-http-proxy/http-proxy.js index 476b16c..486c2e6 100644 --- a/lib/node-http-proxy/http-proxy.js +++ b/lib/node-http-proxy/http-proxy.js @@ -647,8 +647,8 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, buffer) // If the reverseProxy connection has an underlying socket, // then execute the WebSocket handshake. // - if (typeof reverseProxy.socket !== 'undefined') { - reverseProxy.socket.on('data', function handshake (data) { + reverseProxy.once('socket', function (revSocket) { + revSocket.on('data', function handshake (data) { // // Ok, kind of harmfull part of code. Socket.IO sends a hash // at the end of handshake if protocol === 76, but we need @@ -681,12 +681,12 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, buffer) socket.write(sdata); var flushed = socket.write(data); if (!flushed) { - reverseProxy.socket.pause(); + revSocket.pause(); socket.once('drain', function () { - try { reverseProxy.socket.resume() } + try { revSocket.resume() } catch (er) { console.error("reverseProxy.socket.resume error: %s", er.message) } }); - + // // Force the `drain` event in 100ms if it hasn't // happened on its own. @@ -701,7 +701,7 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, buffer) // Remove data listener on socket error because the // 'handshake' has failed. // - reverseProxy.socket.removeListener('data', handshake); + revSocket.removeListener('data', handshake); return proxyError(ex); } @@ -711,9 +711,9 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, buffer) // // Remove data listener now that the 'handshake' is complete // - reverseProxy.socket.removeListener('data', handshake); + revSocket.removeListener('data', handshake); }); - } + }); reverseProxy.on('error', proxyError);