http-proxy-middleware 2.0.6 → 3.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +280 -211
  2. package/dist/configuration.d.ts +2 -0
  3. package/dist/configuration.js +10 -0
  4. package/dist/debug.d.ts +5 -0
  5. package/dist/debug.js +8 -0
  6. package/dist/errors.d.ts +1 -1
  7. package/dist/errors.js +1 -1
  8. package/dist/get-plugins.d.ts +2 -0
  9. package/dist/get-plugins.js +15 -0
  10. package/dist/handlers/fix-request-body.d.ts +4 -1
  11. package/dist/handlers/index.js +5 -1
  12. package/dist/handlers/response-interceptor.d.ts +3 -2
  13. package/dist/handlers/response-interceptor.js +10 -1
  14. package/dist/http-proxy-middleware.d.ts +4 -11
  15. package/dist/http-proxy-middleware.js +39 -50
  16. package/dist/index.d.ts +13 -3
  17. package/dist/index.js +15 -3
  18. package/dist/legacy/create-proxy-middleware.d.ts +13 -0
  19. package/dist/legacy/create-proxy-middleware.js +17 -0
  20. package/dist/legacy/index.d.ts +1 -0
  21. package/dist/legacy/index.js +17 -0
  22. package/dist/legacy/options-adapter.d.ts +6 -0
  23. package/dist/legacy/options-adapter.js +92 -0
  24. package/dist/legacy/public.d.ts +2 -0
  25. package/dist/legacy/public.js +5 -0
  26. package/dist/legacy/types.d.ts +112 -0
  27. package/dist/legacy/types.js +2 -0
  28. package/dist/logger.d.ts +2 -14
  29. package/dist/logger.js +20 -129
  30. package/dist/path-filter.d.ts +4 -0
  31. package/dist/{context-matcher.js → path-filter.js} +24 -24
  32. package/dist/path-rewriter.js +6 -6
  33. package/dist/plugins/default/debug-proxy-errors-plugin.d.ts +6 -0
  34. package/dist/plugins/default/debug-proxy-errors-plugin.js +61 -0
  35. package/dist/plugins/default/error-response-plugin.d.ts +2 -0
  36. package/dist/plugins/default/error-response-plugin.js +19 -0
  37. package/dist/plugins/default/index.d.ts +4 -0
  38. package/dist/plugins/default/index.js +20 -0
  39. package/dist/plugins/default/logger-plugin.d.ts +2 -0
  40. package/dist/plugins/default/logger-plugin.js +44 -0
  41. package/dist/plugins/default/proxy-events.d.ts +22 -0
  42. package/dist/plugins/default/proxy-events.js +33 -0
  43. package/dist/router.js +7 -7
  44. package/dist/status-code.d.ts +1 -0
  45. package/dist/status-code.js +24 -0
  46. package/dist/types.d.ts +109 -38
  47. package/dist/utils/function.d.ts +1 -0
  48. package/dist/utils/function.js +8 -0
  49. package/package.json +37 -45
  50. package/dist/_handlers.d.ts +0 -4
  51. package/dist/_handlers.js +0 -84
  52. package/dist/config-factory.d.ts +0 -6
  53. package/dist/config-factory.js +0 -80
  54. package/dist/context-matcher.d.ts +0 -2
package/README.md CHANGED
@@ -1,25 +1,31 @@
1
1
  # http-proxy-middleware
2
2
 
3
- [![GitHub Workflow Status (branch)](https://img.shields.io/github/workflow/status/chimurai/http-proxy-middleware/CI/master?style=flat-square)](https://github.com/chimurai/http-proxy-middleware/actions?query=branch%3Amaster)
4
- [![Coveralls](https://img.shields.io/coveralls/chimurai/http-proxy-middleware.svg?style=flat-square)](https://coveralls.io/r/chimurai/http-proxy-middleware)
5
- [![dependency Status](https://snyk.io/test/npm/http-proxy-middleware/badge.svg?style=flat-square)](https://snyk.io/test/npm/http-proxy-middleware)
6
- [![npm](https://img.shields.io/npm/v/http-proxy-middleware?color=%23CC3534&style=flat-square)](https://www.npmjs.com/package/http-proxy-middleware)
3
+ [![GitHub Workflow Status (with branch)](https://img.shields.io/github/actions/workflow/status/chimurai/http-proxy-middleware/ci.yml?branch=master&logo=github-actions&logoColor=white&style=flat-square)](https://github.com/chimurai/http-proxy-middleware/actions/workflows/ci.yml?query=branch%3Amaster)
4
+ [![Coveralls](https://img.shields.io/coveralls/chimurai/http-proxy-middleware.svg?style=flat-square&logo=coveralls)](https://coveralls.io/r/chimurai/http-proxy-middleware)
5
+ [![Snyk Vulnerabilities for GitHub Repo](https://img.shields.io/snyk/vulnerabilities/github/chimurai/http-proxy-middleware?logo=snyk&style=flat-square)](https://security.snyk.io/package/npm/http-proxy-middleware)
6
+ [![npm](https://img.shields.io/npm/v/http-proxy-middleware?color=%23CC3534&style=flat-square&logo=npm)](https://www.npmjs.com/package/http-proxy-middleware)
7
7
 
8
- Node.js proxying made simple. Configure proxy middleware with ease for [connect](https://github.com/senchalabs/connect), [express](https://github.com/strongloop/express), [browser-sync](https://github.com/BrowserSync/browser-sync) and [many more](#compatible-servers).
8
+ Node.js proxying made simple. Configure proxy middleware with ease for [connect](https://github.com/senchalabs/connect), [express](https://github.com/expressjs/express), [next.js](https://github.com/vercel/next.js) and [many more](#compatible-servers).
9
9
 
10
- Powered by the popular Nodejitsu [`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)
10
+ Powered by the popular Nodejitsu [`http-proxy`](https://github.com/http-party/node-http-proxy). [![GitHub stars](https://img.shields.io/github/stars/http-party/node-http-proxy.svg?style=social&label=Star)](https://github.com/http-party/node-http-proxy)
11
11
 
12
12
  ## ⚠️ Note <!-- omit in toc -->
13
13
 
14
- This page is showing documentation for version v2.x.x ([release notes](https://github.com/chimurai/http-proxy-middleware/releases))
14
+ This page is showing documentation for version v3.x.x ([release notes](https://github.com/chimurai/http-proxy-middleware/releases))
15
15
 
16
- If you're looking for v0.x documentation. Go to:
17
- https://github.com/chimurai/http-proxy-middleware/tree/v0.21.0#readme
16
+ 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
17
+
18
+ If you're looking for older documentation. Go to:
19
+
20
+ - <https://github.com/chimurai/http-proxy-middleware/tree/v2.0.4#readme>
21
+ - <https://github.com/chimurai/http-proxy-middleware/tree/v0.21.0#readme>
18
22
 
19
23
  ## TL;DR <!-- omit in toc -->
20
24
 
21
25
  Proxy `/api` requests to `http://www.example.org`
22
26
 
27
+ :bulb: **Tip:** Set the option `changeOrigin` to `true` for [name-based virtual hosted sites](http://en.wikipedia.org/wiki/Virtual_hosting#Name-based).
28
+
23
29
  ```javascript
24
30
  // javascript
25
31
 
@@ -28,10 +34,18 @@ const { createProxyMiddleware } = require('http-proxy-middleware');
28
34
 
29
35
  const app = express();
30
36
 
31
- app.use('/api', createProxyMiddleware({ target: 'http://www.example.org', changeOrigin: true }));
37
+ app.use(
38
+ '/api',
39
+ createProxyMiddleware({
40
+ target: 'http://www.example.org/secret',
41
+ changeOrigin: true,
42
+ })
43
+ );
44
+
32
45
  app.listen(3000);
33
46
 
34
- // http://localhost:3000/api/foo/bar -> http://www.example.org/api/foo/bar
47
+ // proxy and change the base path from "/api" to "/secret"
48
+ // http://127.0.0.1:3000/api/foo/bar -> http://www.example.org/secret/foo/bar
35
49
  ```
36
50
 
37
51
  ```typescript
@@ -42,32 +56,45 @@ import { createProxyMiddleware, Filter, Options, RequestHandler } from 'http-pro
42
56
 
43
57
  const app = express();
44
58
 
45
- app.use('/api', createProxyMiddleware({ target: 'http://www.example.org', changeOrigin: true }));
59
+ app.use(
60
+ '/api',
61
+ createProxyMiddleware({
62
+ target: 'http://www.example.org/api',
63
+ changeOrigin: true,
64
+ })
65
+ );
66
+
46
67
  app.listen(3000);
47
68
 
48
- // http://localhost:3000/api/foo/bar -> http://www.example.org/api/foo/bar
69
+ // proxy and keep the same base path "/api"
70
+ // http://127.0.0.1:3000/api/foo/bar -> http://www.example.org/api/foo/bar
49
71
  ```
50
72
 
51
73
  _All_ `http-proxy` [options](https://github.com/nodejitsu/node-http-proxy#options) can be used, along with some extra `http-proxy-middleware` [options](#options).
52
74
 
53
- :bulb: **Tip:** Set the option `changeOrigin` to `true` for [name-based virtual hosted sites](http://en.wikipedia.org/wiki/Virtual_hosting#Name-based).
54
-
55
75
  ## Table of Contents <!-- omit in toc -->
56
76
 
77
+ <!-- // spell-checker:disable -->
78
+
57
79
  - [Install](#install)
58
- - [Core concept](#core-concept)
59
- - [Example](#example)
60
- - [Context matching](#context-matching)
61
- - [Options](#options)
62
- - [http-proxy-middleware options](#http-proxy-middleware-options)
63
- - [http-proxy events](#http-proxy-events)
64
- - [http-proxy options](#http-proxy-options)
65
- - [Shorthand](#shorthand)
80
+ - [Basic usage](#basic-usage)
81
+ - [Express Server Example](#express-server-example)
66
82
  - [app.use(path, proxy)](#appusepath-proxy)
83
+ - [Options](#options)
84
+ - [`pathFilter` (string, \[\]string, glob, \[\]glob, function)](#pathfilter-string-string-glob-glob-function)
85
+ - [`pathRewrite` (object/function)](#pathrewrite-objectfunction)
86
+ - [`router` (object/function)](#router-objectfunction)
87
+ - [`plugins` (Array)](#plugins-array)
88
+ - [`ejectPlugins` (boolean) default: `false`](#ejectplugins-boolean-default-false)
89
+ - [`logger` (Object)](#logger-object)
90
+ - [`http-proxy` events](#http-proxy-events)
91
+ - [`http-proxy` options](#http-proxy-options)
67
92
  - [WebSocket](#websocket)
68
93
  - [External WebSocket upgrade](#external-websocket-upgrade)
69
94
  - [Intercept and manipulate requests](#intercept-and-manipulate-requests)
70
95
  - [Intercept and manipulate responses](#intercept-and-manipulate-responses)
96
+ - [Node.js 17+: ECONNREFUSED issue with IPv6 and localhost (#705)](#nodejs-17-econnrefused-issue-with-ipv6-and-localhost-705)
97
+ - [Debugging](#debugging)
71
98
  - [Working examples](#working-examples)
72
99
  - [Recipes](#recipes)
73
100
  - [Compatible servers](#compatible-servers)
@@ -75,45 +102,35 @@ _All_ `http-proxy` [options](https://github.com/nodejitsu/node-http-proxy#option
75
102
  - [Changelog](#changelog)
76
103
  - [License](#license)
77
104
 
105
+ <!-- // spell-checker:enable -->
106
+
78
107
  ## Install
79
108
 
80
- ```bash
81
- $ npm install --save-dev http-proxy-middleware
109
+ ```shell
110
+ npm install --save-dev http-proxy-middleware
82
111
  ```
83
112
 
84
- ## Core concept
85
-
86
- Proxy middleware configuration.
113
+ ## Basic usage
87
114
 
88
- #### createProxyMiddleware([context,] config)
115
+ Create and configure a proxy middleware with: `createProxyMiddleware(config)`.
89
116
 
90
117
  ```javascript
91
118
  const { createProxyMiddleware } = require('http-proxy-middleware');
92
119
 
93
- const apiProxy = createProxyMiddleware('/api', { target: 'http://www.example.org' });
94
- // \____/ \_____________________________/
95
- // | |
96
- // context options
120
+ const apiProxy = createProxyMiddleware({
121
+ target: 'http://www.example.org',
122
+ changeOrigin: true,
123
+ });
97
124
 
98
125
  // 'apiProxy' is now ready to be used as middleware in a server.
99
126
  ```
100
127
 
101
- - **context**: Determine which requests should be proxied to the target host.
102
- (more on [context matching](#context-matching))
103
128
  - **options.target**: target host to proxy to. _(protocol + host)_
129
+ - **options.changeOrigin**: for virtual hosted sites
104
130
 
105
- (full list of [`http-proxy-middleware` configuration options](#options))
131
+ - see full list of [`http-proxy-middleware` configuration options](#options)
106
132
 
107
- #### createProxyMiddleware(uri [, config])
108
-
109
- ```javascript
110
- // shorthand syntax for the example above:
111
- const apiProxy = createProxyMiddleware('http://www.example.org/api');
112
- ```
113
-
114
- More about the [shorthand configuration](#shorthand).
115
-
116
- ## Example
133
+ ## Express Server Example
117
134
 
118
135
  An example with `express` server.
119
136
 
@@ -122,65 +139,68 @@ An example with `express` server.
122
139
  const express = require('express');
123
140
  const { createProxyMiddleware } = require('http-proxy-middleware');
124
141
 
125
- // proxy middleware options
126
- /** @type {import('http-proxy-middleware/dist/types').Options} */
127
- const options = {
128
- target: 'http://www.example.org', // target host
129
- changeOrigin: true, // needed for virtual hosted sites
130
- ws: true, // proxy websockets
131
- pathRewrite: {
132
- '^/api/old-path': '/api/new-path', // rewrite path
133
- '^/api/remove/path': '/path', // remove base path
134
- },
135
- router: {
136
- // when request.headers.host == 'dev.localhost:3000',
137
- // override target 'http://www.example.org' to 'http://localhost:8000'
138
- 'dev.localhost:3000': 'http://localhost:8000',
139
- },
140
- };
142
+ const app = express();
141
143
 
142
- // create the proxy (without context)
143
- const exampleProxy = createProxyMiddleware(options);
144
+ // create the proxy
145
+ /** @type {import('http-proxy-middleware/dist/types').RequestHandler<express.Request, express.Response>} */
146
+ const exampleProxy = createProxyMiddleware({
147
+ target: 'http://www.example.org/api', // target host with the same base path
148
+ changeOrigin: true, // needed for virtual hosted sites
149
+ });
144
150
 
145
151
  // mount `exampleProxy` in web server
146
- const app = express();
147
152
  app.use('/api', exampleProxy);
148
153
  app.listen(3000);
149
154
  ```
150
155
 
151
- ## Context matching
152
-
153
- 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.
156
+ ### app.use(path, proxy)
154
157
 
155
- [RFC 3986 `path`](https://tools.ietf.org/html/rfc3986#section-3.3) is used for context matching.
158
+ If you want to use the server's `app.use` `path` parameter to match requests.
159
+ Use `pathFilter` option to further include/exclude requests which you want to proxy.
156
160
 
157
- ```ascii
158
- foo://example.com:8042/over/there?name=ferret#nose
159
- \_/ \______________/\_________/ \_________/ \__/
160
- | | | | |
161
- scheme authority path query fragment
161
+ ```javascript
162
+ app.use(
163
+ createProxyMiddleware({
164
+ target: 'http://www.example.org/api',
165
+ changeOrigin: true,
166
+ pathFilter: '/api/proxy-only-this-path',
167
+ })
168
+ );
162
169
  ```
163
170
 
171
+ `app.use` documentation:
172
+
173
+ - express: <http://expressjs.com/en/4x/api.html#app.use>
174
+ - connect: <https://github.com/senchalabs/connect#mount-middleware>
175
+ - polka: <https://github.com/lukeed/polka#usebase-fn>
176
+
177
+ ## Options
178
+
179
+ http-proxy-middleware options:
180
+
181
+ ### `pathFilter` (string, []string, glob, []glob, function)
182
+
183
+ Narrow down which requests should be proxied. The `path` used for filtering is the `request.url` pathname. In Express, this is the `path` relative to the mount-point of the proxy.
184
+
164
185
  - **path matching**
165
186
 
166
- - `createProxyMiddleware({...})` - matches any path, all requests will be proxied.
167
- - `createProxyMiddleware('/', {...})` - matches any path, all requests will be proxied.
168
- - `createProxyMiddleware('/api', {...})` - matches paths starting with `/api`
187
+ - `createProxyMiddleware({...})` - matches any path, all requests will be proxied when `pathFilter` is not configured.
188
+ - `createProxyMiddleware({ pathFilter: '/api', ...})` - matches paths starting with `/api`
169
189
 
170
190
  - **multiple path matching**
171
191
 
172
- - `createProxyMiddleware(['/api', '/ajax', '/someotherpath'], {...})`
192
+ - `createProxyMiddleware({ pathFilter: ['/api', '/ajax', '/someotherpath'], ...})`
173
193
 
174
194
  - **wildcard path matching**
175
195
 
176
196
  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.
177
197
 
178
- - `createProxyMiddleware('**', {...})` matches any path, all requests will be proxied.
179
- - `createProxyMiddleware('**/*.html', {...})` matches any path which ends with `.html`
180
- - `createProxyMiddleware('/*.html', {...})` matches paths directly under path-absolute
181
- - `createProxyMiddleware('/api/**/*.html', {...})` matches requests ending with `.html` in the path of `/api`
182
- - `createProxyMiddleware(['/api/**', '/ajax/**'], {...})` combine multiple patterns
183
- - `createProxyMiddleware(['/api/**', '!**/bad.json'], {...})` exclusion
198
+ - `createProxyMiddleware({ pathFilter: '**', ...})` matches any path, all requests will be proxied.
199
+ - `createProxyMiddleware({ pathFilter: '**/*.html', ...})` matches any path which ends with `.html`
200
+ - `createProxyMiddleware({ pathFilter: '/*.html', ...})` matches paths directly under path-absolute
201
+ - `createProxyMiddleware({ pathFilter: '/api/**/*.html', ...})` matches requests ending with `.html` in the path of `/api`
202
+ - `createProxyMiddleware({ pathFilter: ['/api/**', '/ajax/**'], ...})` combine multiple patterns
203
+ - `createProxyMiddleware({ pathFilter: ['/api/**', '!**/bad.json'], ...})` exclusion
184
204
 
185
205
  **Note**: In multiple path matching, you cannot use string paths and wildcard paths together.
186
206
 
@@ -192,108 +212,154 @@ Providing an alternative way to decide which requests should be proxied; In case
192
212
  /**
193
213
  * @return {Boolean}
194
214
  */
195
- const filter = function (pathname, req) {
196
- return pathname.match('^/api') && req.method === 'GET';
215
+ const pathFilter = function (path, req) {
216
+ return path.match('^/api') && req.method === 'GET';
197
217
  };
198
218
 
199
- const apiProxy = createProxyMiddleware(filter, {
219
+ const apiProxy = createProxyMiddleware({
200
220
  target: 'http://www.example.org',
221
+ pathFilter: pathFilter,
201
222
  });
202
223
  ```
203
224
 
204
- ## Options
225
+ ### `pathRewrite` (object/function)
205
226
 
206
- ### http-proxy-middleware options
227
+ Rewrite target's url path. Object-keys will be used as _RegExp_ to match paths.
207
228
 
208
- - **option.pathRewrite**: object/function, rewrite target's url path. Object-keys will be used as _RegExp_ to match paths.
229
+ ```javascript
230
+ // rewrite path
231
+ pathRewrite: {'^/old/api' : '/new/api'}
209
232
 
210
- ```javascript
211
- // rewrite path
212
- pathRewrite: {'^/old/api' : '/new/api'}
233
+ // remove path
234
+ pathRewrite: {'^/remove/api' : ''}
213
235
 
214
- // remove path
215
- pathRewrite: {'^/remove/api' : ''}
236
+ // add base path
237
+ pathRewrite: {'^/' : '/basepath/'}
216
238
 
217
- // add base path
218
- pathRewrite: {'^/' : '/basepath/'}
239
+ // custom rewriting
240
+ pathRewrite: function (path, req) { return path.replace('/api', '/base/api') }
219
241
 
220
- // custom rewriting
221
- pathRewrite: function (path, req) { return path.replace('/api', '/base/api') }
242
+ // custom rewriting, returning Promise
243
+ pathRewrite: async function (path, req) {
244
+ const should_add_something = await httpRequestToDecideSomething(path);
245
+ if (should_add_something) path += "something";
246
+ return path;
247
+ }
248
+ ```
222
249
 
223
- // custom rewriting, returning Promise
224
- pathRewrite: async function (path, req) {
225
- const should_add_something = await httpRequestToDecideSomething(path);
226
- if (should_add_something) path += "something";
227
- return path;
228
- }
229
- ```
250
+ ### `router` (object/function)
230
251
 
231
- - **option.router**: object/function, re-target `option.target` for specific requests.
252
+ Re-target `option.target` for specific requests.
232
253
 
233
- ```javascript
234
- // Use `host` and/or `path` to match requests. First match will be used.
235
- // The order of the configuration matters.
236
- router: {
237
- 'integration.localhost:3000' : 'http://localhost:8001', // host only
238
- 'staging.localhost:3000' : 'http://localhost:8002', // host only
239
- 'localhost:3000/api' : 'http://localhost:8003', // host + path
240
- '/rest' : 'http://localhost:8004' // path only
241
- }
254
+ ```javascript
255
+ // Use `host` and/or `path` to match requests. First match will be used.
256
+ // The order of the configuration matters.
257
+ router: {
258
+ 'integration.localhost:3000' : 'http://127.0.0.1:8001', // host only
259
+ 'staging.localhost:3000' : 'http://127.0.0.1:8002', // host only
260
+ 'localhost:3000/api' : 'http://127.0.0.1:8003', // host + path
261
+ '/rest' : 'http://127.0.0.1:8004' // path only
262
+ }
263
+
264
+ // Custom router function (string target)
265
+ router: function(req) {
266
+ return 'http://127.0.0.1:8004';
267
+ }
268
+
269
+ // Custom router function (target object)
270
+ router: function(req) {
271
+ return {
272
+ protocol: 'https:', // The : is required
273
+ host: '127.0.0.1',
274
+ port: 8004
275
+ };
276
+ }
242
277
 
243
- // Custom router function (string target)
244
- router: function(req) {
245
- return 'http://localhost:8004';
246
- }
278
+ // Asynchronous router function which returns promise
279
+ router: async function(req) {
280
+ const url = await doSomeIO();
281
+ return url;
282
+ }
283
+ ```
247
284
 
248
- // Custom router function (target object)
249
- router: function(req) {
250
- return {
251
- protocol: 'https:', // The : is required
252
- host: 'localhost',
253
- port: 8004
254
- };
255
- }
285
+ ### `plugins` (Array)
256
286
 
257
- // Asynchronous router function which returns promise
258
- router: async function(req) {
259
- const url = await doSomeIO();
260
- return url;
261
- }
262
- ```
287
+ ```js
288
+ const simpleRequestLogger = (proxyServer, options) => {
289
+ proxyServer.on('proxyReq', (proxyReq, req, res) => {
290
+ console.log(`[HPM] [${req.method}] ${req.url}`); // outputs: [HPM] GET /users
291
+ });
292
+ },
263
293
 
264
- - **option.logLevel**: string, ['debug', 'info', 'warn', 'error', 'silent']. Default: `'info'`
294
+ const config = {
295
+ target: `http://example.org`,
296
+ changeOrigin: true,
297
+ plugins: [simpleRequestLogger],
298
+ };
299
+ ```
265
300
 
266
- - **option.logProvider**: function, modify or replace log provider. Default: `console`.
301
+ ### `ejectPlugins` (boolean) default: `false`
267
302
 
268
- ```javascript
269
- // simple replace
270
- function logProvider(provider) {
271
- // replace the default console log provider.
272
- return require('winston');
273
- }
274
- ```
303
+ If you're not satisfied with the pre-configured plugins, you can eject them by configuring `ejectPlugins: true`.
275
304
 
276
- ```javascript
277
- // verbose replacement
278
- function logProvider(provider) {
279
- const logger = new (require('winston').Logger)();
280
-
281
- const myCustomProvider = {
282
- log: logger.log,
283
- debug: logger.debug,
284
- info: logger.info,
285
- warn: logger.warn,
286
- error: logger.error,
287
- };
288
- return myCustomProvider;
289
- }
290
- ```
305
+ NOTE: register your own error handlers to prevent server from crashing.
306
+
307
+ ```js
308
+ // eject default plugins and manually add them back
309
+
310
+ const {
311
+ debugProxyErrorsPlugin, // subscribe to proxy errors to prevent server from crashing
312
+ loggerPlugin, // log proxy events to a logger (ie. console)
313
+ errorResponsePlugin, // return 5xx response on proxy error
314
+ proxyEventsPlugin, // implements the "on:" option
315
+ } = require('http-proxy-middleware');
316
+
317
+ createProxyMiddleware({
318
+ target: `http://example.org`,
319
+ changeOrigin: true,
320
+ ejectPlugins: true,
321
+ plugins: [debugProxyErrorsPlugin, loggerPlugin, errorResponsePlugin, proxyEventsPlugin],
322
+ });
323
+ ```
324
+
325
+ ### `logger` (Object)
326
+
327
+ Configure a logger to output information from http-proxy-middleware: ie. `console`, `winston`, `pino`, `bunyan`, `log4js`, etc...
328
+
329
+ Only `info`, `warn`, `error` are used internally for compatibility across different loggers.
330
+
331
+ If you use `winston`, make sure to enable interpolation: <https://github.com/winstonjs/winston#string-interpolation>
332
+
333
+ See also logger recipes ([recipes/logger.md](https://github.com/chimurai/http-proxy-middleware/blob/master/recipes/logger.md)) for more details.
291
334
 
292
- ### http-proxy events
335
+ ```javascript
336
+ createProxyMiddleware({
337
+ logger: console,
338
+ });
339
+ ```
293
340
 
294
- Subscribe to [http-proxy events](https://github.com/nodejitsu/node-http-proxy#listening-for-proxy-events):
341
+ ## `http-proxy` events
342
+
343
+ Subscribe to [http-proxy events](https://github.com/nodejitsu/node-http-proxy#listening-for-proxy-events) with the `on` option:
344
+
345
+ ```js
346
+ createProxyMiddleware({
347
+ target: 'http://www.example.org',
348
+ on: {
349
+ proxyReq: (proxyReq, req, res) => {
350
+ /* handle proxyReq */
351
+ },
352
+ proxyRes: (proxyRes, req, res) => {
353
+ /* handle proxyRes */
354
+ },
355
+ error: (err, req, res) => {
356
+ /* handle error */
357
+ },
358
+ },
359
+ });
360
+ ```
295
361
 
296
- - **option.onError**: function, subscribe to http-proxy's `error` event for custom error handling.
362
+ - **option.on.error**: function, subscribe to http-proxy's `error` event for custom error handling.
297
363
 
298
364
  ```javascript
299
365
  function onError(err, req, res, target) {
@@ -304,7 +370,7 @@ Subscribe to [http-proxy events](https://github.com/nodejitsu/node-http-proxy#li
304
370
  }
305
371
  ```
306
372
 
307
- - **option.onProxyRes**: function, subscribe to http-proxy's `proxyRes` event.
373
+ - **option.on.proxyRes**: function, subscribe to http-proxy's `proxyRes` event.
308
374
 
309
375
  ```javascript
310
376
  function onProxyRes(proxyRes, req, res) {
@@ -313,7 +379,7 @@ Subscribe to [http-proxy events](https://github.com/nodejitsu/node-http-proxy#li
313
379
  }
314
380
  ```
315
381
 
316
- - **option.onProxyReq**: function, subscribe to http-proxy's `proxyReq` event.
382
+ - **option.on.proxyReq**: function, subscribe to http-proxy's `proxyReq` event.
317
383
 
318
384
  ```javascript
319
385
  function onProxyReq(proxyReq, req, res) {
@@ -323,7 +389,7 @@ Subscribe to [http-proxy events](https://github.com/nodejitsu/node-http-proxy#li
323
389
  }
324
390
  ```
325
391
 
326
- - **option.onProxyReqWs**: function, subscribe to http-proxy's `proxyReqWs` event.
392
+ - **option.on.proxyReqWs**: function, subscribe to http-proxy's `proxyReqWs` event.
327
393
 
328
394
  ```javascript
329
395
  function onProxyReqWs(proxyReq, req, socket, options, head) {
@@ -332,7 +398,7 @@ Subscribe to [http-proxy events](https://github.com/nodejitsu/node-http-proxy#li
332
398
  }
333
399
  ```
334
400
 
335
- - **option.onOpen**: function, subscribe to http-proxy's `open` event.
401
+ - **option.on.open**: function, subscribe to http-proxy's `open` event.
336
402
 
337
403
  ```javascript
338
404
  function onOpen(proxySocket) {
@@ -341,7 +407,7 @@ Subscribe to [http-proxy events](https://github.com/nodejitsu/node-http-proxy#li
341
407
  }
342
408
  ```
343
409
 
344
- - **option.onClose**: function, subscribe to http-proxy's `close` event.
410
+ - **option.on.close**: function, subscribe to http-proxy's `close` event.
345
411
 
346
412
  ```javascript
347
413
  function onClose(res, socket, head) {
@@ -350,7 +416,7 @@ Subscribe to [http-proxy events](https://github.com/nodejitsu/node-http-proxy#li
350
416
  }
351
417
  ```
352
418
 
353
- ### http-proxy options
419
+ ## `http-proxy` options
354
420
 
355
421
  The following options are provided by the underlying [http-proxy](https://github.com/nodejitsu/node-http-proxy#options) library.
356
422
 
@@ -372,10 +438,12 @@ The following options are provided by the underlying [http-proxy](https://github
372
438
  - **option.autoRewrite**: rewrites the location host/port on (301/302/307/308) redirects based on requested host/port. Default: false.
373
439
  - **option.protocolRewrite**: rewrites the location protocol on (301/302/307/308) redirects to 'http' or 'https'. Default: null.
374
440
  - **option.cookieDomainRewrite**: rewrites domain of `set-cookie` headers. Possible values:
441
+
375
442
  - `false` (default): disable cookie rewriting
376
443
  - String: new domain, for example `cookieDomainRewrite: "new.domain"`. To remove the domain, use `cookieDomainRewrite: ""`.
377
444
  - Object: mapping of domains to new domains, use `"*"` to match all domains.
378
445
  For example keep one domain unchanged, rewrite one domain and remove other domains:
446
+
379
447
  ```json
380
448
  cookieDomainRewrite: {
381
449
  "unchanged.domain": "unchanged.domain",
@@ -383,11 +451,14 @@ The following options are provided by the underlying [http-proxy](https://github
383
451
  "*": ""
384
452
  }
385
453
  ```
454
+
386
455
  - **option.cookiePathRewrite**: rewrites path of `set-cookie` headers. Possible values:
456
+
387
457
  - `false` (default): disable cookie rewriting
388
458
  - String: new path, for example `cookiePathRewrite: "/newPath/"`. To remove the path, use `cookiePathRewrite: ""`. To set path to root use `cookiePathRewrite: "/"`.
389
459
  - Object: mapping of paths to new paths, use `"*"` to match all paths.
390
460
  For example, to keep one path unchanged, rewrite one path and remove other paths:
461
+
391
462
  ```json
392
463
  cookiePathRewrite: {
393
464
  "/unchanged.path/": "/unchanged.path/",
@@ -395,6 +466,7 @@ The following options are provided by the underlying [http-proxy](https://github
395
466
  "*": ""
396
467
  }
397
468
  ```
469
+
398
470
  - **option.headers**: object, adds [request headers](https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Request_fields). (Example: `{host:'www.example.org'}`)
399
471
  - **option.proxyTimeout**: timeout (in millis) when proxy receives no response from target
400
472
  - **option.timeout**: timeout (in millis) for incoming requests
@@ -414,7 +486,7 @@ The following options are provided by the underlying [http-proxy](https://github
414
486
  req,
415
487
  res,
416
488
  {
417
- target: 'http://localhost:4003/',
489
+ target: 'http://127.0.0.1:4003/',
418
490
  buffer: streamify(req.rawBody),
419
491
  },
420
492
  next
@@ -422,47 +494,11 @@ The following options are provided by the underlying [http-proxy](https://github
422
494
  };
423
495
  ```
424
496
 
425
- ## Shorthand
426
-
427
- 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.
428
-
429
- ```javascript
430
- createProxyMiddleware('http://www.example.org:8000/api');
431
- // createProxyMiddleware('/api', {target: 'http://www.example.org:8000'});
432
-
433
- createProxyMiddleware('http://www.example.org:8000/api/books/*/**.json');
434
- // createProxyMiddleware('/api/books/*/**.json', {target: 'http://www.example.org:8000'});
435
-
436
- createProxyMiddleware('http://www.example.org:8000/api', { changeOrigin: true });
437
- // createProxyMiddleware('/api', {target: 'http://www.example.org:8000', changeOrigin: true});
438
- ```
439
-
440
- ### app.use(path, proxy)
441
-
442
- If you want to use the server's `app.use` `path` parameter to match requests;
443
- Create and mount the proxy without the http-proxy-middleware `context` parameter:
444
-
445
- ```javascript
446
- app.use('/api', createProxyMiddleware({ target: 'http://www.example.org', changeOrigin: true }));
447
- ```
448
-
449
- `app.use` documentation:
450
-
451
- - express: http://expressjs.com/en/4x/api.html#app.use
452
- - connect: https://github.com/senchalabs/connect#mount-middleware
453
- - polka: https://github.com/lukeed/polka#usebase-fn
454
-
455
497
  ## WebSocket
456
498
 
457
499
  ```javascript
458
500
  // verbose api
459
- createProxyMiddleware('/', { target: 'http://echo.websocket.org', ws: true });
460
-
461
- // shorthand
462
- createProxyMiddleware('http://echo.websocket.org', { ws: true });
463
-
464
- // shorter shorthand
465
- createProxyMiddleware('ws://echo.websocket.org');
501
+ createProxyMiddleware({ pathFilter: '/', target: 'http://echo.websocket.org', ws: true });
466
502
  ```
467
503
 
468
504
  ### External WebSocket upgrade
@@ -470,7 +506,7 @@ createProxyMiddleware('ws://echo.websocket.org');
470
506
  In the previous WebSocket examples, http-proxy-middleware relies on a initial http request in order to listen to the http `upgrade` event. If you need to proxy WebSockets without the initial http request, you can subscribe to the server's http `upgrade` event manually.
471
507
 
472
508
  ```javascript
473
- const wsProxy = createProxyMiddleware('ws://echo.websocket.org', { changeOrigin: true });
509
+ const wsProxy = createProxyMiddleware({ target: 'ws://echo.websocket.org', changeOrigin: true });
474
510
 
475
511
  const app = express();
476
512
  app.use(wsProxy);
@@ -494,7 +530,9 @@ const proxy = createProxyMiddleware({
494
530
  /**
495
531
  * Fix bodyParser
496
532
  **/
497
- onProxyReq: fixRequestBody,
533
+ on: {
534
+ proxyReq: fixRequestBody,
535
+ },
498
536
  });
499
537
  ```
500
538
 
@@ -522,15 +560,45 @@ const proxy = createProxyMiddleware({
522
560
  /**
523
561
  * Intercept response and replace 'Hello' with 'Goodbye'
524
562
  **/
525
- onProxyRes: responseInterceptor(async (responseBuffer, proxyRes, req, res) => {
526
- const response = responseBuffer.toString('utf8'); // convert buffer to string
527
- return response.replace('Hello', 'Goodbye'); // manipulate response and return the result
528
- }),
563
+ on: {
564
+ proxyRes: responseInterceptor(async (responseBuffer, proxyRes, req, res) => {
565
+ const response = responseBuffer.toString('utf8'); // convert buffer to string
566
+ return response.replace('Hello', 'Goodbye'); // manipulate response and return the result
567
+ }),
568
+ },
529
569
  });
530
570
  ```
531
571
 
532
572
  Check out [interception recipes](https://github.com/chimurai/http-proxy-middleware/blob/master/recipes/response-interceptor.md#readme) for more examples.
533
573
 
574
+ ## Node.js 17+: ECONNREFUSED issue with IPv6 and localhost ([#705](https://github.com/chimurai/http-proxy-middleware/issues/705))
575
+
576
+ Node.js 17+ no longer prefers IPv4 over IPv6 for DNS lookups.
577
+ E.g. It's **not** guaranteed that `localhost` will be resolved to `127.0.0.1` – it might just as well be `::1` (or some other IP address).
578
+
579
+ If your target server only accepts IPv4 connections, trying to proxy to `localhost` will fail if resolved to `::1` (IPv6).
580
+
581
+ Ways to solve it:
582
+
583
+ - Change `target: "http://localhost"` to `target: "http://127.0.0.1"` (IPv4).
584
+ - Change the target server to (also) accept IPv6 connections.
585
+ - Add this flag when running `node`: `node index.js --dns-result-order=ipv4first`. (Not recommended.)
586
+
587
+ > Note: There’s a thing called [Happy Eyeballs](https://en.wikipedia.org/wiki/Happy_Eyeballs) which means connecting to both IPv4 and IPv6 in parallel, which Node.js doesn’t have, but explains why for example `curl` can connect.
588
+
589
+ ## Debugging
590
+
591
+ Configure the `DEBUG` environment variable enable debug logging.
592
+
593
+ See [`debug`](https://github.com/debug-js/debug#readme) project for more options.
594
+
595
+ ```shell
596
+ DEBUG=http-proxy-middleware* node server.js
597
+
598
+ $ http-proxy-middleware proxy created +0ms
599
+ $ http-proxy-middleware proxying request to target: 'http://www.example.org' +359ms
600
+ ```
601
+
534
602
  ## Working examples
535
603
 
536
604
  View and play around with [working examples](https://github.com/chimurai/http-proxy-middleware/tree/master/examples).
@@ -551,6 +619,7 @@ View the [recipes](https://github.com/chimurai/http-proxy-middleware/tree/master
551
619
 
552
620
  - [connect](https://www.npmjs.com/package/connect)
553
621
  - [express](https://www.npmjs.com/package/express)
622
+ - [next.js](https://www.npmjs.com/package/next)
554
623
  - [fastify](https://www.npmjs.com/package/fastify)
555
624
  - [browser-sync](https://www.npmjs.com/package/browser-sync)
556
625
  - [lite-server](https://www.npmjs.com/package/lite-server)