1 # node-http-proxy [![Build Status](https://secure.travis-ci.org/nodejitsu/node-http-proxy.png)](http://travis-ci.org/nodejitsu/node-http-proxy)
3 <img src="http://i.imgur.com/8fTt9.png" />
5 ## Battle-hardened node.js http proxy
9 * Reverse proxies incoming http.ServerRequest streams
10 * Can be used as a CommonJS module in node.js
11 * Reverse or Forward Proxy based on simple JSON-based configuration
12 * Supports [WebSockets][1]
14 * Minimal request overhead and latency
15 * Full suite of functional tests
16 * Battled-hardened through __production usage__ @ [nodejitsu.com][0]
17 * Written entirely in Javascript
21 node-http-proxy is `<= 0.8.x` compatible, if you're looking for a `>= 0.10` compatible version please check [caronte](https://github.com/nodejitsu/node-http-proxy/tree/caronte)
23 ### When to use node-http-proxy
25 Let's suppose you were running multiple http application servers, but you only wanted to expose one machine to the internet. You could setup node-http-proxy on that one machine and then reverse-proxy the incoming http requests to locally running services which were not exposed to the outside network.
27 ### Installing npm (node package manager)
30 curl https://npmjs.org/install.sh | sh
33 ### Installing node-http-proxy
36 npm install http-proxy
39 ## Using node-http-proxy
41 There are several ways to use node-http-proxy; the library is designed to be flexible so that it can be used by itself, or in conjunction with other node.js libraries / tools:
43 1. Standalone HTTP Proxy server
44 2. Inside of another HTTP server (like Connect)
45 3. In conjunction with a Proxy Routing Table
46 4. As a forward-proxy with a reverse proxy
47 5. From the command-line as a long running process
48 6. customized with 3rd party middleware.
50 In each of these scenarios node-http-proxy can handle any of these types of requests:
52 1. HTTP Requests (http://)
53 2. HTTPS Requests (https://)
54 3. WebSocket Requests (ws://)
55 4. Secure WebSocket Requests (wss://)
57 See the [examples][3] for more working sample code.
59 ### Setup a basic stand-alone proxy server
62 var http = require('http'),
63 httpProxy = require('http-proxy');
65 // Create your proxy server
67 httpProxy.createServer(9000, 'localhost').listen(8000);
70 // Create your target server
72 http.createServer(function (req, res) {
73 res.writeHead(200, { 'Content-Type': 'text/plain' });
74 res.write('request successfully proxied!' + '\n' + JSON.stringify(req.headers, true, 2));
79 ### Setup a stand-alone proxy server with custom server logic
82 var http = require('http'),
83 httpProxy = require('http-proxy');
86 // Create a proxy server with custom application logic
88 httpProxy.createServer(function (req, res, proxy) {
90 // Put your custom server logic here
92 proxy.proxyRequest(req, res, {
98 http.createServer(function (req, res) {
99 res.writeHead(200, { 'Content-Type': 'text/plain' });
100 res.write('request successfully proxied: ' + req.url +'\n' + JSON.stringify(req.headers, true, 2));
105 ### Setup a stand-alone proxy server with latency (e.g. IO, etc)
108 var http = require('http'),
109 httpProxy = require('http-proxy');
112 // Create a proxy server with custom application logic
114 httpProxy.createServer(function (req, res, proxy) {
116 // Buffer the request so that `data` and `end` events
117 // are not lost during async operation(s).
119 var buffer = httpProxy.buffer(req);
122 // Wait for two seconds then respond: this simulates
123 // performing async actions before proxying a request
125 setTimeout(function () {
126 proxy.proxyRequest(req, res, {
134 http.createServer(function (req, res) {
135 res.writeHead(200, { 'Content-Type': 'text/plain' });
136 res.write('request successfully proxied: ' + req.url +'\n' + JSON.stringify(req.headers, true, 2));
141 ### Proxy requests within another http server
144 var http = require('http'),
145 httpProxy = require('http-proxy');
148 // Create a new instance of HttProxy to use in your server
150 var proxy = new httpProxy.RoutingProxy();
153 // Create a regular http server and proxy its handler
155 http.createServer(function (req, res) {
157 // Put your custom server logic here, then proxy
159 proxy.proxyRequest(req, res, {
165 http.createServer(function (req, res) {
166 res.writeHead(200, { 'Content-Type': 'text/plain' });
167 res.write('request successfully proxied: ' + req.url +'\n' + JSON.stringify(req.headers, true, 2));
172 ### Proxy requests using a ProxyTable
173 A Proxy Table is a simple lookup table that maps incoming requests to proxy target locations. Take a look at an example of the options you need to pass to httpProxy.createServer:
178 'foo.com/baz': '127.0.0.1:8001',
179 'foo.com/buz': '127.0.0.1:8002',
180 'bar.com/buz': '127.0.0.1:8003'
185 The above route table will take incoming requests to 'foo.com/baz' and forward them to '127.0.0.1:8001'. Likewise it will take incoming requests to 'foo.com/buz' and forward them to '127.0.0.1:8002'. The routes themselves are later converted to regular expressions to enable more complex matching functionality. We can create a proxy server with these options by using the following code:
188 var proxyServer = httpProxy.createServer(options);
189 proxyServer.listen(80);
192 ### Proxy requests using a 'Hostname Only' ProxyTable
193 As mentioned in the previous section, all routes passes to the ProxyTable are by default converted to regular expressions that are evaluated at proxy-time. This is good for complex URL rewriting of proxy requests, but less efficient when one simply wants to do pure hostname routing based on the HTTP 'Host' header. If you are only concerned with hostname routing, you change the lookup used by the internal ProxyTable:
199 'foo.com': '127.0.0.1:8001',
200 'bar.com': '127.0.0.1:8002'
205 Notice here that I have not included paths on the individual domains because this is not possible when using only the HTTP 'Host' header. Care to learn more? See [RFC2616: HTTP/1.1, Section 14.23, "Host"][4].
207 ### Proxy requests using a 'Pathname Only' ProxyTable
209 If you dont care about forwarding to different hosts, you can redirect based on the request path.
215 '/wiki': '127.0.0.1:8001',
216 '/blog': '127.0.0.1:8002',
217 '/api': '127.0.0.1:8003'
222 This comes in handy if you are running separate services or applications on separate paths. Note, using this option disables routing by hostname entirely.
225 ### Proxy requests with an additional forward proxy
226 Sometimes in addition to a reverse proxy, you may want your front-facing server to forward traffic to another location. For example, if you wanted to load test your staging environment. This is possible when using node-http-proxy using similar JSON-based configuration to a proxy table:
229 var proxyServerWithForwarding = httpProxy.createServer(9000, 'localhost', {
235 proxyServerWithForwarding.listen(80);
238 The forwarding option can be used in conjunction with the proxy table options by simply including both the 'forward' and 'router' properties in the options passed to 'createServer'.
240 ### Listening for proxy events
241 Sometimes you want to listen to an event on a proxy. For example, you may want to listen to the 'end' event, which represents when the proxy has finished proxying a request.
244 var httpProxy = require('http-proxy');
246 var server = httpProxy.createServer(function (req, res, proxy) {
247 var buffer = httpProxy.buffer(req);
249 proxy.proxyRequest(req, res, {
256 server.proxy.on('end', function () {
257 console.log("The request was proxied.");
263 It's important to remember not to listen for events on the proxy object in the function passed to `httpProxy.createServer`. Doing so would add a new listener on every request, which would end up being a disaster.
266 You have all the full flexibility of node-http-proxy offers in HTTPS as well as HTTP. The two basic scenarios are: with a stand-alone proxy server or in conjunction with another HTTPS server.
268 ### Proxying to HTTP from HTTPS
269 This is probably the most common use-case for proxying in conjunction with HTTPS. You have some front-facing HTTPS server, but all of your internal traffic is HTTP. In this way, you can reduce the number of servers to which your CA and other important security files are deployed and reduce the computational overhead from HTTPS traffic.
271 Using HTTPS in `node-http-proxy` is relatively straight-forward:
274 var fs = require('fs'),
275 http = require('http'),
276 https = require('https'),
277 httpProxy = require('http-proxy');
281 key: fs.readFileSync('path/to/your/key.pem', 'utf8'),
282 cert: fs.readFileSync('path/to/your/cert.pem', 'utf8')
287 // Create a standalone HTTPS proxy server
289 httpProxy.createServer(8000, 'localhost', options).listen(8001);
292 // Create an instance of HttpProxy to use with another HTTPS server
294 var proxy = new httpProxy.HttpProxy({
300 https.createServer(options.https, function (req, res) {
301 proxy.proxyRequest(req, res)
305 // Create the target HTTPS server for both cases
307 http.createServer(function (req, res) {
308 res.writeHead(200, { 'Content-Type': 'text/plain' });
309 res.write('hello https\n');
314 ### Using two certificates
316 Suppose that your reverse proxy will handle HTTPS traffic for two different domains `fobar.com` and `barbaz.com`.
317 If you need to use two different certificates you can take advantage of [Server Name Indication](http://en.wikipedia.org/wiki/Server_Name_Indication).
320 var https = require('https'),
321 path = require("path"),
323 crypto = require("crypto");
326 // generic function to load the credentials context from disk
328 function getCredentialsContext (cer) {
329 return crypto.createCredentials({
330 key: fs.readFileSync(path.join(__dirname, 'certs', cer + '.key')),
331 cert: fs.readFileSync(path.join(__dirname, 'certs', cer + '.crt'))
336 // A certificate per domain hash
339 "fobar.com": getCredentialsContext("foobar"),
340 "barbaz.com": getCredentialsContext("barbaz")
346 // This section assumes that myCert, myKey and myCa are defined (they are not
347 // in this example). With a SNICallback, the proxy needs a default set of
348 // certificates to use.
352 SNICallback: function (hostname) {
353 return certs[hostname];
361 'fobar.com': '127.0.0.1:8001',
362 'barbaz.com': '127.0.0.1:8002'
367 // Create a standalone HTTPS proxy server
369 httpProxy.createServer(options).listen(8001);
372 // Create the target HTTPS server
374 http.createServer(function (req, res) {
375 res.writeHead(200, { 'Content-Type': 'text/plain' });
376 res.write('hello https\n');
382 ### Proxying to HTTPS from HTTPS
383 Proxying from HTTPS to HTTPS is essentially the same as proxying from HTTPS to HTTP, but you must include the `target` option in when calling `httpProxy.createServer` or instantiating a new instance of `HttpProxy`.
386 var fs = require('fs'),
387 https = require('https'),
388 httpProxy = require('http-proxy');
392 key: fs.readFileSync('path/to/your/key.pem', 'utf8'),
393 cert: fs.readFileSync('path/to/your/cert.pem', 'utf8')
396 https: true // This could also be an Object with key and cert properties
401 // Create a standalone HTTPS proxy server
403 httpProxy.createServer(8000, 'localhost', options).listen(8001);
406 // Create an instance of HttpProxy to use with another HTTPS server
408 var proxy = new httpProxy.HttpProxy({
416 https.createServer(options.https, function (req, res) {
417 proxy.proxyRequest(req, res);
421 // Create the target HTTPS server for both cases
423 https.createServer(options.https, function (req, res) {
424 res.writeHead(200, { 'Content-Type': 'text/plain' });
425 res.write('hello https\n');
431 `node-http-proxy` now supports connect middleware. Add middleware functions to your createServer call:
434 httpProxy.createServer(
435 require('connect-gzip').gzip(),
440 A regular request we receive is to support the modification of html/xml content that is returned in the response from an upstream server.
442 [Harmon](https://github.com/No9/harmon/) is a stream based middleware plugin that is designed to solve that problem in the most effective way possible.
444 If you would like to handle errors passed to `next()` then attach a listener to the proxy:
446 server = httpProxy.createServer(
451 server.proxy.on('middlewareError', function (err, req, res) {
452 // handle the error here and call res.end()
455 ## Proxying WebSockets
456 Websockets are handled automatically when using `httpProxy.createServer()`, however, if you supply a callback inside the createServer call, you will need to handle the 'upgrade' proxy event yourself. Here's how:
464 var server = httpProxy.createServer(
469 server.listen(port, function () { ... });
470 server.on('upgrade', function (req, socket, head) {
471 server.proxy.proxyWebSocketRequest(req, socket, head);
475 If you would rather not use createServer call, and create the server that proxies yourself, see below:
478 var http = require('http'),
479 httpProxy = require('http-proxy');
482 // Create an instance of node-http-proxy
484 var proxy = new httpProxy.HttpProxy({
491 var server = http.createServer(function (req, res) {
493 // Proxy normal HTTP requests
495 proxy.proxyRequest(req, res);
498 server.on('upgrade', function (req, socket, head) {
500 // Proxy websocket requests too
502 proxy.proxyWebSocketRequest(req, socket, head);
508 ### with custom server logic
511 var httpProxy = require('http-proxy')
513 var server = httpProxy.createServer(function (req, res, proxy) {
515 // Put your custom server logic here
517 proxy.proxyRequest(req, res, {
523 server.on('upgrade', function (req, socket, head) {
525 // Put your custom server logic here
527 server.proxy.proxyWebSocketRequest(req, socket, head, {
536 ### Configuring your Socket limits
538 By default, `node-http-proxy` will set a 100 socket limit for all `host:port` proxy targets. You can change this in two ways:
540 1. By passing the `maxSockets` option to `httpProxy.createServer()`
541 2. By calling `httpProxy.setMaxSockets(n)`, where `n` is the number of sockets you with to use.
543 ## POST requests and buffering
545 express.bodyParser will interfere with proxying of POST requests (and other methods that have a request
546 body). With bodyParser active, proxied requests will never send anything to the upstream server, and
547 the original client will just hang. See https://github.com/nodejitsu/node-http-proxy/issues/180 for options.
549 ## Using node-http-proxy from the command line
550 When you install this package with npm, a node-http-proxy binary will become available to you. Using this binary is easy with some simple options:
553 usage: node-http-proxy [options]
555 All options should be set with the syntax --option=value
558 --port PORT Port that the proxy server should run on
559 --target HOST:PORT Location of the server the proxy will target
560 --config OUTFILE Location of the configuration file for the proxy server
561 --silent Silence the log output from the proxy server
562 -h, --help You're staring at it
566 ## Why doesn't node-http-proxy have more advanced features like x, y, or z?
568 If you have a suggestion for a feature currently not supported, feel free to open a [support issue][6]. node-http-proxy is designed to just proxy http requests from one server to another, but we will be soon releasing many other complimentary projects that can be used in conjunction with node-http-proxy.
574 `createServer()` supports the following options
578 forward: { // options for forward-proxy
582 target : { // options for proxy target
586 source : { // additional options for websocket proxying
592 xforward: true // enables X-Forwarded-For
594 changeOrigin: false, // changes the origin of the host header to the target URL
595 timeout: 120000 // override the default 2 minute http socket timeout value in milliseconds
600 The test suite is designed to fully cover the combinatoric possibilities of HTTP and HTTPS proxying:
608 vows test/*-test.js --spec
609 vows test/*-test.js --spec --https
610 vows test/*-test.js --spec --https --target=https
611 vows test/*-test.js --spec --target=https
619 Copyright (c) 2010 Charlie Robbins, Mikeal Rogers, Fedor Indutny, & Marak Squires
621 Permission is hereby granted, free of charge, to any person obtaining
622 a copy of this software and associated documentation files (the
623 "Software"), to deal in the Software without restriction, including
624 without limitation the rights to use, copy, modify, merge, publish,
625 distribute, sublicense, and/or sell copies of the Software, and to
626 permit persons to whom the Software is furnished to do so, subject to
627 the following conditions:
629 The above copyright notice and this permission notice shall be
630 included in all copies or substantial portions of the Software.
632 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
633 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
634 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
635 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
636 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
637 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
638 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
640 [0]: http://nodejitsu.com
641 [1]: https://github.com/nodejitsu/node-http-proxy/blob/master/examples/websocket/websocket-proxy.js
642 [2]: https://github.com/nodejitsu/node-http-proxy/blob/master/examples/http/proxy-https-to-http.js
643 [3]: https://github.com/nodejitsu/node-http-proxy/tree/master/examples
644 [4]: http://www.ietf.org/rfc/rfc2616.txt
645 [5]: http://socket.io
646 [6]: http://github.com/nodejitsu/node-http-proxy/issues