Skip to content

Commit ddea7e8

Browse files
committed
feat(ejectPlugins): skip loading default plugins
1 parent 4bc66b9 commit ddea7e8

File tree

5 files changed

+138
-14
lines changed

5 files changed

+138
-14
lines changed

README.md

+25
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ _All_ `http-proxy` [options](https://github.com/nodejitsu/node-http-proxy#option
7373
- [`pathRewrite` (object/function)](#pathrewrite-objectfunction)
7474
- [`router` (object/function)](#router-objectfunction)
7575
- [`plugins` (Array)](#plugins-array)
76+
- [`ejectPlugins` (boolean) default: `false`](#ejectplugins-boolean-default-false)
7677
- [`logger` (Object)](#logger-object)
7778
- [`http-proxy` events](#http-proxy-events)
7879
- [`http-proxy` options](#http-proxy-options)
@@ -286,6 +287,30 @@ const config = {
286287
};
287288
```
288289

290+
### `ejectPlugins` (boolean) default: `false`
291+
292+
If you're not satisfied with the pre-configured plugins, you can eject them by configuring `ejectPlugins: true`.
293+
294+
NOTE: register your own error handlers to prevent server from crashing.
295+
296+
```js
297+
// eject default plugins and manually add them back
298+
299+
const {
300+
debugProxyErrorsPlugin, // subscribe to proxy errors to prevent server from crashing
301+
loggerPlugin, // log proxy events to a logger (ie. console)
302+
errorResponsePlugin, // return 5xx response on proxy error
303+
proxyEventsPlugin, // implements the "on:" option
304+
} = require('http-proxy-middleware/plugins/default');
305+
306+
createProxyMiddleware({
307+
target: `http://example.org`,
308+
changeOrigin: true,
309+
ejectPlugins: true,
310+
plugins: [debugProxyErrorsPlugin, loggerPlugin, errorResponsePlugin, proxyEventsPlugin],
311+
});
312+
```
313+
289314
### `logger` (Object)
290315

291316
Configure a logger to output information from http-proxy-middleware: ie. `console`, `winston`, `pino`, `bunyan`, `log4js`, etc...

src/get-plugins.ts

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import type { Options, Plugin } from './types';
2+
import {
3+
debugProxyErrorsPlugin,
4+
loggerPlugin,
5+
errorResponsePlugin,
6+
proxyEventsPlugin,
7+
} from './plugins/default';
8+
9+
export function getPlugins(options: Options): Plugin[] {
10+
const defaultPlugins: Plugin[] = !!options.ejectPlugins
11+
? [] // no default plugins when ejecting
12+
: [debugProxyErrorsPlugin, proxyEventsPlugin, loggerPlugin, errorResponsePlugin];
13+
const userPlugins: Plugin[] = options.plugins ?? [];
14+
return [...defaultPlugins, ...userPlugins];
15+
}

src/http-proxy-middleware.ts

+3-14
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,11 @@ import type * as https from 'https';
22
import type { Request, RequestHandler, Options, Filter, Logger } from './types';
33
import * as httpProxy from 'http-proxy';
44
import { verifyConfig } from './configuration';
5+
import { getPlugins } from './get-plugins';
56
import { matchPathFilter } from './path-filter';
67
import { getLogger } from './logger';
78
import * as PathRewriter from './path-rewriter';
89
import * as Router from './router';
9-
import {
10-
debugProxyErrorsPlugin,
11-
loggerPlugin,
12-
errorResponsePlugin,
13-
proxyEventsPlugin,
14-
} from './plugins/default';
1510

1611
export class HttpProxyMiddleware {
1712
private logger: Logger;
@@ -81,14 +76,8 @@ export class HttpProxyMiddleware {
8176
};
8277

8378
private registerPlugins(proxy: httpProxy, options: Options) {
84-
const defaultPlugins = [
85-
debugProxyErrorsPlugin,
86-
proxyEventsPlugin,
87-
loggerPlugin,
88-
errorResponsePlugin,
89-
];
90-
const plugins = options.plugins ?? [];
91-
[...defaultPlugins, ...plugins].forEach((plugin) => plugin(proxy, options));
79+
const plugins = getPlugins(options);
80+
plugins.forEach((plugin) => plugin(proxy, options));
9281
}
9382

9483
private catchUpgradeRequest = (server: https.Server) => {

src/types.ts

+7
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,13 @@ export interface Options extends httpProxy.ServerOptions {
6262
* ```
6363
*/
6464
plugins?: Plugin[];
65+
/**
66+
* Eject pre-configured plugins.
67+
* NOTE: register your own error handlers to prevent server from crashing.
68+
*
69+
* @since v3.0.0
70+
*/
71+
ejectPlugins?: boolean;
6572
/**
6673
* Listen to http-proxy events
6774
* @see {@link OnProxyEvent} for available events

test/unit/get-plugins.spec.ts

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import { Plugin } from '../../src/types';
2+
import { getPlugins } from '../../src/get-plugins';
3+
import {
4+
debugProxyErrorsPlugin,
5+
loggerPlugin,
6+
errorResponsePlugin,
7+
proxyEventsPlugin,
8+
} from '../../src/plugins/default';
9+
10+
describe('getPlugins', () => {
11+
let plugins: Plugin[];
12+
13+
it('should return default plugins when no user plugins are provided', () => {
14+
plugins = getPlugins({});
15+
16+
expect(plugins).toHaveLength(4);
17+
expect(plugins.map((plugin) => plugin.name)).toMatchInlineSnapshot(`
18+
Array [
19+
"debugProxyErrorsPlugin",
20+
"proxyEventsPlugin",
21+
"loggerPlugin",
22+
"errorResponsePlugin",
23+
]
24+
`);
25+
});
26+
27+
it('should return no plugins when ejectPlugins is configured in option', () => {
28+
plugins = getPlugins({
29+
ejectPlugins: true,
30+
});
31+
32+
expect(plugins).toHaveLength(0);
33+
});
34+
35+
it('should return user plugins with default plugins when user plugins are provided', () => {
36+
const myPlugin: Plugin = () => {
37+
/* noop */
38+
};
39+
plugins = getPlugins({
40+
plugins: [myPlugin],
41+
});
42+
43+
expect(plugins).toHaveLength(5);
44+
expect(plugins.map((plugin) => plugin.name)).toMatchInlineSnapshot(`
45+
Array [
46+
"debugProxyErrorsPlugin",
47+
"proxyEventsPlugin",
48+
"loggerPlugin",
49+
"errorResponsePlugin",
50+
"myPlugin",
51+
]
52+
`);
53+
});
54+
55+
it('should only return user plugins when user plugins are provided with ejectPlugins option', () => {
56+
const myPlugin: Plugin = () => {
57+
/* noop */
58+
};
59+
plugins = getPlugins({
60+
ejectPlugins: true,
61+
plugins: [myPlugin],
62+
});
63+
64+
expect(plugins).toHaveLength(1);
65+
expect(plugins.map((plugin) => plugin.name)).toMatchInlineSnapshot(`
66+
Array [
67+
"myPlugin",
68+
]
69+
`);
70+
});
71+
72+
it('should return manually added default plugins in different order after using ejectPlugins', () => {
73+
plugins = getPlugins({
74+
ejectPlugins: true,
75+
plugins: [debugProxyErrorsPlugin, errorResponsePlugin, loggerPlugin, proxyEventsPlugin], // alphabetical order
76+
});
77+
78+
expect(plugins).toHaveLength(4);
79+
expect(plugins.map((plugin) => plugin.name)).toMatchInlineSnapshot(`
80+
Array [
81+
"debugProxyErrorsPlugin",
82+
"errorResponsePlugin",
83+
"loggerPlugin",
84+
"proxyEventsPlugin",
85+
]
86+
`);
87+
});
88+
});

0 commit comments

Comments
 (0)