From d96932b8dd492bfa4401d47e3ae3c1dd80dfc1e2 Mon Sep 17 00:00:00 2001
From: Mikkel Garcia <mikkel@255bits.com>
Date: Tue, 5 Mar 2013 17:08:44 -0700
Subject: [PATCH 1/3] pathnameOnly flag added.  Ignores hostname and applies
 routing table to the paths being requested.

---
 lib/node-http-proxy/proxy-table.js | 23 +++++++++++++++++++++--
 test/http/routing-table-test.js    |  8 ++++++++
 test/macros/http.js                |  1 +
 3 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/lib/node-http-proxy/proxy-table.js b/lib/node-http-proxy/proxy-table.js
index b12b577..87184e8 100644
--- a/lib/node-http-proxy/proxy-table.js
+++ b/lib/node-http-proxy/proxy-table.js
@@ -34,6 +34,7 @@ var util = require('util'),
 // #### @router {Object} Object containing the host based routes
 // #### @silent {Boolean} Value indicating whether we should suppress logs
 // #### @hostnameOnly {Boolean} Value indicating if we should route based on __hostname string only__
+// #### @pathnameOnly {Boolean} Value indicating if we should route based on only the pathname.  __This causes hostnames to be ignored.__.  Using this along with hostnameOnly wont work at all.
 // Constructor function for the ProxyTable responsible for getting
 // locations of proxy targets based on ServerRequest headers; specifically
 // the HTTP host header.
@@ -43,6 +44,7 @@ var ProxyTable = exports.ProxyTable = function (options) {
 
   this.silent       = options.silent || options.silent !== true;
   this.target       = options.target || {};
+  this.pathnameOnly = options.pathnameOnly === true;
   this.hostnameOnly = options.hostnameOnly === true;
 
   if (typeof options.router === 'object') {
@@ -164,8 +166,9 @@ ProxyTable.prototype.getProxyLocation = function (req) {
     return null;
   }
 
-  var target = req.headers.host.split(':')[0];
+  var targetHost = req.headers.host.split(':')[0];
   if (this.hostnameOnly === true) {
+    var target = targetHost;
     if (this.router.hasOwnProperty(target)) {
       var location = this.router[target].split(':'),
           host = location[0],
@@ -177,8 +180,24 @@ ProxyTable.prototype.getProxyLocation = function (req) {
       };
     }
   }
+  else if (this.pathnameOnly === true) {
+    var target = req.url;
+    for (var i in this.routes) {
+        var route = this.routes[i];
+        if (target.match(route.source.regexp)) {
+            req.url = url.format(target.replace(route.source.regexp, ''));
+            return {
+              protocol: route.target.url.protocol.replace(':', ''),
+              host: route.target.url.hostname,
+              port: route.target.url.port
+                || (this.target.https ? 443 : 80)
+            };
+        }
+    }
+
+  }
   else {
-    target += req.url;
+    var target = targetHost + req.url;
     for (var i in this.routes) {
       var route = this.routes[i];
       if (target.match(route.source.regexp)) {
diff --git a/test/http/routing-table-test.js b/test/http/routing-table-test.js
index f758bba..679c286 100644
--- a/test/http/routing-table-test.js
+++ b/test/http/routing-table-test.js
@@ -43,6 +43,14 @@ vows.describe(helpers.describe('routing-table')).addBatch({
         "bar.com": "127.0.0.1:{PORT}"
       }
     }),
+    "using pathnameOnly": macros.http.assertProxiedToRoutes({
+      pathnameOnly: true,
+      routes: {
+        "/foo": "127.0.0.1:{PORT}",
+        "/bar": "127.0.0.1:{PORT}",
+        "/pizza": "127.0.0.1:{PORT}"
+      }
+    }),
     "using a routing file": macros.http.assertProxiedToRoutes({
       filename: routeFile,
       routes: {
diff --git a/test/macros/http.js b/test/macros/http.js
index 767b7db..cf62ce9 100644
--- a/test/macros/http.js
+++ b/test/macros/http.js
@@ -220,6 +220,7 @@ exports.assertProxiedToRoutes = function (options, nested) {
     //
     proxy = {
       hostnameOnly: options.hostnameOnly,
+      pathnameOnly: options.pathnameOnly,
       router: options.routes
     };
   }
-- 
GitLab


From cbf39f502e742bce6f8e5a7663603e788855e2f2 Mon Sep 17 00:00:00 2001
From: Mikkel Garcia <mikkel@255bits.com>
Date: Tue, 5 Mar 2013 17:32:49 -0700
Subject: [PATCH 2/3] pathnameOnly option documented in the Readme.md

---
 README.md | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/README.md b/README.md
index fdedc3a..9dcce5c 100644
--- a/README.md
+++ b/README.md
@@ -202,6 +202,24 @@ var options = {
 
 Notice here that I have not included paths on the individual domains because this is not possible when using only the HTTP 'Host' header. Care to learn more? See [RFC2616: HTTP/1.1, Section 14.23, "Host"][4].
 
+### Proxy requests using a 'Pathname Only' ProxyTable
+
+If you dont care about forwarding to different hosts, you can redirect based on the request path.
+
+``` js
+var options = {
+  pathnameOnly: true,
+  router: {
+    '/wiki': '127.0.0.1:8001',
+    '/blog': '127.0.0.1:8002',
+    '/api':  '127.0.0.1:8003'
+  }
+}
+```
+
+This comes in handy if you are running separate services or applications on separate paths.  Note, using this option disables routing by hostname entirely.
+
+
 ### Proxy requests with an additional forward proxy
 Sometimes in addition to a reverse proxy, you may want your front-facing server to forward traffic to another location. For example, if you wanted to load test your staging environment. This is possible when using node-http-proxy using similar JSON-based configuration to a proxy table: 
 
-- 
GitLab


From 189950ec36c2c07575dab076b3c8c949486176ab Mon Sep 17 00:00:00 2001
From: Mikkel Garcia <mikkel@255bits.com>
Date: Tue, 5 Mar 2013 17:57:03 -0700
Subject: [PATCH 3/3] [doc] added comments to pathnameOnly block.

---
 lib/node-http-proxy/proxy-table.js | 29 +++++++++++++++++++----------
 1 file changed, 19 insertions(+), 10 deletions(-)

diff --git a/lib/node-http-proxy/proxy-table.js b/lib/node-http-proxy/proxy-table.js
index 87184e8..407ba47 100644
--- a/lib/node-http-proxy/proxy-table.js
+++ b/lib/node-http-proxy/proxy-table.js
@@ -183,16 +183,25 @@ ProxyTable.prototype.getProxyLocation = function (req) {
   else if (this.pathnameOnly === true) {
     var target = req.url;
     for (var i in this.routes) {
-        var route = this.routes[i];
-        if (target.match(route.source.regexp)) {
-            req.url = url.format(target.replace(route.source.regexp, ''));
-            return {
-              protocol: route.target.url.protocol.replace(':', ''),
-              host: route.target.url.hostname,
-              port: route.target.url.port
-                || (this.target.https ? 443 : 80)
-            };
-        }
+      var route = this.routes[i];
+      // 
+      // If we are matching pathname only, we remove the matched pattern.
+      // 
+      // IE /wiki/heartbeat
+      // is redirected to
+      // /heartbeat
+      //
+      // for the route "/wiki" : "127.0.0.1:8020"
+      //
+      if (target.match(route.source.regexp)) {
+        req.url = url.format(target.replace(route.source.regexp, ''));
+        return {
+          protocol: route.target.url.protocol.replace(':', ''),
+          host: route.target.url.hostname,
+          port: route.target.url.port
+            || (this.target.https ? 443 : 80)
+        };
+      }
     }
 
   }
-- 
GitLab