Skip to content

feat(context): custom context matcher #59

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 23, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ Request URL's [ _path-absolute_ and _query_](https://tools.ietf.org/html/rfc3986
- `['/api', '/ajax', '/someotherpath']`

* **wildcard path matching**

For fine-grained control you can use wildcard matching. Glob pattern matching is done by _micromatch_. Visit [micromatch](https://www.npmjs.com/package/micromatch) or [glob](https://www.npmjs.com/package/glob) for more globbing examples.
- `'**'` matches any path, all requests will be proxied.
- `'**/*.html'` matches any path which ends with `.html`
Expand All @@ -102,6 +103,17 @@ Request URL's [ _path-absolute_ and _query_](https://tools.ietf.org/html/rfc3986
- `['/api/**', '/ajax/**']` combine multiple patterns
- `['/api/**', '!**/bad.json']` exclusion

* **custom matching**

For full control you can provide a custom filter function to determine which requests should be proxied or not.
```javascript
var filter = function (path, req) {
return (path.match('^/api') && req.method === 'GET');
};

var apiProxy = proxyMiddleware(filter, {target: 'http://www.example.org'})
```

## Shorthand

Use the shorthand syntax when verbose configuration is not needed. The `context` and `option.target` will be automatically configured when shorthand is used. Options can still be used if needed.
Expand Down
4 changes: 2 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ var httpProxyMiddleware = function(context, opts) {
req.url = req.originalUrl;
}

if (contextMatcher.match(config.context, req.url)) {
if (contextMatcher.match(config.context, req.url, req)) {
var activeProxyOptions = prepareProxyRequest(req);
proxy.web(req, res, activeProxyOptions);
} else {
Expand All @@ -62,7 +62,7 @@ var httpProxyMiddleware = function(context, opts) {
}

function handleUpgrade(req, socket, head) {
if (contextMatcher.match(config.context, req.url)) {
if (contextMatcher.match(config.context, req.url, req)) {
var activeProxyOptions = prepareProxyRequest(req);
proxy.ws(req, socket, head, activeProxyOptions);
logger.info('[HPM] Upgrading to WebSocket');
Expand Down
14 changes: 12 additions & 2 deletions lib/context-matcher.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
var _ = require('lodash');
var url = require('url');
var isGlob = require('is-glob');
var micromatch = require('micromatch');
Expand All @@ -6,15 +7,18 @@ module.exports = {
match: matchContext
};

function matchContext(context, uri) {
function matchContext(context, uri, req) {

// single path
if (isStringPath(context)) {
return matchSingleStringPath(context, uri);
}

// single glob path
if (isGlobPath(context)) {
return matchSingleGlobPath(context, uri);
}

// multi path
if (Array.isArray(context)) {
if (context.every(isStringPath)) {
Expand All @@ -27,6 +31,12 @@ function matchContext(context, uri) {
throw new Error('[HPM] Invalid context. Expecting something like: ["/api", "/ajax"] or ["/api/**", "!**.html"]');
}

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

throw new Error('[HPM] Invalid context. Expecting something like: "/api" or ["/api", "/ajax"]');
}

Expand Down Expand Up @@ -70,7 +80,7 @@ function getUrlPath(uri) {
}

function isStringPath(context) {
return typeof context === 'string' && !isGlob(context);
return _.isString(context) && !isGlob(context);
}

function isGlobPath(context) {
Expand Down
75 changes: 75 additions & 0 deletions recipes/context.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Context matching

## Path

This example will create a basic proxy.

Requests with path `/api` will be proxied to `http://localhost:3000`

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

var apiProxy = proxy('/api', {target: 'http://localhost:3000'});

// `/api/foo/bar` -> `http://localhost:3000/api/foo/bar`
```

## Multi Path

This example will create a basic proxy

Requests with path `/api` and `/rest` will be proxied to `http://localhost:3000`

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

var apiProxy = proxy(['/api', '/rest'], {target: 'http://localhost:3000'});

// `/api/foo/bar` -> `http://localhost:3000/api/foo/bar`
// `/rest/lorum/ipsum` -> `http://localhost:3000/rest/lorum/ipsum`
```

## Wildcard

This example will create a proxy with wildcard context matching.

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

var apiProxy = proxy('/api/**/*.json', {target: 'http://localhost:3000'});
```

## Multi Wildcard

This example will create a proxy with wildcard context matching.

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

var apiProxy = proxy(['/api/**', '/ajax/**'], {target: 'http://localhost:3000'});
```

## Wildcard / Exclusion

This example will create a proxy with wildcard context matching.

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

var apiProxy = proxy(['/api/**', '!**/bad.json'], {target: 'http://localhost:3000'});
```

## 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.

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

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

var apiProxy = proxy(filter, {target: 'http://localhost:3000'});
```
13 changes: 0 additions & 13 deletions recipes/context.path.md

This file was deleted.

14 changes: 0 additions & 14 deletions recipes/context.path.multi.md

This file was deleted.

9 changes: 0 additions & 9 deletions recipes/context.wildcard.exclusion.md

This file was deleted.

9 changes: 0 additions & 9 deletions recipes/context.wildcard.md

This file was deleted.

9 changes: 0 additions & 9 deletions recipes/context.wildcard.multi.md

This file was deleted.

Loading