Skip to content

Commit

Permalink
feat(legacyCreateProxyMiddleware): adapter with v2 behaviour (#754)
Browse files Browse the repository at this point in the history
* fix(error event): user error event handler replaces default error response handler

* feat(legacyCreateProxyMiddleware): adapter with legacy behavior

* test(on.error): test custom error handler

* chore(typescript): deprecate LegacyOptions

* docs: minor doc improvements
  • Loading branch information
chimurai authored Apr 18, 2022
1 parent 397aed3 commit cdfe934
Show file tree
Hide file tree
Showing 19 changed files with 624 additions and 28 deletions.
163 changes: 163 additions & 0 deletions MIGRATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
# Migration guide

- [v2 to v3 adapter](#v2-to-v3-adapter)
- [`legacyCreateProxyMiddleware`](#legacycreateproxymiddleware)
- [v3 breaking changes](#v3-breaking-changes)
- [Removed `req.url` patching](#removed-requrl-patching)
- [`pathRewrite` (potential behavior change)](#pathrewrite-potential-behavior-change)
- [Removed "shorthand" usage](#removed-shorthand-usage)
- [Removed `context` argument](#removed-context-argument)
- [Removed `logProvider` and `logLevel` options](#removed-logprovider-and-loglevel-options)
- [Refactored proxy events](#refactored-proxy-events)

## v2 to v3 adapter

### `legacyCreateProxyMiddleware`

Use the adapter to use v3 with minimal changes to your v2 implementation.

NOTE: `legacyCreateProxyMiddleware` will be removed in a future version.

```js
// before
const { createProxyMiddleware } = require('http-proxy-middleware');

createProxyMiddleware(...);

// after
const { legacyCreateProxyMiddleware } = require('http-proxy-middleware');

legacyCreateProxyMiddleware(...);
```

```ts
// before
import { createProxyMiddleware, Options } from 'http-proxy-middleware';

createProxyMiddleware(...);

// after
import { legacyCreateProxyMiddleware, LegacyOptions } from 'http-proxy-middleware';

legacyCreateProxyMiddleware(...);
```

## v3 breaking changes

### Removed `req.url` patching

```js
// before
app.use('/user', proxy({ target: 'http://www.example.org' }));

// after
app.use('/user', proxy({ target: 'http://www.example.org/user' }));
```

### `pathRewrite` (potential behavior change)

Related to removal of [`req.url` patching](#removed-requrl-patching).

`pathRewrite` now only rewrites the `path` after the mount point.

It was common to rewrite the `basePath` with the `pathRewrite` option:

```js
// before
app.use('/user', proxy({
target: 'http://www.example.org'
pathRewrite: { '^/user': '/secret' }
}));

// after
app.use('/user', proxy({ target: 'http://www.example.org/secret' }));
```

When proxy is mounted at the root, `pathRewrite` should still work as in v2.

```js
// not affected
app.use(proxy({
target: 'http://www.example.org'
pathRewrite: { '^/user': '/secret' }
}));
```

### Removed "shorthand" usage

Specify the `target` option.

```js
// before
createProxyMiddleware('http:/www.example.org');

// after
createProxyMiddleware({ target: 'http:/www.example.org' });
```

### Removed `context` argument

The `context` argument has been moved to option: `pathFilter`.

Functionality did not change.

See [recipes/pathFilter.md](./recipes/pathFilter.md) for more information.

```js
// before
createProxyMiddleware('/path', { target: 'http://www.example.org' });

// after
createProxyMiddleware({
target: 'http://www.example.org',
pathFilter: '/path',
});
```

### Removed `logProvider` and `logLevel` options

Use your external logging library to _log_ and control the logging _level_.

Only `info`, `warn`, `error` are used internally for compatibility across different loggers.

If you use `winston`, make sure to enable interpolation: <https://github.com/winstonjs/winston#string-interpolation>

See [recipes/logger.md](./recipes/logger.md) for more information.

```js
// new
createProxyMiddleware({
target: 'http://www.example.org',
logger: console,
});
```

### Refactored proxy events

See [recipes/proxy-events.md](./recipes/proxy-events.md) for more information.

```js
// before
createProxyMiddleware({
target: 'http://www.example.org',
onError: () => {},
onProxyReq: () => {},
onProxyRes: () => {},
onProxyReqWs: () => {},
onOpen: () => {},
onClose: () => {},
});

// after
createProxyMiddleware({
target: 'http://www.example.org',
on: {
error: () => {},
proxyReq: () => {},
proxyRes: () => {},
proxyReqWs: () => {},
open: () => {},
close: () => {},
},
});
```
44 changes: 33 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,21 @@ Powered by the popular Nodejitsu [`http-proxy`](https://github.com/nodejitsu/nod

## ⚠️ Note <!-- omit in toc -->

This page is showing documentation for version v2.x.x ([release notes](https://github.com/chimurai/http-proxy-middleware/releases))
This page is showing documentation for version v3.x.x ([release notes](https://github.com/chimurai/http-proxy-middleware/releases))

If you're looking for v0.x documentation. Go to:
https://github.com/chimurai/http-proxy-middleware/tree/v0.21.0#readme
See [MIGRATION.md](https://github.com/chimurai/http-proxy-middleware/blob/master/MIGRATION.md) for details on how to migrate from v2.x.x to v3.x.x

If you're looking for older documentation. Go to:

- <https://github.com/chimurai/http-proxy-middleware/tree/v2.0.4#readme>
- <https://github.com/chimurai/http-proxy-middleware/tree/v0.21.0#readme>

## TL;DR <!-- omit in toc -->

Proxy `/api` requests to `http://www.example.org`

:bulb: **Tip:** Set the option `changeOrigin` to `true` for [name-based virtual hosted sites](http://en.wikipedia.org/wiki/Virtual_hosting#Name-based).

```javascript
// javascript

Expand All @@ -30,8 +36,12 @@ const app = express();

app.use(
'/api',
createProxyMiddleware({ target: 'http://www.example.org/secret', changeOrigin: true })
createProxyMiddleware({
target: 'http://www.example.org/secret',
changeOrigin: true,
})
);

app.listen(3000);

// proxy and change the base path from "/api" to "/secret"
Expand All @@ -48,8 +58,12 @@ const app = express();

app.use(
'/api',
createProxyMiddleware({ target: 'http://www.example.org/api', changeOrigin: true })
createProxyMiddleware({
target: 'http://www.example.org/api',
changeOrigin: true,
})
);

app.listen(3000);

// proxy and keep the same base path "/api"
Expand All @@ -58,8 +72,6 @@ app.listen(3000);

_All_ `http-proxy` [options](https://github.com/nodejitsu/node-http-proxy#options) can be used, along with some extra `http-proxy-middleware` [options](#options).

:bulb: **Tip:** Set the option `changeOrigin` to `true` for [name-based virtual hosted sites](http://en.wikipedia.org/wiki/Virtual_hosting#Name-based).

## Table of Contents <!-- omit in toc -->

<!-- // spell-checker:disable -->
Expand Down Expand Up @@ -160,9 +172,9 @@ app.use(

`app.use` documentation:

- express: http://expressjs.com/en/4x/api.html#app.use
- connect: https://github.com/senchalabs/connect#mount-middleware
- polka: https://github.com/lukeed/polka#usebase-fn
- express: <http://expressjs.com/en/4x/api.html#app.use>
- connect: <https://github.com/senchalabs/connect#mount-middleware>
- polka: <https://github.com/lukeed/polka#usebase-fn>

## Options

Expand Down Expand Up @@ -302,7 +314,7 @@ const {
loggerPlugin, // log proxy events to a logger (ie. console)
errorResponsePlugin, // return 5xx response on proxy error
proxyEventsPlugin, // implements the "on:" option
} = require('http-proxy-middleware/plugins/default');
} = require('http-proxy-middleware');

createProxyMiddleware({
target: `http://example.org`,
Expand All @@ -316,6 +328,10 @@ createProxyMiddleware({
Configure a logger to output information from http-proxy-middleware: ie. `console`, `winston`, `pino`, `bunyan`, `log4js`, etc...
Only `info`, `warn`, `error` are used internally for compatibility across different loggers.
If you use `winston`, make sure to enable interpolation: <https://github.com/winstonjs/winston#string-interpolation>
See also logger recipes ([recipes/logger.md](https://github.com/chimurai/http-proxy-middleware/blob/master/recipes/logger.md)) for more details.
```javascript
Expand Down Expand Up @@ -424,29 +440,35 @@ The following options are provided by the underlying [http-proxy](https://github
- **option.autoRewrite**: rewrites the location host/port on (301/302/307/308) redirects based on requested host/port. Default: false.
- **option.protocolRewrite**: rewrites the location protocol on (301/302/307/308) redirects to 'http' or 'https'. Default: null.
- **option.cookieDomainRewrite**: rewrites domain of `set-cookie` headers. Possible values:
- `false` (default): disable cookie rewriting
- String: new domain, for example `cookieDomainRewrite: "new.domain"`. To remove the domain, use `cookieDomainRewrite: ""`.
- Object: mapping of domains to new domains, use `"*"` to match all domains.
For example keep one domain unchanged, rewrite one domain and remove other domains:
```json
cookieDomainRewrite: {
"unchanged.domain": "unchanged.domain",
"old.domain": "new.domain",
"*": ""
}
```
- **option.cookiePathRewrite**: rewrites path of `set-cookie` headers. Possible values:
- `false` (default): disable cookie rewriting
- String: new path, for example `cookiePathRewrite: "/newPath/"`. To remove the path, use `cookiePathRewrite: ""`. To set path to root use `cookiePathRewrite: "/"`.
- Object: mapping of paths to new paths, use `"*"` to match all paths.
For example, to keep one path unchanged, rewrite one path and remove other paths:
```json
cookiePathRewrite: {
"/unchanged.path/": "/unchanged.path/",
"/old.path/": "/new.path/",
"*": ""
}
```
- **option.headers**: object, adds [request headers](https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Request_fields). (Example: `{host:'www.example.org'}`)
- **option.proxyTimeout**: timeout (in millis) when proxy receives no response from target
- **option.timeout**: timeout (in millis) for incoming requests
Expand Down
11 changes: 9 additions & 2 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,21 @@
"language": "en",
"spellCheckDelayMs": 500,
"dictionaries": ["node", "npm", "typescript", "contributors"],
"ignorePaths": ["node_modules/**", "coverage/**", "dist/**", "package.json", "yarn.lock"],
"ignorePaths": [
"node_modules/**",
"coverage/**",
"dist/**",
"package.json",
"yarn.lock",
"*.tgz"
],
"dictionaryDefinitions": [
{
"name": "contributors",
"path": "CONTRIBUTORS.txt"
}
],
"ignoreRegExpList": ["[a-z]+path"],
"ignoreRegExpList": ["[a-z]+path", "\\]\\(#[a-z-]+\\)"],
"words": [
"camelcase",
"codesandbox",
Expand Down
1 change: 0 additions & 1 deletion examples/connect/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ const { createProxyMiddleware } = require('../../dist'); // require('http-proxy-
const jsonPlaceholderProxy = createProxyMiddleware({
target: 'http://jsonplaceholder.typicode.com/users',
changeOrigin: true, // for vhosted sites, changes host header to match to target's host
logLevel: 'debug',
});

const app = connect();
Expand Down
1 change: 0 additions & 1 deletion examples/express/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ const { createProxyMiddleware } = require('../../dist'); // require('http-proxy-
const jsonPlaceholderProxy = createProxyMiddleware({
target: 'http://jsonplaceholder.typicode.com/users',
changeOrigin: true, // for vhosted sites, changes host header to match to target's host
logLevel: 'debug',
logger: console,
});

Expand Down
2 changes: 1 addition & 1 deletion recipes/proxy-events.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Proxy Events

Subscribe to [`http-proxy`](https://github.com/nodejitsu/node-http-proxy) [![GitHub stars](https://img.shields.io/github/stars/nodejitsu/node-http-proxy.svg?style=social&label=Star)](https://github.com/nodejitsu/node-http-proxy) events: `error`, `proxyReq`, `proxyReqWs`, `proxyRes`, `open`, `close`, `start`, `end`, `econnreset`.
Subscribe to `http-proxy` events: `error`, `proxyReq`, `proxyReqWs`, `proxyRes`, `open`, `close`, `start`, `end`, `econnreset`.

## on.error

Expand Down
9 changes: 6 additions & 3 deletions recipes/websocket.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ This example will create a proxy middleware with websocket support.
```javascript
const { createProxyMiddleware } = require('http-proxy-middleware');

const socketProxy = createProxyMiddleware('/socket', {
const socketProxy = createProxyMiddleware({
target: 'http://localhost:3000',
pathFilter: '/socket',
ws: true,
});
```
Expand All @@ -21,12 +22,13 @@ const { createProxyMiddleware } = require('http-proxy-middleware');
const options = {
target: 'http://localhost:3000',
ws: true,
pathFilter: '/socket',
pathRewrite: {
'^/socket': '',
},
};

const socketProxy = createProxyMiddleware('/socket', options);
const socketProxy = createProxyMiddleware(options);
```

## WebSocket - Server update subscription
Expand All @@ -38,8 +40,9 @@ Subscribe to server's upgrade event.
```javascript
const { createProxyMiddleware } = require('http-proxy-middleware');

const socketProxy = createProxyMiddleware('/socket', {
const socketProxy = createProxyMiddleware({
target: 'http://localhost:3000',
pathFilter: '/socket',
ws: true,
});

Expand Down
5 changes: 4 additions & 1 deletion src/get-plugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ import {
} from './plugins/default';

export function getPlugins(options: Options): Plugin[] {
// don't load default errorResponsePlugin if user has specified their own
const maybeErrorResponsePlugin = !!options.on?.error ? [] : [errorResponsePlugin];

const defaultPlugins: Plugin[] = !!options.ejectPlugins
? [] // no default plugins when ejecting
: [debugProxyErrorsPlugin, proxyEventsPlugin, loggerPlugin, errorResponsePlugin];
: [debugProxyErrorsPlugin, proxyEventsPlugin, loggerPlugin, ...maybeErrorResponsePlugin];
const userPlugins: Plugin[] = options.plugins ?? [];
return [...defaultPlugins, ...userPlugins];
}
Loading

0 comments on commit cdfe934

Please sign in to comment.