From 698b01da8e1fe6195b00e5006032d262a0a86f4e Mon Sep 17 00:00:00 2001 From: Bradley Meck Date: Thu, 20 Sep 2012 10:54:29 -0500 Subject: [PATCH] [fix] spdy should look like https when forwarding (until we get a client) --- lib/node-http-proxy.js | 81 ++++++++++++++++--------------- lib/node-http-proxy/http-proxy.js | 7 ++- 2 files changed, 46 insertions(+), 42 deletions(-) diff --git a/lib/node-http-proxy.js b/lib/node-http-proxy.js index 4ab390c..c0c85a5 100644 --- a/lib/node-http-proxy.js +++ b/lib/node-http-proxy.js @@ -79,9 +79,9 @@ exports.createServer = function () { case 'number': port = arg; break; case 'object': options = arg || {}; break; case 'function': callback = arg; handlers.push(callback); break; - } + }; }); - + // // Helper function to create intelligent error message(s) // for the very liberal arguments parsing performed by @@ -90,35 +90,36 @@ exports.createServer = function () { function validArguments() { var conditions = { 'port and host': function () { - return port && host; + return port && host; }, 'options.target or options.router': function () { - return options && (options.router || + return options && (options.router || (options.target && options.target.host && options.target.port)); }, 'or proxy handlers': function () { return handlers && handlers.length; } - }; - + } + var missing = Object.keys(conditions).filter(function (name) { return !conditions[name](); }); - + if (missing.length === 3) { message = 'Cannot proxy without ' + missing.join(', '); return false; } - + return true; - } - + } + if (!validArguments()) { // - // If `host`, `port` and `options` are all not passed (with valid + // If `host`, `port` and `options` are all not passed (with valid // options) then this server is improperly configured. // throw new Error(message); + return; } // @@ -129,7 +130,7 @@ exports.createServer = function () { options.target = options.target || {}; options.target.port = options.target.port || port; options.target.host = options.target.host || host; - + if (options.target && options.target.host && options.target.port) { // // If an explicit `host` and `port` combination has been passed @@ -147,31 +148,31 @@ exports.createServer = function () { // we have to assume that this is a "go-anywhere" Proxy (i.e. a `RoutingProxy`). // proxy = new RoutingProxy(options); - + if (options.router) { // - // If a routing table has been supplied than we assume + // If a routing table has been supplied than we assume // the user intends us to add the "proxy" middleware layer - // for them + // for them // handlers.push(function (req, res) { proxy.proxyRequest(req, res); }); - + proxy.on('routes', function (routes) { server.emit('routes', routes); }); - } + } } - + // // Create the `http[s].Server` instance which will use // an instance of `httpProxy.HttpProxy`. // - handler = handlers.length > 1 + handler = handlers.length > 1 ? exports.stack(handlers, proxy) : function (req, res) { handlers[0](req, res, proxy) }; - + server = options.https ? https.createServer(options.https, handler) : http.createServer(handler); @@ -183,8 +184,8 @@ exports.createServer = function () { if (!callback) { // // If an explicit callback has not been supplied then - // automagically proxy the request using the `HttpProxy` - // instance we have created. + // automagically proxy the request using the `HttpProxy` + // instance we have created. // server.on('upgrade', function (req, socket, head) { proxy.proxyWebSocketRequest(req, socket, head); @@ -221,7 +222,7 @@ exports.createServer = function () { // exports.buffer = function (obj) { var events = [], - onData, + onData, onEnd; obj.on('data', onData = function (data, encoding) { @@ -239,11 +240,11 @@ exports.buffer = function (obj) { }, destroy: function () { this.end(); - this.resume = function () { - console.error("Cannot resume buffer after destroying it."); - }; - - onData = onEnd = events = obj = null; + this.resume = function () { + console.error("Cannot resume buffer after destroying it."); + }; + + onData = onEnd = events = obj = null; }, resume: function () { this.end(); @@ -277,10 +278,10 @@ exports.setMaxSockets = function (value) { // // ### function stack (middlewares, proxy) // #### @middlewares {Array} Array of functions to stack. -// #### @proxy {HttpProxy|RoutingProxy} Proxy instance to +// #### @proxy {HttpProxy|RoutingProxy} Proxy instance to // Iteratively build up a single handler to the `http.Server` // `request` event (i.e. `function (req, res)`) by wrapping -// each middleware `layer` into a `child` middleware which +// each middleware `layer` into a `child` middleware which // is in invoked by the parent (i.e. predecessor in the Array). // // adapted from https://github.com/creationix/stack @@ -294,17 +295,17 @@ exports.stack = function stack (middlewares, proxy) { if (err) { if (res._headerSent) { res.destroy(); - } + } else { res.statusCode = 500; res.setHeader('Content-Type', 'text/plain'); res.end('Internal Server Error'); } - + console.error('Error in middleware(s): %s', err.stack); return; } - + if (child) { child(req, res); } @@ -343,7 +344,7 @@ exports._getAgent = function _getAgent (options) { if (!options || !options.host) { throw new Error('`options.host` is required to create an Agent.'); } - + if (!options.port) { options.port = options.https ? 443 : 80; } @@ -351,21 +352,21 @@ exports._getAgent = function _getAgent (options) { var Agent = options.https ? https.Agent : http.Agent, agent; - agent = new Agent({ - host: options.host, + agent = new Agent({ + host: options.host, port: options.port }); agent.maxSockets = options.maxSockets || maxSockets; return agent; -}; +} // // ### function _getProtocol (options) // #### @options {Object} Options for the proxy target. -// Returns the appropriate node.js core protocol module (i.e. `http` or `https`) -// based on the `options` supplied. +// Returns the appropriate node.js core protocol module (i.e. `http` or `https`) +// based on the `options` supplied. // exports._getProtocol = function _getProtocol (options) { return options.https ? https : http; @@ -381,7 +382,7 @@ exports._getProtocol = function _getProtocol (options) { // exports._getBase = function _getBase (options) { var result = function () {}; - + if (options.https && typeof options.https === 'object') { ['ca', 'cert', 'key'].forEach(function (key) { if (options.https[key]) { diff --git a/lib/node-http-proxy/http-proxy.js b/lib/node-http-proxy/http-proxy.js index 5f606e2..704eec9 100644 --- a/lib/node-http-proxy/http-proxy.js +++ b/lib/node-http-proxy/http-proxy.js @@ -115,6 +115,9 @@ util.inherits(HttpProxy, events.EventEmitter); // #### @res {ServerResponse} Outgoing HTTP Request to write proxied data to. // #### @buffer {Object} Result from `httpProxy.buffer(req)` // +function getProto(req) { + return req.isSpdy ? 'https' : (req.connection.pair ? 'https' : 'http'); +} HttpProxy.prototype.proxyRequest = function (req, res, buffer) { var self = this, errState = false, @@ -148,11 +151,11 @@ HttpProxy.prototype.proxyRequest = function (req, res, buffer) { } if (req.headers['x-forwarded-proto']){ - var protoToAppend = "," + (req.connection.pair ? 'https' : 'http'); + var protoToAppend = "," + getProto(req); req.headers['x-forwarded-proto'] += protoToAppend; } else { - req.headers['x-forwarded-proto'] = req.connection.pair ? 'https' : 'http'; + req.headers['x-forwarded-proto'] = getProto(req); } }