Projekt

Obecné

Profil

Stáhnout (17.9 KB) Statistiky
| Větev: | Revize:
1 3a515b92 cagy
# http-proxy-middleware
2
3
[![Build Status](https://img.shields.io/travis/chimurai/http-proxy-middleware/master.svg?style=flat-square)](https://travis-ci.org/chimurai/http-proxy-middleware)
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://img.shields.io/david/chimurai/http-proxy-middleware.svg?style=flat-square)](https://david-dm.org/chimurai/http-proxy-middleware#info=dependencies)
6
[![dependency Status](https://snyk.io/test/npm/http-proxy-middleware/badge.svg)](https://snyk.io/test/npm/http-proxy-middleware)
7
[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)
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).
10
11
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)
12
13
## TL;DR
14
15
Proxy `/api` requests to `http://www.example.org`
16
17
```javascript
18
var express = require('express')
19
var proxy = require('http-proxy-middleware')
20
21
var app = express()
22
23
app.use('/api', proxy({ target: 'http://www.example.org', changeOrigin: true }))
24
app.listen(3000)
25
26
// http://localhost:3000/api/foo/bar -> http://www.example.org/api/foo/bar
27
```
28
29
_All_ `http-proxy` [options](https://github.com/nodejitsu/node-http-proxy#options) can be used, along with some extra `http-proxy-middleware` [options](#options).
30
31
:bulb: **Tip:** Set the option `changeOrigin` to `true` for [name-based virtual hosted sites](http://en.wikipedia.org/wiki/Virtual_hosting#Name-based).
32
33
## Table of Contents
34
35
<!-- MarkdownTOC autolink=true bracket=round depth=2 -->
36
37
- [Install](#install)
38
- [Core concept](#core-concept)
39
- [Example](#example)
40
- [Context matching](#context-matching)
41
- [Options](#options)
42
  - [http-proxy-middleware options](#http-proxy-middleware-options)
43
  - [http-proxy events](#http-proxy-events)
44
  - [http-proxy options](#http-proxy-options)
45
- [Shorthand](#shorthand)
46
  - [app.use\(path, proxy\)](#appusepath-proxy)
47
- [WebSocket](#websocket)
48
  - [External WebSocket upgrade](#external-websocket-upgrade)
49
- [Working examples](#working-examples)
50
- [Recipes](#recipes)
51
- [Compatible servers](#compatible-servers)
52
- [Tests](#tests)
53
- [Changelog](#changelog)
54
- [License](#license)
55
56
<!-- /MarkdownTOC -->
57
58
## Install
59
60
```javascript
61
$ npm install --save-dev http-proxy-middleware
62
```
63
64
## Core concept
65
66
Proxy middleware configuration.
67
68
#### proxy([context,] config)
69
70
```javascript
71
var proxy = require('http-proxy-middleware')
72
73
var apiProxy = proxy('/api', { target: 'http://www.example.org' })
74
//                   \____/   \_____________________________/
75
//                     |                    |
76
//                   context             options
77
78
// 'apiProxy' is now ready to be used as middleware in a server.
79
```
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)_
84
85
(full list of [`http-proxy-middleware` configuration options](#options))
86
87
#### proxy(uri [, config])
88
89
```javascript
90
// shorthand syntax for the example above:
91
var apiProxy = proxy('http://www.example.org/api')
92
```
93
94
More about the [shorthand configuration](#shorthand).
95
96
## Example
97
98
An example with `express` server.
99
100
```javascript
101
// include dependencies
102
var express = require('express')
103
var proxy = require('http-proxy-middleware')
104
105
// proxy middleware options
106
var options = {
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
}
120
121
// create the proxy (without context)
122
var exampleProxy = proxy(options)
123
124
// mount `exampleProxy` in web server
125
var app = express()
126
app.use('/api', exampleProxy)
127
app.listen(3000)
128
```
129
130
## Context matching
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.
133
134
[RFC 3986 `path`](https://tools.ietf.org/html/rfc3986#section-3.3) is used for context matching.
135
136
```
137
         foo://example.com:8042/over/there?name=ferret#nose
138
         \_/   \______________/\_________/ \_________/ \__/
139
          |           |            |            |        |
140
       scheme     authority       path        query   fragment
141
```
142
143
- **path matching**
144
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`
148
149
- **multiple path matching**
150
151
  - `proxy(['/api', '/ajax', '/someotherpath'], {...})`
152
153
- **wildcard path matching**
154
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.
156
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
163
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
184
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
242
    }
243
    return myCustomProvider
244
  }
245
  ```
246
247
- (DEPRECATED) **option.proxyHost**: Use `option.changeOrigin = true` instead.
248
- (DEPRECATED) **option.proxyTable**: Use `option.router` instead.
249
250
### http-proxy events
251
252
Subscribe to [http-proxy events](https://github.com/nodejitsu/node-http-proxy#listening-for-proxy-events):
253
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
  ```
311
312
### http-proxy options
313
314
The following options are provided by the underlying [http-proxy](https://github.com/nodejitsu/node-http-proxy#options) library.
315
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:
338
    ```
339
    cookieDomainRewrite: {
340
      "unchanged.domain": "unchanged.domain",
341
      "old.domain": "new.domain",
342
      "*": ""
343
    }
344
    ```
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
      "*": ""
355
    }
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:
363
364
  ```
365
  'use strict';
366
367
  const streamify = require('stream-array');
368
  const HttpProxy = require('http-proxy');
369
  const proxy = new HttpProxy();
370
371
  module.exports = (req, res, next) => {
372
373
    proxy.web(req, res, {
374
      target: 'http://localhost:4003/',
375
      buffer: streamify(req.rawBody)
376
    }, next);
377
378
  };
379
  ```
380
381
## Shorthand
382
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.
384
385
```javascript
386
proxy('http://www.example.org:8000/api')
387
// proxy('/api', {target: 'http://www.example.org:8000'});
388
389
proxy('http://www.example.org:8000/api/books/*/**.json')
390
// proxy('/api/books/*/**.json', {target: 'http://www.example.org:8000'});
391
392
proxy('http://www.example.org:8000/api', { changeOrigin: true })
393
// proxy('/api', {target: 'http://www.example.org:8000', changeOrigin: true});
394
```
395
396
### app.use(path, proxy)
397
398
If you want to use the server's `app.use` `path` parameter to match requests;
399
Create and mount the proxy without the http-proxy-middleware `context` parameter:
400
401
```javascript
402
app.use('/api', proxy({ target: 'http://www.example.org', changeOrigin: true }))
403
```
404
405
`app.use` documentation:
406
407
- express: http://expressjs.com/en/4x/api.html#app.use
408
- connect: https://github.com/senchalabs/connect#mount-middleware
409
410
## WebSocket
411
412
```javascript
413
// verbose api
414
proxy('/', { target: 'http://echo.websocket.org', ws: true })
415
416
// shorthand
417
proxy('http://echo.websocket.org', { ws: true })
418
419
// shorter shorthand
420
proxy('ws://echo.websocket.org')
421
```
422
423
### External WebSocket upgrade
424
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
427
```javascript
428
var wsProxy = proxy('ws://echo.websocket.org', { changeOrigin: true })
429
430
var app = express()
431
app.use(wsProxy)
432
433
var server = app.listen(3000)
434
server.on('upgrade', wsProxy.upgrade) // <-- subscribe to http 'upgrade'
435
```
436
437
## Working examples
438
439
View and play around with [working examples](https://github.com/chimurai/http-proxy-middleware/tree/master/examples).
440
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))
445
446
## Recipes
447
448
View the [recipes](https://github.com/chimurai/http-proxy-middleware/tree/master/recipes) for common use cases.
449
450
## Compatible servers
451
452
`http-proxy-middleware` is compatible with the following servers:
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)
462
463
Sample implementations can be found in the [server recipes](https://github.com/chimurai/http-proxy-middleware/tree/master/recipes/servers.md).
464
465
## Tests
466
467
Run the test suite:
468
469
```bash
470
# install dependencies
471
$ npm install
472
473
# linting
474
$ npm run lint
475
476
# unit tests
477
$ npm test
478
479
# code coverage
480
$ npm run cover
481
```
482
483
## Changelog
484
485
- [View changelog](https://github.com/chimurai/http-proxy-middleware/blob/master/CHANGELOG.md)
486
487
## License
488
489
The MIT License (MIT)
490
491
Copyright (c) 2015-2018 Steven Chim