diff --git a/lib/node-http-proxy/proxy-table.js b/lib/node-http-proxy/proxy-table.js index d5ec7fd..4841c8d 100644 --- a/lib/node-http-proxy/proxy-table.js +++ b/lib/node-http-proxy/proxy-table.js @@ -42,6 +42,7 @@ var ProxyTable = exports.ProxyTable = function (options) { events.EventEmitter.call(this); this.silent = options.silent || options.silent !== true; + this.target = options.target || {}; this.hostnameOnly = options.hostnameOnly === true; if (typeof options.router === 'object') { @@ -91,19 +92,62 @@ ProxyTable.prototype.setRoutes = function (router) { throw new Error('Cannot update ProxyTable routes without router.'); } + var self = this; this.router = router; if (this.hostnameOnly === false) { - var self = this; this.routes = []; Object.keys(router).forEach(function (path) { - var route = new RegExp('^' + path, 'i'); + if (!/http[s]?/.test(router[path])) { + router[path] = (self.target.https ? 'https://' : 'http://') + + router[path]; + } + var target = url.parse(router[path]), + defaultPort = self.target.https ? 443 : 80; + + // + // Setup a robust lookup table for the route: + // + // { + // source: { + // regexp: /^foo.com/i, + // sref: 'foo.com', + // url: { + // protocol: 'http:', + // slashes: true, + // host: 'foo.com', + // hostname: 'foo.com', + // href: 'http://foo.com/', + // pathname: '/', + // path: '/' + // } + // }, + // { + // target: { + // sref: '127.0.0.1:8000/', + // url: { + // protocol: 'http:', + // slashes: true, + // host: '127.0.0.1:8000', + // hostname: '127.0.0.1', + // href: 'http://127.0.0.1:8000/', + // pathname: '/', + // path: '/' + // } + // }, + // self.routes.push({ - route: route, - target: router[path], - path: path + source: { + regexp: new RegExp('^' + path, 'i'), + sref: path, + url: url.parse('http://' + path) + }, + target: { + sref: target.hostname + ':' + (target.port || defaultPort) + target.path, + url: target + } }); }); } @@ -137,22 +181,30 @@ ProxyTable.prototype.getProxyLocation = function (req) { target += req.url; for (var i in this.routes) { var route = this.routes[i]; - if (target.match(route.route)) { - var requrl = url.parse(req.url); - //add the 'http://'' to get around a url.parse bug, it won't actually be used. - var targeturl = url.parse('http://'+route.target); - var pathurl = url.parse('http://'+route.path); + if (target.match(route.source.regexp)) { + // + // Attempt to perform any path replacement for differences + // between the source path and the target path. This replaces the + // path's part of the URL to the target's part of the URL. + // + // 1. Parse the request URL + // 2. Replace any portions of the source path with the target path + // 3. Set the request URL to the formatted URL with replacements. + // + var parsed = url.parse(req.url); - //This replaces the path's part of the URL to the target's part of the URL. - requrl.pathname = requrl.pathname.replace(pathurl.pathname, targeturl.pathname); - req.url = url.format(requrl); + parsed.pathname = parsed.pathname.replace( + route.source.url.pathname, + route.target.url.pathname + ); - var host = targeturl.hostname, - port = targeturl.port || 80; + req.url = url.format(parsed); return { - port: port, - host: host + protocol: route.target.url.protocol.replace(':', ''), + host: route.target.url.hostname, + port: route.target.url.port + || (this.target.https ? 443 : 80) }; } } diff --git a/lib/node-http-proxy/routing-proxy.js b/lib/node-http-proxy/routing-proxy.js index b769246..0f87be4 100644 --- a/lib/node-http-proxy/routing-proxy.js +++ b/lib/node-http-proxy/routing-proxy.js @@ -47,8 +47,8 @@ var RoutingProxy = exports.RoutingProxy = function (options) { // Setup other default options to be used for instances of // `HttpProxy` created by this `RoutingProxy` instance. // - this.source = options.source || { host: 'localhost', port: 8000 }; - this.https = this.source.https || options.https; + this.source = options.source || { host: 'localhost', port: 8000 }; + this.https = this.source.https || options.https; this.enable = options.enable; this.forward = options.forward; @@ -88,8 +88,7 @@ RoutingProxy.prototype.add = function (options) { options.target.host = options.target.host || options.host; options.target.port = options.target.port || options.port; options.target.https = this.target && this.target.https || - options.target && options.target.https || - options.https; + options.target && options.target.https; // // Setup options to pass-thru to the new `HttpProxy` instance @@ -102,12 +101,15 @@ RoutingProxy.prototype.add = function (options) { }); this.proxies[key] = new HttpProxy(options); + if (this.listeners('proxyError').length > 0) { this.proxies[key].on('proxyError', this.emit.bind(this, 'proxyError')); } + if (this.listeners('webSocketProxyError').length > 0) { this.proxies[key].on('webSocketProxyError', this.emit.bind(this, 'webSocketProxyError')); } + this.proxies[key].on('start', this.emit.bind(this, 'start')); this.proxies[key].on('forward', this.emit.bind(this, 'forward')); this.proxies[key].on('end', this.emit.bind(this, 'end')); @@ -200,7 +202,13 @@ RoutingProxy.prototype.proxyRequest = function (req, res, options) { } var key = this._getKey(options), - proxy; + proxy; + + if ((this.target && this.target.https) + || (location && location.protocol === 'https')) { + options.target = options.target || {}; + options.target.https = true; + } if (!this.proxies[key]) { this.add(options);