From efa17ef6cf614b763fc3b76570a24e750e2ddd31 Mon Sep 17 00:00:00 2001 From: Dominic Tarr Date: Thu, 21 Jul 2011 23:08:11 +1000 Subject: [PATCH] [fix] use routing table mhen proxying WebSockets. closes issue #72 --- lib/node-http-proxy.js | 14 +++++++++++ test/helpers.js | 40 +++++++++++++++++++++++++++++++ test/web-socket-proxy-test.js | 45 +++++++++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+) diff --git a/lib/node-http-proxy.js b/lib/node-http-proxy.js index c3bff9d..9266727 100644 --- a/lib/node-http-proxy.js +++ b/lib/node-http-proxy.js @@ -583,6 +583,20 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, options CRLF = '\r\n', outgoing; + options = options || {}; + options.host = options.host || this.target.host; + options.port = options.port || this.target.port; // + + if (this.proxyTable && !options.host) { + location = this.proxyTable.getProxyLocation(req); + + if (!location) { + res.writeHead(404); + return res.end(); + } + options.port = location.port; + options.host = location.host; + } // // WebSocket requests must have the `GET` method and // the `upgrade:websocket` header diff --git a/test/helpers.js b/test/helpers.js index 956e548..23a29e6 100644 --- a/test/helpers.js +++ b/test/helpers.js @@ -121,6 +121,10 @@ TestRunner.prototype.assertResponseCode = function (proxyPort, statusCode, creat return test; }; +// +// WebSocketTest +// + TestRunner.prototype.webSocketTest = function (options) { var self = this; @@ -154,6 +158,42 @@ TestRunner.prototype.webSocketTest = function (options) { }); } +// +// WebSocketTestWithTable +// + +TestRunner.prototype.webSocketTestWithTable = function (options) { + var self = this; + + this.startTargetServer(options.ports.target, 'hello websocket', function (err, target) { + var socket = options.io.listen(target); + + if (options.onListen) { + options.onListen(socket); + } + + self.startProxyServerWithTable( + options.ports.proxy, + {router: options.router}, + function (err, proxy) { + if (options.onServer) { options.onServer(proxy) } + + // + // Setup the web socket against our proxy + // + var uri = options.wsprotocol + '://' + options.host + ':' + options.ports.proxy; + var ws = new websocket.WebSocket(uri + '/socket.io/websocket/', 'borf', { + origin: options.protocol + '://' + options.host + }); + + if (options.onWsupgrade) { ws.on('wsupgrade', options.onWsupgrade) } + if (options.onMessage) { ws.on('message', options.onMessage) } + if (options.onOpen) { ws.on('open', function () { options.onOpen(ws) }) } + } + ); + }); +} + // // Creates the reverse proxy server // diff --git a/test/web-socket-proxy-test.js b/test/web-socket-proxy-test.js index b02075a..339bc71 100644 --- a/test/web-socket-proxy-test.js +++ b/test/web-socket-proxy-test.js @@ -48,6 +48,50 @@ var protocol = argv.https ? 'https' : 'http', runner = new helpers.TestRunner(protocol); vows.describe('node-http-proxy/websocket/' + wsprotocol).addBatch({ + "when using proxy table":{ + "with no latency" : { + "when an inbound message is sent from a WebSocket client": { + topic: function () { + var that = this + headers = {}; + + runner.webSocketTestWithTable({ + io: io, + host: 'localhost', + wsprotocol: wsprotocol, + protocol: protocol, + router: {'localhost':'localhost:8230'}, + ports: { + target: 8230, + proxy: 8231 + }, + onListen: function (socket) { + socket.on('connection', function (client) { + client.on('message', function (msg) { + that.callback(null, msg, headers); + }); + }); + }, + onWsupgrade: function (req, res) { + headers.request = req; + headers.response = res.headers; + }, + onOpen: function (ws) { + ws.send(utils.encode('from client')); + } + }); + }, + "the target server should receive the message": function (err, msg, headers) { + assert.equal(msg, 'from client'); + }, + "the origin and sec-websocket-origin headers should match": function (err, msg, headers) { + assert.isString(headers.response['sec-websocket-location']); + assert.isTrue(headers.response['sec-websocket-location'].indexOf(wsprotocol) !== -1); + assert.equal(headers.request.Origin, headers.response['sec-websocket-origin']); + } + } + } + }, "When using server created by httpProxy.createServer()": { "with no latency" : { "when an inbound message is sent from a WebSocket client": { @@ -114,6 +158,7 @@ vows.describe('node-http-proxy/websocket/' + wsprotocol).addBatch({ }); }, "should raise the `websocket:incoming` event": function (ign, data) { + console.log(ign,data,utils.decode(data)) assert.equal(utils.decode(data.toString().replace('\u0000', '')), 'from client'); }, },