http-proxy-middleware 0.17.4 → 0.19.2
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/CHANGELOG.md +45 -2
- package/README.md +283 -239
- package/index.js +3 -3
- package/lib/config-factory.js +74 -71
- package/lib/context-matcher.js +46 -46
- package/lib/errors.js +12 -0
- package/lib/handlers.js +59 -51
- package/lib/index.js +167 -132
- package/lib/logger.js +130 -116
- package/lib/path-rewriter.js +57 -50
- package/lib/router.js +37 -39
- package/package.json +35 -14
package/README.md
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
[](https://coveralls.io/r/chimurai/http-proxy-middleware)
|
|
5
5
|
[](https://david-dm.org/chimurai/http-proxy-middleware#info=dependencies)
|
|
6
6
|
[](https://snyk.io/test/npm/http-proxy-middleware)
|
|
7
|
+
[](https://github.com/prettier/prettier)
|
|
7
8
|
|
|
8
9
|
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).
|
|
9
10
|
|
|
@@ -14,13 +15,13 @@ Powered by the popular Nodejitsu [`http-proxy`](https://github.com/nodejitsu/nod
|
|
|
14
15
|
Proxy `/api` requests to `http://www.example.org`
|
|
15
16
|
|
|
16
17
|
```javascript
|
|
17
|
-
var express = require('express')
|
|
18
|
-
var proxy = require('http-proxy-middleware')
|
|
18
|
+
var express = require('express')
|
|
19
|
+
var proxy = require('http-proxy-middleware')
|
|
19
20
|
|
|
20
|
-
var app = express()
|
|
21
|
+
var app = express()
|
|
21
22
|
|
|
22
|
-
app.use('/api', proxy({target: 'http://www.example.org', changeOrigin: true}))
|
|
23
|
-
app.listen(3000)
|
|
23
|
+
app.use('/api', proxy({ target: 'http://www.example.org', changeOrigin: true }))
|
|
24
|
+
app.listen(3000)
|
|
24
25
|
|
|
25
26
|
// http://localhost:3000/api/foo/bar -> http://www.example.org/api/foo/bar
|
|
26
27
|
```
|
|
@@ -38,13 +39,13 @@ _All_ `http-proxy` [options](https://github.com/nodejitsu/node-http-proxy#option
|
|
|
38
39
|
- [Example](#example)
|
|
39
40
|
- [Context matching](#context-matching)
|
|
40
41
|
- [Options](#options)
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
- [http-proxy-middleware options](#http-proxy-middleware-options)
|
|
43
|
+
- [http-proxy events](#http-proxy-events)
|
|
44
|
+
- [http-proxy options](#http-proxy-options)
|
|
44
45
|
- [Shorthand](#shorthand)
|
|
45
|
-
|
|
46
|
+
- [app.use\(path, proxy\)](#appusepath-proxy)
|
|
46
47
|
- [WebSocket](#websocket)
|
|
47
|
-
|
|
48
|
+
- [External WebSocket upgrade](#external-websocket-upgrade)
|
|
48
49
|
- [Working examples](#working-examples)
|
|
49
50
|
- [Recipes](#recipes)
|
|
50
51
|
- [Compatible servers](#compatible-servers)
|
|
@@ -54,7 +55,6 @@ _All_ `http-proxy` [options](https://github.com/nodejitsu/node-http-proxy#option
|
|
|
54
55
|
|
|
55
56
|
<!-- /MarkdownTOC -->
|
|
56
57
|
|
|
57
|
-
|
|
58
58
|
## Install
|
|
59
59
|
|
|
60
60
|
```javascript
|
|
@@ -68,28 +68,29 @@ Proxy middleware configuration.
|
|
|
68
68
|
#### proxy([context,] config)
|
|
69
69
|
|
|
70
70
|
```javascript
|
|
71
|
-
var proxy = require('http-proxy-middleware')
|
|
71
|
+
var proxy = require('http-proxy-middleware')
|
|
72
72
|
|
|
73
|
-
var apiProxy = proxy('/api', {target: 'http://www.example.org'})
|
|
73
|
+
var apiProxy = proxy('/api', { target: 'http://www.example.org' })
|
|
74
74
|
// \____/ \_____________________________/
|
|
75
75
|
// | |
|
|
76
76
|
// context options
|
|
77
77
|
|
|
78
78
|
// 'apiProxy' is now ready to be used as middleware in a server.
|
|
79
79
|
```
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
80
|
+
|
|
81
|
+
- **context**: Determine which requests should be proxied to the target host.
|
|
82
|
+
(more on [context matching](#context-matching))
|
|
83
|
+
- **options.target**: target host to proxy to. _(protocol + host)_
|
|
83
84
|
|
|
84
85
|
(full list of [`http-proxy-middleware` configuration options](#options))
|
|
85
86
|
|
|
86
87
|
#### proxy(uri [, config])
|
|
87
88
|
|
|
88
|
-
```
|
|
89
|
+
```javascript
|
|
89
90
|
// shorthand syntax for the example above:
|
|
90
|
-
var apiProxy = proxy('http://www.example.org/api')
|
|
91
|
-
|
|
91
|
+
var apiProxy = proxy('http://www.example.org/api')
|
|
92
92
|
```
|
|
93
|
+
|
|
93
94
|
More about the [shorthand configuration](#shorthand).
|
|
94
95
|
|
|
95
96
|
## Example
|
|
@@ -98,39 +99,39 @@ An example with `express` server.
|
|
|
98
99
|
|
|
99
100
|
```javascript
|
|
100
101
|
// include dependencies
|
|
101
|
-
var express = require('express')
|
|
102
|
-
var proxy = require('http-proxy-middleware')
|
|
102
|
+
var express = require('express')
|
|
103
|
+
var proxy = require('http-proxy-middleware')
|
|
103
104
|
|
|
104
105
|
// proxy middleware options
|
|
105
106
|
var options = {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
107
|
+
target: 'http://www.example.org', // target host
|
|
108
|
+
changeOrigin: true, // needed for virtual hosted sites
|
|
109
|
+
ws: true, // proxy websockets
|
|
110
|
+
pathRewrite: {
|
|
111
|
+
'^/api/old-path': '/api/new-path', // rewrite path
|
|
112
|
+
'^/api/remove/path': '/path' // remove base path
|
|
113
|
+
},
|
|
114
|
+
router: {
|
|
115
|
+
// when request.headers.host == 'dev.localhost:3000',
|
|
116
|
+
// override target 'http://www.example.org' to 'http://localhost:8000'
|
|
117
|
+
'dev.localhost:3000': 'http://localhost:8000'
|
|
118
|
+
}
|
|
119
|
+
}
|
|
119
120
|
|
|
120
121
|
// create the proxy (without context)
|
|
121
|
-
var exampleProxy = proxy(options)
|
|
122
|
+
var exampleProxy = proxy(options)
|
|
122
123
|
|
|
123
124
|
// mount `exampleProxy` in web server
|
|
124
|
-
var app = express()
|
|
125
|
-
|
|
126
|
-
|
|
125
|
+
var app = express()
|
|
126
|
+
app.use('/api', exampleProxy)
|
|
127
|
+
app.listen(3000)
|
|
127
128
|
```
|
|
128
129
|
|
|
129
130
|
## Context matching
|
|
130
131
|
|
|
131
132
|
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.
|
|
132
133
|
|
|
133
|
-
|
|
134
|
+
[RFC 3986 `path`](https://tools.ietf.org/html/rfc3986#section-3.3) is used for context matching.
|
|
134
135
|
|
|
135
136
|
```
|
|
136
137
|
foo://example.com:8042/over/there?name=ferret#nose
|
|
@@ -139,260 +140,308 @@ The [RFC 3986 `path`](https://tools.ietf.org/html/rfc3986#section-3.3) is be use
|
|
|
139
140
|
scheme authority path query fragment
|
|
140
141
|
```
|
|
141
142
|
|
|
142
|
-
|
|
143
|
-
- `proxy({...})` - matches any path, all requests will be proxied.
|
|
144
|
-
- `proxy('/', {...})` - matches any path, all requests will be proxied.
|
|
145
|
-
- `proxy('/api', {...})` - matches paths starting with `/api`
|
|
146
|
-
|
|
147
|
-
* **multiple path matching**
|
|
148
|
-
- `proxy(['/api', '/ajax', '/someotherpath'], {...})`
|
|
149
|
-
|
|
150
|
-
* **wildcard path matching**
|
|
151
|
-
|
|
152
|
-
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.
|
|
153
|
-
- `proxy('**', {...})` matches any path, all requests will be proxied.
|
|
154
|
-
- `proxy('**/*.html', {...})` matches any path which ends with `.html`
|
|
155
|
-
- `proxy('/*.html', {...})` matches paths directly under path-absolute
|
|
156
|
-
- `proxy('/api/**/*.html', {...})` matches requests ending with `.html` in the path of `/api`
|
|
157
|
-
- `proxy(['/api/**', '/ajax/**'], {...})` combine multiple patterns
|
|
158
|
-
- `proxy(['/api/**', '!**/bad.json'], {...})` exclusion
|
|
159
|
-
|
|
160
|
-
* **custom matching**
|
|
161
|
-
|
|
162
|
-
For full control you can provide a custom function to determine which requests should be proxied or not.
|
|
163
|
-
```javascript
|
|
164
|
-
/**
|
|
165
|
-
* @return {Boolean}
|
|
166
|
-
*/
|
|
167
|
-
var filter = function (pathname, req) {
|
|
168
|
-
return (pathname.match('^/api') && req.method === 'GET');
|
|
169
|
-
};
|
|
170
|
-
|
|
171
|
-
var apiProxy = proxy(filter, {target: 'http://www.example.org'})
|
|
172
|
-
```
|
|
143
|
+
- **path matching**
|
|
173
144
|
|
|
174
|
-
|
|
145
|
+
- `proxy({...})` - matches any path, all requests will be proxied.
|
|
146
|
+
- `proxy('/', {...})` - matches any path, all requests will be proxied.
|
|
147
|
+
- `proxy('/api', {...})` - matches paths starting with `/api`
|
|
175
148
|
|
|
176
|
-
|
|
149
|
+
- **multiple path matching**
|
|
177
150
|
|
|
178
|
-
|
|
179
|
-
```javascript
|
|
180
|
-
// rewrite path
|
|
181
|
-
pathRewrite: {'^/old/api' : '/new/api'}
|
|
182
|
-
|
|
183
|
-
// remove path
|
|
184
|
-
pathRewrite: {'^/remove/api' : ''}
|
|
185
|
-
|
|
186
|
-
// add base path
|
|
187
|
-
pathRewrite: {'^/' : '/basepath/'}
|
|
188
|
-
|
|
189
|
-
// custom rewriting
|
|
190
|
-
pathRewrite: function (path, req) { return path.replace('/api', '/base/api') }
|
|
191
|
-
```
|
|
151
|
+
- `proxy(['/api', '/ajax', '/someotherpath'], {...})`
|
|
192
152
|
|
|
193
|
-
|
|
194
|
-
```javascript
|
|
195
|
-
// Use `host` and/or `path` to match requests. First match will be used.
|
|
196
|
-
// The order of the configuration matters.
|
|
197
|
-
router: {
|
|
198
|
-
'integration.localhost:3000' : 'http://localhost:8001', // host only
|
|
199
|
-
'staging.localhost:3000' : 'http://localhost:8002', // host only
|
|
200
|
-
'localhost:3000/api' : 'http://localhost:8003', // host + path
|
|
201
|
-
'/rest' : 'http://localhost:8004' // path only
|
|
202
|
-
}
|
|
153
|
+
- **wildcard path matching**
|
|
203
154
|
|
|
204
|
-
|
|
205
|
-
router: function(req) {
|
|
206
|
-
return 'http://localhost:8004';
|
|
207
|
-
}
|
|
208
|
-
```
|
|
155
|
+
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.
|
|
209
156
|
|
|
210
|
-
|
|
157
|
+
- `proxy('**', {...})` matches any path, all requests will be proxied.
|
|
158
|
+
- `proxy('**/*.html', {...})` matches any path which ends with `.html`
|
|
159
|
+
- `proxy('/*.html', {...})` matches paths directly under path-absolute
|
|
160
|
+
- `proxy('/api/**/*.html', {...})` matches requests ending with `.html` in the path of `/api`
|
|
161
|
+
- `proxy(['/api/**', '/ajax/**'], {...})` combine multiple patterns
|
|
162
|
+
- `proxy(['/api/**', '!**/bad.json'], {...})` exclusion
|
|
211
163
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
164
|
+
**Note**: In multiple path matching, you cannot use string paths and wildcard paths together.
|
|
165
|
+
|
|
166
|
+
- **custom matching**
|
|
167
|
+
|
|
168
|
+
For full control you can provide a custom function to determine which requests should be proxied or not.
|
|
169
|
+
|
|
170
|
+
```javascript
|
|
171
|
+
/**
|
|
172
|
+
* @return {Boolean}
|
|
173
|
+
*/
|
|
174
|
+
var filter = function(pathname, req) {
|
|
175
|
+
return pathname.match('^/api') && req.method === 'GET'
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
var apiProxy = proxy(filter, { target: 'http://www.example.org' })
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## Options
|
|
182
|
+
|
|
183
|
+
### http-proxy-middleware options
|
|
220
184
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
185
|
+
- **option.pathRewrite**: object/function, rewrite target's url path. Object-keys will be used as _RegExp_ to match paths.
|
|
186
|
+
|
|
187
|
+
```javascript
|
|
188
|
+
// rewrite path
|
|
189
|
+
pathRewrite: {'^/old/api' : '/new/api'}
|
|
190
|
+
|
|
191
|
+
// remove path
|
|
192
|
+
pathRewrite: {'^/remove/api' : ''}
|
|
193
|
+
|
|
194
|
+
// add base path
|
|
195
|
+
pathRewrite: {'^/' : '/basepath/'}
|
|
196
|
+
|
|
197
|
+
// custom rewriting
|
|
198
|
+
pathRewrite: function (path, req) { return path.replace('/api', '/base/api') }
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
- **option.router**: object/function, re-target `option.target` for specific requests.
|
|
202
|
+
|
|
203
|
+
```javascript
|
|
204
|
+
// Use `host` and/or `path` to match requests. First match will be used.
|
|
205
|
+
// The order of the configuration matters.
|
|
206
|
+
router: {
|
|
207
|
+
'integration.localhost:3000' : 'http://localhost:8001', // host only
|
|
208
|
+
'staging.localhost:3000' : 'http://localhost:8002', // host only
|
|
209
|
+
'localhost:3000/api' : 'http://localhost:8003', // host + path
|
|
210
|
+
'/rest' : 'http://localhost:8004' // path only
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Custom router function
|
|
214
|
+
router: function(req) {
|
|
215
|
+
return 'http://localhost:8004';
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
- **option.logLevel**: string, ['debug', 'info', 'warn', 'error', 'silent']. Default: `'info'`
|
|
220
|
+
|
|
221
|
+
- **option.logProvider**: function, modify or replace log provider. Default: `console`.
|
|
222
|
+
|
|
223
|
+
```javascript
|
|
224
|
+
// simple replace
|
|
225
|
+
function logProvider(provider) {
|
|
226
|
+
// replace the default console log provider.
|
|
227
|
+
return require('winston')
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
```javascript
|
|
232
|
+
// verbose replacement
|
|
233
|
+
function logProvider(provider) {
|
|
234
|
+
var logger = new (require('winston')).Logger()
|
|
235
|
+
|
|
236
|
+
var myCustomProvider = {
|
|
237
|
+
log: logger.log,
|
|
238
|
+
debug: logger.debug,
|
|
239
|
+
info: logger.info,
|
|
240
|
+
warn: logger.warn,
|
|
241
|
+
error: logger.error
|
|
234
242
|
}
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
243
|
+
return myCustomProvider
|
|
244
|
+
}
|
|
245
|
+
```
|
|
238
246
|
|
|
247
|
+
- (DEPRECATED) **option.proxyHost**: Use `option.changeOrigin = true` instead.
|
|
248
|
+
- (DEPRECATED) **option.proxyTable**: Use `option.router` instead.
|
|
239
249
|
|
|
240
250
|
### http-proxy events
|
|
241
251
|
|
|
242
252
|
Subscribe to [http-proxy events](https://github.com/nodejitsu/node-http-proxy#listening-for-proxy-events):
|
|
243
253
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
254
|
+
- **option.onError**: function, subscribe to http-proxy's `error` event for custom error handling.
|
|
255
|
+
|
|
256
|
+
```javascript
|
|
257
|
+
function onError(err, req, res) {
|
|
258
|
+
res.writeHead(500, {
|
|
259
|
+
'Content-Type': 'text/plain'
|
|
260
|
+
})
|
|
261
|
+
res.end(
|
|
262
|
+
'Something went wrong. And we are reporting a custom error message.'
|
|
263
|
+
)
|
|
264
|
+
}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
- **option.onProxyRes**: function, subscribe to http-proxy's `proxyRes` event.
|
|
268
|
+
|
|
269
|
+
```javascript
|
|
270
|
+
function onProxyRes(proxyRes, req, res) {
|
|
271
|
+
proxyRes.headers['x-added'] = 'foobar' // add new header to response
|
|
272
|
+
delete proxyRes.headers['x-removed'] // remove header from response
|
|
273
|
+
}
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
- **option.onProxyReq**: function, subscribe to http-proxy's `proxyReq` event.
|
|
277
|
+
|
|
278
|
+
```javascript
|
|
279
|
+
function onProxyReq(proxyReq, req, res) {
|
|
280
|
+
// add custom header to request
|
|
281
|
+
proxyReq.setHeader('x-added', 'foobar')
|
|
282
|
+
// or log the req
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
- **option.onProxyReqWs**: function, subscribe to http-proxy's `proxyReqWs` event.
|
|
287
|
+
|
|
288
|
+
```javascript
|
|
289
|
+
function onProxyReqWs(proxyReq, req, socket, options, head) {
|
|
290
|
+
// add custom header
|
|
291
|
+
proxyReq.setHeader('X-Special-Proxy-Header', 'foobar')
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
- **option.onOpen**: function, subscribe to http-proxy's `open` event.
|
|
296
|
+
|
|
297
|
+
```javascript
|
|
298
|
+
function onOpen(proxySocket) {
|
|
299
|
+
// listen for messages coming FROM the target here
|
|
300
|
+
proxySocket.on('data', hybiParseAndLogMessage)
|
|
301
|
+
}
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
- **option.onClose**: function, subscribe to http-proxy's `close` event.
|
|
305
|
+
```javascript
|
|
306
|
+
function onClose(res, socket, head) {
|
|
307
|
+
// view disconnected websocket connections
|
|
308
|
+
console.log('Client disconnected')
|
|
309
|
+
}
|
|
310
|
+
```
|
|
253
311
|
|
|
254
|
-
|
|
255
|
-
```javascript
|
|
256
|
-
function onProxyRes(proxyRes, req, res) {
|
|
257
|
-
proxyRes.headers['x-added'] = 'foobar'; // add new header to response
|
|
258
|
-
delete proxyRes.headers['x-removed']; // remove header from response
|
|
259
|
-
}
|
|
260
|
-
```
|
|
312
|
+
### http-proxy options
|
|
261
313
|
|
|
262
|
-
|
|
263
|
-
```javascript
|
|
264
|
-
function onProxyReq(proxyReq, req, res) {
|
|
265
|
-
// add custom header to request
|
|
266
|
-
proxyReq.setHeader('x-added', 'foobar');
|
|
267
|
-
// or log the req
|
|
268
|
-
}
|
|
269
|
-
```
|
|
314
|
+
The following options are provided by the underlying [http-proxy](https://github.com/nodejitsu/node-http-proxy#options) library.
|
|
270
315
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
316
|
+
- **option.target**: url string to be parsed with the url module
|
|
317
|
+
- **option.forward**: url string to be parsed with the url module
|
|
318
|
+
- **option.agent**: object to be passed to http(s).request (see Node's [https agent](http://nodejs.org/api/https.html#https_class_https_agent) and [http agent](http://nodejs.org/api/http.html#http_class_http_agent) objects)
|
|
319
|
+
- **option.ssl**: object to be passed to https.createServer()
|
|
320
|
+
- **option.ws**: true/false: if you want to proxy websockets
|
|
321
|
+
- **option.xfwd**: true/false, adds x-forward headers
|
|
322
|
+
- **option.secure**: true/false, if you want to verify the SSL Certs
|
|
323
|
+
- **option.toProxy**: true/false, passes the absolute URL as the `path` (useful for proxying to proxies)
|
|
324
|
+
- **option.prependPath**: true/false, Default: true - specify whether you want to prepend the target's path to the proxy path
|
|
325
|
+
- **option.ignorePath**: true/false, Default: false - specify whether you want to ignore the proxy path of the incoming request (note: you will have to append / manually if required).
|
|
326
|
+
- **option.localAddress** : Local interface string to bind for outgoing connections
|
|
327
|
+
- **option.changeOrigin**: true/false, Default: false - changes the origin of the host header to the target URL
|
|
328
|
+
- **option.preserveHeaderKeyCase**: true/false, Default: false - specify whether you want to keep letter case of response header key
|
|
329
|
+
- **option.auth** : Basic authentication i.e. 'user:password' to compute an Authorization header.
|
|
330
|
+
- **option.hostRewrite**: rewrites the location hostname on (301/302/307/308) redirects.
|
|
331
|
+
- **option.autoRewrite**: rewrites the location host/port on (301/302/307/308) redirects based on requested host/port. Default: false.
|
|
332
|
+
- **option.protocolRewrite**: rewrites the location protocol on (301/302/307/308) redirects to 'http' or 'https'. Default: null.
|
|
333
|
+
- **option.cookieDomainRewrite**: rewrites domain of `set-cookie` headers. Possible values:
|
|
334
|
+
- `false` (default): disable cookie rewriting
|
|
335
|
+
- String: new domain, for example `cookieDomainRewrite: "new.domain"`. To remove the domain, use `cookieDomainRewrite: ""`.
|
|
336
|
+
- Object: mapping of domains to new domains, use `"*"` to match all domains.
|
|
337
|
+
For example keep one domain unchanged, rewrite one domain and remove other domains:
|
|
277
338
|
```
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
// listen for messages coming FROM the target here
|
|
283
|
-
proxySocket.on('data', hybiParseAndLogMessage);
|
|
339
|
+
cookieDomainRewrite: {
|
|
340
|
+
"unchanged.domain": "unchanged.domain",
|
|
341
|
+
"old.domain": "new.domain",
|
|
342
|
+
"*": ""
|
|
284
343
|
}
|
|
285
344
|
```
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
345
|
+
- **option.cookiePathRewrite**: rewrites path of `set-cookie` headers. Possible values:
|
|
346
|
+
- `false` (default): disable cookie rewriting
|
|
347
|
+
- String: new path, for example `cookiePathRewrite: "/newPath/"`. To remove the path, use `cookiePathRewrite: ""`. To set path to root use `cookiePathRewrite: "/"`.
|
|
348
|
+
- Object: mapping of paths to new paths, use `"*"` to match all paths.
|
|
349
|
+
For example, to keep one path unchanged, rewrite one path and remove other paths:
|
|
350
|
+
```
|
|
351
|
+
cookiePathRewrite: {
|
|
352
|
+
"/unchanged.path/": "/unchanged.path/",
|
|
353
|
+
"/old.path/": "/new.path/",
|
|
354
|
+
"*": ""
|
|
292
355
|
}
|
|
293
356
|
```
|
|
357
|
+
- **option.headers**: object, adds [request headers](https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Request_fields). (Example: `{host:'www.example.org'}`)
|
|
358
|
+
- **option.proxyTimeout**: timeout (in millis) when proxy receives no response from target
|
|
359
|
+
- **option.timeout**: timeout (in millis) for incoming requests
|
|
360
|
+
- **option.followRedirects**: true/false, Default: false - specify whether you want to follow redirects
|
|
361
|
+
- **option.selfHandleResponse** true/false, if set to true, none of the webOutgoing passes are called and it's your responsibility to appropriately return the response by listening and acting on the `proxyRes` event
|
|
362
|
+
- **option.buffer**: stream of data to send as the request body. Maybe you have some middleware that consumes the request stream before proxying it on e.g. If you read the body of a request into a field called 'req.rawbody' you could restream this field in the buffer option:
|
|
294
363
|
|
|
295
|
-
|
|
364
|
+
```
|
|
365
|
+
'use strict';
|
|
296
366
|
|
|
297
|
-
|
|
367
|
+
const streamify = require('stream-array');
|
|
368
|
+
const HttpProxy = require('http-proxy');
|
|
369
|
+
const proxy = new HttpProxy();
|
|
298
370
|
|
|
299
|
-
|
|
300
|
-
* **option.forward**: url string to be parsed with the url module
|
|
301
|
-
* **option.agent**: object to be passed to http(s).request (see Node's [https agent](http://nodejs.org/api/https.html#https_class_https_agent) and [http agent](http://nodejs.org/api/http.html#http_class_http_agent) objects)
|
|
302
|
-
* **option.ssl**: object to be passed to https.createServer()
|
|
303
|
-
* **option.ws**: true/false: if you want to proxy websockets
|
|
304
|
-
* **option.xfwd**: true/false, adds x-forward headers
|
|
305
|
-
* **option.secure**: true/false, if you want to verify the SSL Certs
|
|
306
|
-
* **option.toProxy**: true/false, passes the absolute URL as the `path` (useful for proxying to proxies)
|
|
307
|
-
* **option.prependPath**: true/false, Default: true - specify whether you want to prepend the target's path to the proxy path
|
|
308
|
-
* **option.ignorePath**: true/false, Default: false - specify whether you want to ignore the proxy path of the incoming request (note: you will have to append / manually if required).
|
|
309
|
-
* **option.localAddress** : Local interface string to bind for outgoing connections
|
|
310
|
-
* **option.changeOrigin**: true/false, Default: false - changes the origin of the host header to the target URL
|
|
311
|
-
* **option.auth** : Basic authentication i.e. 'user:password' to compute an Authorization header.
|
|
312
|
-
* **option.hostRewrite**: rewrites the location hostname on (301/302/307/308) redirects.
|
|
313
|
-
* **option.autoRewrite**: rewrites the location host/port on (301/302/307/308) redirects based on requested host/port. Default: false.
|
|
314
|
-
* **option.protocolRewrite**: rewrites the location protocol on (301/302/307/308) redirects to 'http' or 'https'. Default: null.
|
|
315
|
-
* **option.cookieDomainRewrite**: rewrites domain of `set-cookie` headers. Possible values:
|
|
316
|
-
* `false` (default): disable cookie rewriting
|
|
317
|
-
* String: new domain, for example `cookieDomainRewrite: "new.domain"`. To remove the domain, use `cookieDomainRewrite: ""`.
|
|
318
|
-
* Object: mapping of domains to new domains, use `"*"` to match all domains.
|
|
319
|
-
For example keep one domain unchanged, rewrite one domain and remove other domains:
|
|
320
|
-
```
|
|
321
|
-
cookieDomainRewrite: {
|
|
322
|
-
"unchanged.domain": "unchanged.domain",
|
|
323
|
-
"old.domain": "new.domain",
|
|
324
|
-
"*": ""
|
|
325
|
-
}
|
|
326
|
-
```
|
|
327
|
-
* **option.headers**: object, adds [request headers](https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Request_fields). (Example: `{host:'www.example.org'}`)
|
|
328
|
-
* **option.proxyTimeout**: timeout (in millis) when proxy receives no response from target
|
|
371
|
+
module.exports = (req, res, next) => {
|
|
329
372
|
|
|
373
|
+
proxy.web(req, res, {
|
|
374
|
+
target: 'http://localhost:4003/',
|
|
375
|
+
buffer: streamify(req.rawBody)
|
|
376
|
+
}, next);
|
|
330
377
|
|
|
378
|
+
};
|
|
379
|
+
```
|
|
331
380
|
|
|
332
381
|
## Shorthand
|
|
333
382
|
|
|
334
383
|
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.
|
|
335
384
|
|
|
336
385
|
```javascript
|
|
337
|
-
proxy('http://www.example.org:8000/api')
|
|
386
|
+
proxy('http://www.example.org:8000/api')
|
|
338
387
|
// proxy('/api', {target: 'http://www.example.org:8000'});
|
|
339
388
|
|
|
340
|
-
|
|
341
|
-
proxy('http://www.example.org:8000/api/books/*/**.json');
|
|
389
|
+
proxy('http://www.example.org:8000/api/books/*/**.json')
|
|
342
390
|
// proxy('/api/books/*/**.json', {target: 'http://www.example.org:8000'});
|
|
343
391
|
|
|
344
|
-
|
|
345
|
-
proxy('http://www.example.org:8000/api', {changeOrigin:true});
|
|
392
|
+
proxy('http://www.example.org:8000/api', { changeOrigin: true })
|
|
346
393
|
// proxy('/api', {target: 'http://www.example.org:8000', changeOrigin: true});
|
|
347
394
|
```
|
|
348
395
|
|
|
349
396
|
### app.use(path, proxy)
|
|
350
397
|
|
|
351
|
-
If you want to use the server's `app.use` `path` parameter to match requests;
|
|
398
|
+
If you want to use the server's `app.use` `path` parameter to match requests;
|
|
352
399
|
Create and mount the proxy without the http-proxy-middleware `context` parameter:
|
|
400
|
+
|
|
353
401
|
```javascript
|
|
354
|
-
app.use('/api', proxy({target:'http://www.example.org', changeOrigin:true}))
|
|
402
|
+
app.use('/api', proxy({ target: 'http://www.example.org', changeOrigin: true }))
|
|
355
403
|
```
|
|
356
404
|
|
|
357
405
|
`app.use` documentation:
|
|
358
|
-
|
|
359
|
-
|
|
406
|
+
|
|
407
|
+
- express: http://expressjs.com/en/4x/api.html#app.use
|
|
408
|
+
- connect: https://github.com/senchalabs/connect#mount-middleware
|
|
360
409
|
|
|
361
410
|
## WebSocket
|
|
362
411
|
|
|
363
412
|
```javascript
|
|
364
413
|
// verbose api
|
|
365
|
-
proxy('/', {target:'http://echo.websocket.org', ws:true})
|
|
414
|
+
proxy('/', { target: 'http://echo.websocket.org', ws: true })
|
|
366
415
|
|
|
367
416
|
// shorthand
|
|
368
|
-
proxy('http://echo.websocket.org', {ws:true})
|
|
417
|
+
proxy('http://echo.websocket.org', { ws: true })
|
|
369
418
|
|
|
370
419
|
// shorter shorthand
|
|
371
|
-
proxy('ws://echo.websocket.org')
|
|
420
|
+
proxy('ws://echo.websocket.org')
|
|
372
421
|
```
|
|
373
422
|
|
|
374
423
|
### External WebSocket upgrade
|
|
375
424
|
|
|
376
425
|
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.
|
|
426
|
+
|
|
377
427
|
```javascript
|
|
378
|
-
var wsProxy = proxy('ws://echo.websocket.org', {changeOrigin:true})
|
|
428
|
+
var wsProxy = proxy('ws://echo.websocket.org', { changeOrigin: true })
|
|
379
429
|
|
|
380
|
-
var app = express()
|
|
381
|
-
|
|
430
|
+
var app = express()
|
|
431
|
+
app.use(wsProxy)
|
|
382
432
|
|
|
383
|
-
var server = app.listen(3000)
|
|
384
|
-
|
|
433
|
+
var server = app.listen(3000)
|
|
434
|
+
server.on('upgrade', wsProxy.upgrade) // <-- subscribe to http 'upgrade'
|
|
385
435
|
```
|
|
386
436
|
|
|
387
|
-
|
|
388
437
|
## Working examples
|
|
389
438
|
|
|
390
439
|
View and play around with [working examples](https://github.com/chimurai/http-proxy-middleware/tree/master/examples).
|
|
391
440
|
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
441
|
+
- Browser-Sync ([example source](https://github.com/chimurai/http-proxy-middleware/tree/master/examples/browser-sync/index.js))
|
|
442
|
+
- express ([example source](https://github.com/chimurai/http-proxy-middleware/tree/master/examples/express/index.js))
|
|
443
|
+
- connect ([example source](https://github.com/chimurai/http-proxy-middleware/tree/master/examples/connect/index.js))
|
|
444
|
+
- WebSocket ([example source](https://github.com/chimurai/http-proxy-middleware/tree/master/examples/websocket/index.js))
|
|
396
445
|
|
|
397
446
|
## Recipes
|
|
398
447
|
|
|
@@ -401,14 +450,15 @@ View the [recipes](https://github.com/chimurai/http-proxy-middleware/tree/master
|
|
|
401
450
|
## Compatible servers
|
|
402
451
|
|
|
403
452
|
`http-proxy-middleware` is compatible with the following servers:
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
453
|
+
|
|
454
|
+
- [connect](https://www.npmjs.com/package/connect)
|
|
455
|
+
- [express](https://www.npmjs.com/package/express)
|
|
456
|
+
- [browser-sync](https://www.npmjs.com/package/browser-sync)
|
|
457
|
+
- [lite-server](https://www.npmjs.com/package/lite-server)
|
|
458
|
+
- [grunt-contrib-connect](https://www.npmjs.com/package/grunt-contrib-connect)
|
|
459
|
+
- [grunt-browser-sync](https://www.npmjs.com/package/grunt-browser-sync)
|
|
460
|
+
- [gulp-connect](https://www.npmjs.com/package/gulp-connect)
|
|
461
|
+
- [gulp-webserver](https://www.npmjs.com/package/gulp-webserver)
|
|
412
462
|
|
|
413
463
|
Sample implementations can be found in the [server recipes](https://github.com/chimurai/http-proxy-middleware/tree/master/recipes/servers.md).
|
|
414
464
|
|
|
@@ -419,18 +469,13 @@ Run the test suite:
|
|
|
419
469
|
```bash
|
|
420
470
|
# install dependencies
|
|
421
471
|
$ npm install
|
|
422
|
-
```
|
|
423
472
|
|
|
424
|
-
|
|
473
|
+
# linting
|
|
474
|
+
$ npm run lint
|
|
425
475
|
|
|
426
|
-
```bash
|
|
427
476
|
# unit tests
|
|
428
477
|
$ npm test
|
|
429
|
-
```
|
|
430
478
|
|
|
431
|
-
coverage
|
|
432
|
-
|
|
433
|
-
```bash
|
|
434
479
|
# code coverage
|
|
435
480
|
$ npm run cover
|
|
436
481
|
```
|
|
@@ -439,9 +484,8 @@ $ npm run cover
|
|
|
439
484
|
|
|
440
485
|
- [View changelog](https://github.com/chimurai/http-proxy-middleware/blob/master/CHANGELOG.md)
|
|
441
486
|
|
|
442
|
-
|
|
443
487
|
## License
|
|
444
488
|
|
|
445
489
|
The MIT License (MIT)
|
|
446
490
|
|
|
447
|
-
Copyright (c) 2015-
|
|
491
|
+
Copyright (c) 2015-2018 Steven Chim
|