diff --git a/tools/run-httpproxy.js b/tools/run-httpproxy.js index 1b29cfa158..175357dea1 100644 --- a/tools/run-httpproxy.js +++ b/tools/run-httpproxy.js @@ -19,6 +19,7 @@ var HttpProxy = function (options) { self.mode = "proxy"; self.httpQueue = []; // keys: req, res self.websocketQueue = []; // keys: req, socket, head + self.connectQueue = []; // keys: req, socket, head self.proxy = null; self.server = null; @@ -53,6 +54,11 @@ _.extend(HttpProxy.prototype, { self._tryHandleConnections(); }); + self.server.on('connect', function (req, socket, head) { + self.connectQueue.push({ req: req, socket: socket, head: head }); + self._tryHandleConnections(); + }); + self.server.on('upgrade', function (req, socket, head) { // Websocket connection self.websocketQueue.push({ req: req, socket: socket, head: head }); @@ -148,6 +154,11 @@ _.extend(HttpProxy.prototype, { }); self.websocketQueue = []; + _.each(self.connectQueue, function (c) { + c.socket.destroy(); + }); + self.connectQueue = []; + self.mode = "hold"; }, @@ -180,6 +191,15 @@ _.extend(HttpProxy.prototype, { target: targetUrl }); } + + while (self.connectQueue.length) { + if (self.mode !== "proxy") + break; + + var c = self.connectQueue.shift(); + runLog.log("Proxy request (connect): " + c.req.method + " " + c.req.url); + proxyConnectMethod(c.req, c.socket, c.head); + } }, // The proxy can be in one of three modes: @@ -193,4 +213,68 @@ _.extend(HttpProxy.prototype, { } }); + + +// This is what http-proxy does +// XXX: We should submit connect support upstream +var setupSocket = function(socket) { + socket.setTimeout(0); + socket.setNoDelay(true); + + socket.setKeepAlive(true, 0); + + return socket; +}; + + +var proxyConnectMethod = function (req, socket, options, head, server, clb) { + if (req.method !== 'CONNECT') { + socket.destroy(); + return true; + } + + var tokens = req.url.split(':'); + + if (tokens.length != 2) { + runLog.log("Bad request: " + req.url); + socket.destroy(); + return true; + } + + var host = tokens[0]; + var port = tokens[1]; + + if (port != 443) { + runLog.log("Blocking request to non-443 port: " + req.url); + socket.destroy(); + return true; + } + + setupSocket(socket); + + // XXX: Needed? + // if (head && head.length) socket.unshift(head); + + var net = require('net'); + var proxySocket = net.createConnection(port, host); + setupSocket(proxySocket); + + socket.on('error', function (err) { + runLog.log("Error on socket: " + err); + proxySocket.end(); + }); + proxySocket.on('error', function (err) { + runLog.log("Error on proxySocket: " + err); + socket.end(); + }); + + proxySocket.on('connect', function(connect) { + runLog.log("Connection established to " + host + ":" + port); + socket.write("HTTP/1.0 200 Connection established\n\n"); + socket.pipe(proxySocket); + proxySocket.pipe(socket); + }); +}; + + exports.HttpProxy = HttpProxy;