UNPKG

15.6 kBMarkdownView Raw
1# 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
7Node.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
9Powered 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
11## TL;DR
12
13Proxy `/api` requests to `http://www.example.org`
14
15```javascript
16var express = require('express');
17var proxy = require('http-proxy-middleware');
18
19var app = express();
20
21app.use('/api', proxy({target: 'http://www.example.org', changeOrigin: true}));
22app.listen(3000);
23
24// http://localhost:3000/api/foo/bar -> http://www.example.org/api/foo/bar
25```
26
27_All_ `http-proxy` [options](https://github.com/nodejitsu/node-http-proxy#options) can be used, along with some extra `http-proxy-middleware` [options](#options).
28
29:bulb: **Tip:** Set the option `changeOrigin` to `true` for [name-based virtual hosted sites](http://en.wikipedia.org/wiki/Virtual_hosting#Name-based).
30
31## Table of Contents
32
33<!-- MarkdownTOC autolink=true bracket=round depth=3 -->
34
35- [Install](#install)
36- [Core concept](#core-concept)
37- [Example](#example)
38- [Context matching](#context-matching)
39- [Options](#options)
40 - [http-proxy-middleware options](#http-proxy-middleware-options)
41 - [http-proxy events](#http-proxy-events)
42 - [http-proxy options](#http-proxy-options)
43- [Shorthand](#shorthand)
44 - [app.use\(path, proxy\)](#appusepath-proxy)
45- [WebSocket](#websocket)
46 - [External WebSocket upgrade](#external-websocket-upgrade)
47- [Working examples](#working-examples)
48- [Recipes](#recipes)
49- [Compatible servers](#compatible-servers)
50- [Tests](#tests)
51- [Changelog](#changelog)
52- [License](#license)
53
54<!-- /MarkdownTOC -->
55
56
57## Install
58
59```javascript
60$ npm install --save-dev http-proxy-middleware
61```
62
63## Core concept
64
65Proxy middleware configuration.
66
67#### proxy([context,] config)
68
69```javascript
70var proxy = require('http-proxy-middleware');
71
72var apiProxy = proxy('/api', {target: 'http://www.example.org'});
73// \____/ \_____________________________/
74// | |
75// context options
76
77// 'apiProxy' is now ready to be used as middleware in a server.
78```
79* **context**: Determine which requests should be proxied to the target host.
80 (more on [context matching](#context-matching))
81* **options.target**: target host to proxy to. _(protocol + host)_
82
83(full list of [`http-proxy-middleware` configuration options](#options))
84
85#### proxy(uri [, config])
86
87``` javascript
88// shorthand syntax for the example above:
89var apiProxy = proxy('http://www.example.org/api');
90
91```
92More about the [shorthand configuration](#shorthand).
93
94## Example
95
96An example with `express` server.
97
98```javascript
99// include dependencies
100var express = require('express');
101var proxy = require('http-proxy-middleware');
102
103// proxy middleware options
104var options = {
105 target: 'http://www.example.org', // target host
106 changeOrigin: true, // needed for virtual hosted sites
107 ws: true, // proxy websockets
108 pathRewrite: {
109 '^/old/api' : '/new/api', // rewrite path
110 '^/remove/api' : '/api' // remove path
111 },
112 proxyTable: {
113 // when request.headers.host == 'dev.localhost:3000',
114 // override target 'http://www.example.org' to 'http://localhost:8000'
115 'dev.localhost:3000' : 'http://localhost:8000'
116 }
117 };
118
119// create the proxy (without context)
120var exampleProxy = proxy(options);
121
122// mount `exampleProxy` in web server
123var app = express();
124 app.use('/api', exampleProxy);
125 app.listen(3000);
126```
127
128## Context matching
129
130Providing 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. Request URL's [ _path-absolute_ and _query_](https://tools.ietf.org/html/rfc3986#section-3) will be used for context matching.
131
132* **path matching**
133 - `proxy({...})` or `proxy('/', {...})` - matches any path, all requests will be proxied.
134 - `proxy('/api', {...})` - matches paths starting with `/api`
135
136* **multiple path matching**
137 - `proxy(['/api', '/ajax', '/someotherpath'], {...})`
138
139* **wildcard path matching**
140
141 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.
142 - `proxy('**', {...})` matches any path, all requests will be proxied.
143 - `proxy('**/*.html', {...})` matches any path which ends with `.html`
144 - `proxy('/*.html', {...})` matches paths directly under path-absolute
145 - `proxy('/api/**/*.html', {...})` matches requests ending with `.html` in the path of `/api`
146 - `proxy(['/api/**', '/ajax/**'], {...})` combine multiple patterns
147 - `proxy(['/api/**', '!**/bad.json'], {...})` exclusion
148
149* **custom matching**
150
151 For full control you can provide a custom function to determine which requests should be proxied or not.
152 ```javascript
153 /**
154 * @return {Boolean}
155 */
156 var filter = function (path, req) {
157 return (path.match('^/api') && req.method === 'GET');
158 };
159
160 var apiProxy = proxy(filter, {target: 'http://www.example.org'})
161 ```
162
163## Options
164
165### http-proxy-middleware options
166
167* **option.pathRewrite**: object/function, rewrite target's url path. Object-keys will be used as _RegExp_ to match paths.
168 ```javascript
169 // rewrite path
170 pathRewrite: {'^/old/api' : '/new/api'}
171
172 // remove path
173 pathRewrite: {'^/remove/api' : ''}
174
175 // add base path
176 pathRewrite: {'^/' : '/basepath/'}
177
178 // custom rewriting
179 pathRewrite: function (path, req) { return path.replace('/api', '/base/api') }
180 ```
181
182* **option.proxyTable**: object, re-target `option.target` based on the request header `host` parameter. `host` can be used in conjunction with `path`. Only one instance of the proxy will be used. The order of the configuration matters.
183 ```javascript
184 proxyTable: {
185 'integration.localhost:3000' : 'http://localhost:8001', // host only
186 'staging.localhost:3000' : 'http://localhost:8002', // host only
187 'localhost:3000/api' : 'http://localhost:8003', // host + path
188 '/rest' : 'http://localhost:8004' // path only
189 }
190 ```
191
192* **option.logLevel**: string, ['debug', 'info', 'warn', 'error', 'silent']. Default: `'info'`
193
194* **option.logProvider**: function, modify or replace log provider. Default: `console`.
195 ```javascript
196 // simple replace
197 function logProvider(provider) {
198 // replace the default console log provider.
199 return require('winston');
200 }
201 ```
202
203 ```javascript
204 // verbose replacement
205 function logProvider(provider) {
206 var logger = new (require('winston').Logger)();
207
208 var myCustomProvider = {
209 log: logger.log,
210 debug: logger.debug,
211 info: logger.info,
212 warn: logger.warn,
213 error: logger.error
214 }
215 return myCustomProvider;
216 }
217 ```
218* (DEPRECATED) **option.proxyHost**: Use `option.changeOrigin = true` instead.
219
220
221### http-proxy events
222
223Subscribe to [http-proxy events](https://github.com/nodejitsu/node-http-proxy#listening-for-proxy-events):
224
225* **option.onError**: function, subscribe to http-proxy's `error` event for custom error handling.
226 ```javascript
227 function onError(err, req, res) {
228 res.writeHead(500, {
229 'Content-Type': 'text/plain'
230 });
231 res.end('Something went wrong. And we are reporting a custom error message.');
232 }
233 ```
234
235* **option.onProxyRes**: function, subscribe to http-proxy's `proxyRes` event.
236 ```javascript
237 function onProxyRes(proxyRes, req, res) {
238 proxyRes.headers['x-added'] = 'foobar'; // add new header to response
239 delete proxyRes.headers['x-removed']; // remove header from response
240 }
241 ```
242
243* **option.onProxyReq**: function, subscribe to http-proxy's `proxyReq` event.
244 ```javascript
245 function onProxyReq(proxyReq, req, res) {
246 // add custom header to request
247 proxyReq.setHeader('x-added', 'foobar');
248 // or log the req
249 }
250 ```
251
252* **option.onProxyReqWs**: function, subscribe to http-proxy's `proxyReqWs` event.
253 ```javascript
254 function onProxyReqWs(proxyReq, req, socket, options, head) {
255 // add custom header
256 proxyReq.setHeader('X-Special-Proxy-Header', 'foobar');
257 }
258 ```
259
260* **option.onOpen**: function, subscribe to http-proxy's `open` event.
261 ```javascript
262 function onOpen(proxySocket) {
263 // listen for messages coming FROM the target here
264 proxySocket.on('data', hybiParseAndLogMessage);
265 }
266 ```
267
268* **option.onClose**: function, subscribe to http-proxy's `close` event.
269 ```javascript
270 function onClose(res, socket, head) {
271 // view disconnected websocket connections
272 console.log('Client disconnected');
273 }
274 ```
275
276### http-proxy options
277
278The following options are provided by the underlying [http-proxy](https://github.com/nodejitsu/node-http-proxy#options) library.
279
280* **option.target**: url string to be parsed with the url module
281* **option.forward**: url string to be parsed with the url module
282* **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)
283* **option.ssl**: object to be passed to https.createServer()
284* **option.ws**: true/false: if you want to proxy websockets
285* **option.xfwd**: true/false, adds x-forward headers
286* **option.secure**: true/false, if you want to verify the SSL Certs
287* **option.toProxy**: true/false, passes the absolute URL as the `path` (useful for proxying to proxies)
288* **option.prependPath**: true/false, Default: true - specify whether you want to prepend the target's path to the proxy path>
289* **option.ignorePath**: true/false, Default: false - specify whether you want to ignore the proxy path of the incoming request>
290* **option.localAddress** : Local interface string to bind for outgoing connections
291* **option.changeOrigin**: true/false, adds host to request header.
292* **option.auth** : Basic authentication i.e. 'user:password' to compute an Authorization header.
293* **option.hostRewrite**: rewrites the location hostname on (301/302/307/308) redirects.
294* **option.autoRewrite**: rewrites the location host/port on (301/302/307/308) redirects based on requested host/port. Default: false.
295* **option.protocolRewrite**: rewrites the location protocol on (301/302/307/308) redirects to 'http' or 'https'. Default: null.
296* **option.headers**: object, adds [request headers](https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Request_fields). (Example: `{host:'www.example.org'}`)
297
298
299## Shorthand
300
301Use 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.
302
303```javascript
304proxy('http://www.example.org:8000/api');
305// proxy('/api', {target: 'http://www.example.org:8000'});
306
307
308proxy('http://www.example.org:8000/api/books/*/**.json');
309// proxy('/api/books/*/**.json', {target: 'http://www.example.org:8000'});
310
311
312proxy('http://www.example.org:8000/api', {changeOrigin:true});
313// proxy('/api', {target: 'http://www.example.org:8000', changeOrigin: true});
314```
315
316### app.use(path, proxy)
317
318If you want to use the server's `app.use` `path` parameter to match requests;
319Create and mount the proxy without the http-proxy-middleware `context` parameter:
320```javascript
321app.use('/api', proxy({target:'http://www.example.org', changeOrigin:true}));
322```
323
324`app.use` documentation:
325* express: http://expressjs.com/en/4x/api.html#app.use
326* connect: https://github.com/senchalabs/connect#mount-middleware
327
328## WebSocket
329
330```javascript
331// verbose api
332proxy('/', {target:'http://echo.websocket.org', ws:true});
333
334// shorthand
335proxy('http://echo.websocket.org', {ws:true});
336
337// shorter shorthand
338proxy('ws://echo.websocket.org');
339```
340
341### External WebSocket upgrade
342
343In 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.
344```javascript
345var wsProxy = proxy('ws://echo.websocket.org', {changeOrigin:true});
346
347var app = express();
348 app.use(wsProxy);
349
350var server = app.listen(3000);
351 server.on('upgrade', wsProxy.upgrade); // <-- subscribe to http 'upgrade'
352```
353
354
355## Working examples
356
357View and play around with [working examples](https://github.com/chimurai/http-proxy-middleware/tree/master/examples).
358
359* Browser-Sync ([example source](https://github.com/chimurai/http-proxy-middleware/tree/master/examples/browser-sync/index.js))
360* express ([example source](https://github.com/chimurai/http-proxy-middleware/tree/master/examples/express/index.js))
361* connect ([example source](https://github.com/chimurai/http-proxy-middleware/tree/master/examples/connect/index.js))
362* WebSocket ([example source](https://github.com/chimurai/http-proxy-middleware/tree/master/examples/websocket/index.js))
363
364## Recipes
365
366View the [recipes](https://github.com/chimurai/http-proxy-middleware/tree/master/recipes) for common use cases.
367
368## Compatible servers
369
370`http-proxy-middleware` is compatible with the following servers:
371* [connect](https://www.npmjs.com/package/connect)
372* [express](https://www.npmjs.com/package/express)
373* [browser-sync](https://www.npmjs.com/package/browser-sync)
374* [lite-server](https://www.npmjs.com/package/lite-server)
375* [grunt-contrib-connect](https://www.npmjs.com/package/grunt-contrib-connect)
376* [grunt-browser-sync](https://www.npmjs.com/package/grunt-browser-sync)
377* [gulp-connect](https://www.npmjs.com/package/gulp-connect)
378* [gulp-webserver](https://www.npmjs.com/package/gulp-webserver)
379
380Sample implementations can be found in the [server recipes](https://github.com/chimurai/http-proxy-middleware/tree/master/recipes/servers.md).
381
382## Tests
383
384Run the test suite:
385
386```bash
387# install dependencies
388$ npm install
389```
390
391unit testing
392
393```bash
394# unit tests
395$ npm test
396```
397
398coverage
399
400```bash
401# code coverage
402$ npm run cover
403```
404
405## Changelog
406
407- [View changelog](https://github.com/chimurai/http-proxy-middleware/blob/master/CHANGELOG.md)
408
409
410## License
411
412The MIT License (MIT)
413
414Copyright (c) 2015-2016 Steven Chim