Skip to content

Commit

Permalink
Merge pull request #5 from chimurai/path-rewrite
Browse files Browse the repository at this point in the history
feat: added rewritePath support
  • Loading branch information
chimurai committed Jul 8, 2015
2 parents 38d6512 + 9bc533c commit 15784f0
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 6 deletions.
10 changes: 9 additions & 1 deletion README.md
Expand Up @@ -48,6 +48,14 @@ Use the created `proxy` object as middleware in any middleware compatible server
## Options

* (DEPRECATED) **option.proxyHost**: Use `option.headers.host` instead.
* **option.rewritePath**: object, rewrite the url path. Object-keys will be used as _RegEx_ to match paths.

```javascript
{
"^/old/api" : "/new/api", // rewrite path
"^/remove/api" : "" // remove path
}
```

The following options are provided by the underlying [http-proxy](https://www.npmjs.com/package/http-proxy).
* **option.target**: url string to be parsed with the url module
Expand All @@ -61,7 +69,7 @@ The following options are provided by the underlying [http-proxy](https://www.np
Undocumented options are provided by the underlying [http-proxy](https://www.npmjs.com/package/http-proxy).
* **option.headers**: object, adds [request headers](https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Request_fields). (Example: `{host:'www.example.org'}` adds host to request header. Useful for [name-based virtual hosted](http://en.wikipedia.org/wiki/Virtual_hosting#Name-based) sites)

## Examples
## More Examples

To [view the examples](https://github.com/chimurai/http-proxy-middleware/tree/master/examples), clone the http-proxy-middleware repo and install the dependencies:

Expand Down
11 changes: 9 additions & 2 deletions index.js
Expand Up @@ -19,10 +19,17 @@ var httpProxyMiddleware = function (context, opts) {
proxyOptions.headers.host = proxyOptions.proxyHost;
}

// create proxy
var proxy = httpProxy.createProxyServer(proxyOptions);

// modify requests
// proxy.on('proxyReq', function () {});
// handle option.pathRewrite
if (proxyOptions.pathRewrite) {
var pathRewriter = utils.createPathRewriter(proxyOptions.pathRewrite);

proxy.on('proxyReq', function (proxyReq, req, res, options) {
handlers.proxyPathRewrite(proxyReq, pathRewriter);
});
}

// handle error and close connection properly
proxy.on('error', function (err, req, res) {
Expand Down
8 changes: 7 additions & 1 deletion lib/handlers.js
@@ -1,5 +1,6 @@
module.exports = {
proxyError : proxyError
proxyError : proxyError,
proxyPathRewrite : proxyPathRewrite
}

function proxyError (err, req, res, proxyOptions) {
Expand All @@ -10,3 +11,8 @@ function proxyError (err, req, res, proxyOptions) {

console.log('[HPM] Proxy error:', err.code, targetUri);
};

function proxyPathRewrite(proxyReq, fnRewriter) {
proxyReq.path = fnRewriter(proxyReq.path);
}

51 changes: 49 additions & 2 deletions lib/utils.js
@@ -1,10 +1,57 @@
var url = require('url');

module.exports = {
hasContext : hasContext
hasContext : hasContext,
createPathRewriter : createPathRewriter
}

function hasContext (context, uri) {
var urlPath = url.parse(uri).path;
return urlPath.indexOf(context) === 0;
};
}

/**
* Create rewrite function, to cache parsed rewrite rules.
*/
function createPathRewriter (config) {
var rules = parsePathRewriteRules(config);

return rewritePath;

function rewritePath (path) {
var result = path;

rules.forEach(function (rule) {
if (rule.regex.test(path)) {
result = result.replace(rule.regex, rule.value);
}
});

return result;
}
}

function parsePathRewriteRules (config) {
var rules = [];

if (isObject(config) === false) {
throw new Error('[HPM] Invalid pathRewrite config. Expecting an object literal with pathRewrite configuration');
}

for (var key in config) {
if (config.hasOwnProperty(key)) {
rules.push({
regex : new RegExp(key),
value : config[key]
});

console.log('[HPM] Proxy rewrite rule created: "' + key + '" -> "' + config[key] + '"');
}
}

return rules;
}

function isObject (val) {
return Object.prototype.toString.call(val) === '[object Object]' && typeof val === 'object';
}
32 changes: 32 additions & 0 deletions test/http-proxy-middleware.spec.js
Expand Up @@ -143,6 +143,38 @@ describe('http-proxy-middleware in actual server', function () {
});
});

describe('Rewrite path', function () {
var responseBody;

beforeEach(function (done) {
servers = createServers({
proxy: proxyMiddleware('/api', {
target:'http://localhost:8000',
pathRewrite: {
'^/api' : '/rest',
'^/remove' : '',
}
}),
sourceMiddleware : function (req, res, next) {next()},
targetMiddleware: function (req, res, next) {
res.write(req.url); // respond with req.url
res.end()
},
});

http.get('http://localhost:3000/api/foo/bar', function (res) {
res.on('data', function (chunk) {
responseBody = chunk.toString();
done();
});
});
});

it('should have response body with the rewritten req.url: "/rest/..."', function () {
expect(responseBody).to.equal('/rest/foo/bar');
});
});

afterEach(function () {
closeServers(servers);
servers = null;
Expand Down

2 comments on commit 15784f0

@gwbarrett
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although documented in the README.md as rewritePath, the code is actually using pathRewrite.

@chimurai
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gwbarrett Nice catch!

Will update the docs.

Please sign in to comment.