Skip to content

Commit

Permalink
Merge b942ac4 into 09926cd
Browse files Browse the repository at this point in the history
  • Loading branch information
chimurai committed Jun 16, 2016
2 parents 09926cd + b942ac4 commit 3d98a62
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 20 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,8 @@
# Changelog

## [develop](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.17.0)
- fix(wildcard context matching): Use [RFC 3986 path](https://tools.ietf.org/html/rfc3986#section-3.3) in wildcard matching. (excludes query parameters)

## [v0.16.0](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.16.0)
- deprecated(proxyTable): renamed `proxyTable` to `router`.
- feat(router): support for custom `router` function.
Expand Down
18 changes: 14 additions & 4 deletions README.md
Expand Up @@ -127,10 +127,20 @@ var app = express();

## Context matching

Providing an alternative way to decide which requests should be proxied; In case you are not able to use the server's [`path` parameter](http://expressjs.com/en/4x/api.html#app.use) to mount the proxy or when you need more flexibility. Request URL's [ _path-absolute_ and _query_](https://tools.ietf.org/html/rfc3986#section-3) will be used for context matching.
Providing an alternative way to decide which requests should be proxied; In case you are not able to use the server's [`path` parameter](http://expressjs.com/en/4x/api.html#app.use) to mount the proxy or when you need more flexibility.

The [RFC 3986 `path`](https://tools.ietf.org/html/rfc3986#section-3.3) is be used for context matching.

```
foo://example.com:8042/over/there?name=ferret#nose
\_/ \______________/\_________/ \_________/ \__/
| | | | |
scheme authority path query fragment
```

* **path matching**
- `proxy({...})` or `proxy('/', {...})` - matches any path, all requests will be proxied.
- `proxy({...})` - matches any path, all requests will be proxied.
- `proxy('/', {...})` - matches any path, all requests will be proxied.
- `proxy('/api', {...})` - matches paths starting with `/api`

* **multiple path matching**
Expand All @@ -153,8 +163,8 @@ Providing an alternative way to decide which requests should be proxied; In case
/**
* @return {Boolean}
*/
var filter = function (path, req) {
return (path.match('^/api') && req.method === 'GET');
var filter = function (pathname, req) {
return (pathname.match('^/api') && req.method === 'GET');
};

var apiProxy = proxy(filter, {target: 'http://www.example.org'})
Expand Down
22 changes: 14 additions & 8 deletions lib/context-matcher.js
Expand Up @@ -33,8 +33,8 @@ function matchContext(context, uri, req) {

// custom matching
if (_.isFunction(context)) {
var path = getUrlPath(uri);
return context(path, req);
var pathname = getUrlPathName(uri);
return context(pathname, req);
}

throw new Error('[HPM] Invalid context. Expecting something like: "/api" or ["/api", "/ajax"]');
Expand All @@ -46,13 +46,13 @@ function matchContext(context, uri, req) {
* @return {Boolean}
*/
function matchSingleStringPath(context, uri) {
var path = getUrlPath(uri);
return path.indexOf(context) === 0;
var pathname = getUrlPathName(uri);
return pathname.indexOf(context) === 0;
}

function matchSingleGlobPath(pattern, uri) {
var path = getUrlPath(uri);
var matches = micromatch(path, pattern);
var pathname = getUrlPathName(uri);
var matches = micromatch(pathname, pattern);
return matches && (matches.length > 0);
}

Expand All @@ -75,8 +75,14 @@ function matchMultiPath(contextList, uri) {
return false;
}

function getUrlPath(uri) {
return uri && url.parse(uri).path;
/**
* Parses URI and returns RFC 3986 path
*
* @param {String} uri from req.url
* @return {String} RFC 3986 path
*/
function getUrlPathName(uri) {
return uri && url.parse(uri).pathname;
}

function isStringPath(context) {
Expand Down
2 changes: 1 addition & 1 deletion package.json
@@ -1,6 +1,6 @@
{
"name": "http-proxy-middleware",
"version": "0.16.0",
"version": "0.17.0-beta",
"description": "The one-liner node.js proxy middleware for connect, express and browser-sync",
"main": "index.js",
"scripts": {
Expand Down
20 changes: 16 additions & 4 deletions recipes/context-matching.md
@@ -1,6 +1,18 @@
# Context matching

Determine which requests should be proxied. `http-proxy-middleware` offers several ways to do this:
Determine which requests should be proxied.

The [RFC 3986 `path`](https://tools.ietf.org/html/rfc3986#section-3.3) is be used for context matching.

```
foo://example.com:8042/over/there?name=ferret#nose
\_/ \______________/\_________/ \_________/ \__/
| | | | |
scheme authority path query fragment
```


`http-proxy-middleware` offers several ways to do this:

<!-- MarkdownTOC autolink=true bracket=round -->

Expand Down Expand Up @@ -76,13 +88,13 @@ var apiProxy = proxy(['/api/**', '!**/bad.json'], {target: 'http://localhost:300
## Custom filtering

This example will create a proxy with custom filtering.
The request `path` and `req` object are provided to determine which requests should be proxied or not.
The request `pathname` and `req` object are provided to determine which requests should be proxied or not.

```javascript
var proxy = require("http-proxy-middleware");

var filter = function (path, req) {
return (path.match('^/api') && req.method === 'GET');
var filter = function (pathname, req) {
return (pathname.match('^/api') && req.method === 'GET');
};

var apiProxy = proxy(filter, {target: 'http://localhost:3000'});
Expand Down
6 changes: 3 additions & 3 deletions test/unit/context-matcher.spec.js
Expand Up @@ -111,9 +111,9 @@ describe('Context Matching', function() {
expect(contextMatcher.match(pattern, 'http://localhost/some/path/index.html')).to.be.false;
});

it('should only match .php files with query params', function() {
expect(contextMatcher.match('/**/*.php', 'http://localhost/a/b/c.php?d=e&e=f')).to.be.false;
expect(contextMatcher.match('/**/*.php?*', 'http://localhost/a/b/c.php?d=e&e=f')).to.be.true;
it('should ignore query params', function() {
expect(contextMatcher.match('/**/*.php', 'http://localhost/a/b/c.php?d=e&e=f')).to.be.true;
expect(contextMatcher.match('/**/*.php?*', 'http://localhost/a/b/c.php?d=e&e=f')).to.be.false;
});

it('should only match any file in root path', function() {
Expand Down

0 comments on commit 3d98a62

Please sign in to comment.