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.
- package/README.md +280 -211
- package/dist/configuration.d.ts +2 -0
- package/dist/configuration.js +10 -0
- package/dist/debug.d.ts +5 -0
- package/dist/debug.js +8 -0
- package/dist/errors.d.ts +1 -1
- package/dist/errors.js +1 -1
- package/dist/get-plugins.d.ts +2 -0
- package/dist/get-plugins.js +15 -0
- package/dist/handlers/fix-request-body.d.ts +4 -1
- package/dist/handlers/index.js +5 -1
- package/dist/handlers/response-interceptor.d.ts +3 -2
- package/dist/handlers/response-interceptor.js +10 -1
- package/dist/http-proxy-middleware.d.ts +4 -11
- package/dist/http-proxy-middleware.js +39 -50
- package/dist/index.d.ts +13 -3
- package/dist/index.js +15 -3
- package/dist/legacy/create-proxy-middleware.d.ts +13 -0
- package/dist/legacy/create-proxy-middleware.js +17 -0
- package/dist/legacy/index.d.ts +1 -0
- package/dist/legacy/index.js +17 -0
- package/dist/legacy/options-adapter.d.ts +6 -0
- package/dist/legacy/options-adapter.js +92 -0
- package/dist/legacy/public.d.ts +2 -0
- package/dist/legacy/public.js +5 -0
- package/dist/legacy/types.d.ts +112 -0
- package/dist/legacy/types.js +2 -0
- package/dist/logger.d.ts +2 -14
- package/dist/logger.js +20 -129
- package/dist/path-filter.d.ts +4 -0
- package/dist/{context-matcher.js → path-filter.js} +24 -24
- package/dist/path-rewriter.js +6 -6
- package/dist/plugins/default/debug-proxy-errors-plugin.d.ts +6 -0
- package/dist/plugins/default/debug-proxy-errors-plugin.js +61 -0
- package/dist/plugins/default/error-response-plugin.d.ts +2 -0
- package/dist/plugins/default/error-response-plugin.js +19 -0
- package/dist/plugins/default/index.d.ts +4 -0
- package/dist/plugins/default/index.js +20 -0
- package/dist/plugins/default/logger-plugin.d.ts +2 -0
- package/dist/plugins/default/logger-plugin.js +44 -0
- package/dist/plugins/default/proxy-events.d.ts +22 -0
- package/dist/plugins/default/proxy-events.js +33 -0
- package/dist/router.js +7 -7
- package/dist/status-code.d.ts +1 -0
- package/dist/status-code.js +24 -0
- package/dist/types.d.ts +109 -38
- package/dist/utils/function.d.ts +1 -0
- package/dist/utils/function.js +8 -0
- package/package.json +37 -45
- package/dist/_handlers.d.ts +0 -4
- package/dist/_handlers.js +0 -84
- package/dist/config-factory.d.ts +0 -6
- package/dist/config-factory.js +0 -80
- package/dist/context-matcher.d.ts +0 -2
package/README.md
CHANGED
|
@@ -1,25 +1,31 @@
|
|
|
1
1
|
# http-proxy-middleware
|
|
2
2
|
|
|
3
|
-
[](https://coveralls.io/r/chimurai/http-proxy-middleware)
|
|
5
|
-
[](https://www.npmjs.com/package/http-proxy-middleware)
|
|
3
|
+
[](https://github.com/chimurai/http-proxy-middleware/actions/workflows/ci.yml?query=branch%3Amaster)
|
|
4
|
+
[](https://coveralls.io/r/chimurai/http-proxy-middleware)
|
|
5
|
+
[](https://security.snyk.io/package/npm/http-proxy-middleware)
|
|
6
|
+
[](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/
|
|
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/
|
|
10
|
+
Powered by the popular Nodejitsu [`http-proxy`](https://github.com/http-party/node-http-proxy). [](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
|
|
14
|
+
This page is showing documentation for version v3.x.x ([release notes](https://github.com/chimurai/http-proxy-middleware/releases))
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
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(
|
|
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
|
-
//
|
|
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(
|
|
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
|
-
//
|
|
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
|
-
- [
|
|
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
|
-
```
|
|
81
|
-
|
|
109
|
+
```shell
|
|
110
|
+
npm install --save-dev http-proxy-middleware
|
|
82
111
|
```
|
|
83
112
|
|
|
84
|
-
##
|
|
85
|
-
|
|
86
|
-
Proxy middleware configuration.
|
|
113
|
+
## Basic usage
|
|
87
114
|
|
|
88
|
-
|
|
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(
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
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
|
-
|
|
131
|
+
- see full list of [`http-proxy-middleware` configuration options](#options)
|
|
106
132
|
|
|
107
|
-
|
|
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
|
-
|
|
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
|
|
143
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
```
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
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('/',
|
|
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('**',
|
|
179
|
-
- `createProxyMiddleware('**/*.html',
|
|
180
|
-
- `createProxyMiddleware('/*.html',
|
|
181
|
-
- `createProxyMiddleware('/api/**/*.html',
|
|
182
|
-
- `createProxyMiddleware(['/api/**', '/ajax/**'],
|
|
183
|
-
- `createProxyMiddleware(['/api/**', '!**/bad.json'],
|
|
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
|
|
196
|
-
return
|
|
215
|
+
const pathFilter = function (path, req) {
|
|
216
|
+
return path.match('^/api') && req.method === 'GET';
|
|
197
217
|
};
|
|
198
218
|
|
|
199
|
-
const apiProxy = createProxyMiddleware(
|
|
219
|
+
const apiProxy = createProxyMiddleware({
|
|
200
220
|
target: 'http://www.example.org',
|
|
221
|
+
pathFilter: pathFilter,
|
|
201
222
|
});
|
|
202
223
|
```
|
|
203
224
|
|
|
204
|
-
|
|
225
|
+
### `pathRewrite` (object/function)
|
|
205
226
|
|
|
206
|
-
|
|
227
|
+
Rewrite target's url path. Object-keys will be used as _RegExp_ to match paths.
|
|
207
228
|
|
|
208
|
-
|
|
229
|
+
```javascript
|
|
230
|
+
// rewrite path
|
|
231
|
+
pathRewrite: {'^/old/api' : '/new/api'}
|
|
209
232
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
pathRewrite: {'^/old/api' : '/new/api'}
|
|
233
|
+
// remove path
|
|
234
|
+
pathRewrite: {'^/remove/api' : ''}
|
|
213
235
|
|
|
214
|
-
|
|
215
|
-
|
|
236
|
+
// add base path
|
|
237
|
+
pathRewrite: {'^/' : '/basepath/'}
|
|
216
238
|
|
|
217
|
-
|
|
218
|
-
|
|
239
|
+
// custom rewriting
|
|
240
|
+
pathRewrite: function (path, req) { return path.replace('/api', '/base/api') }
|
|
219
241
|
|
|
220
|
-
|
|
221
|
-
|
|
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
|
-
|
|
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
|
-
-
|
|
252
|
+
Re-target `option.target` for specific requests.
|
|
232
253
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
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
|
-
|
|
244
|
-
|
|
245
|
-
|
|
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
|
-
|
|
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
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
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
|
-
|
|
294
|
+
const config = {
|
|
295
|
+
target: `http://example.org`,
|
|
296
|
+
changeOrigin: true,
|
|
297
|
+
plugins: [simpleRequestLogger],
|
|
298
|
+
};
|
|
299
|
+
```
|
|
265
300
|
|
|
266
|
-
|
|
301
|
+
### `ejectPlugins` (boolean) default: `false`
|
|
267
302
|
|
|
268
|
-
|
|
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
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
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
|
-
|
|
335
|
+
```javascript
|
|
336
|
+
createProxyMiddleware({
|
|
337
|
+
logger: console,
|
|
338
|
+
});
|
|
339
|
+
```
|
|
293
340
|
|
|
294
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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://
|
|
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('/',
|
|
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',
|
|
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
|
-
|
|
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
|
-
|
|
526
|
-
|
|
527
|
-
|
|
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)
|