Security News
The Unpaid Backbone of Open Source: Solo Maintainers Face Increasing Security Demands
Solo open source maintainers face burnout and security challenges, with 60% unpaid and 60% considering quitting.
http-proxy
Advanced tools
The http-proxy npm package is a full-featured HTTP proxy library for Node.js. It supports websockets and can be used to proxy different kinds of HTTP and HTTPS traffic, which makes it suitable for implementing reverse proxies and load balancers.
Proxying HTTP/HTTPS requests
This code creates an HTTP server that listens on port 8000 and proxies all incoming requests to 'http://mytarget.com:8080'.
const http = require('http');
const httpProxy = require('http-proxy');
const proxy = httpProxy.createProxyServer({});
const server = http.createServer(function(req, res) {
proxy.web(req, res, { target: 'http://mytarget.com:8080' });
});
server.listen(8000);
Proxying WebSockets
This code sets up a server that can proxy WebSocket connections to 'ws://mytarget.com:8080' when an 'upgrade' event is emitted.
const http = require('http');
const httpProxy = require('http-proxy');
const proxy = httpProxy.createProxyServer({});
const server = http.createServer(function(req, res) {
// This function is not used when proxying WebSockets
});
server.on('upgrade', function(req, socket, head) {
proxy.ws(req, socket, head, { target: 'ws://mytarget.com:8080' });
});
server.listen(8000);
Listening for proxy events
This code listens for errors and responses from the proxy server, allowing for custom error handling and logging.
const httpProxy = require('http-proxy');
const proxy = httpProxy.createProxyServer({});
proxy.on('error', function(err, req, res) {
res.writeHead(500, {
'Content-Type': 'text/plain'
});
res.end('Something went wrong.');
});
proxy.on('proxyRes', function(proxyRes, req, res) {
console.log('RAW Response from the target', JSON.stringify(proxyRes.headers, true, 2));
});
node-http-proxy is a similar package that offers high-performance reverse proxy and load balancing capabilities. It is often compared to http-proxy due to its similar feature set.
Redbird is a modern reverse proxy library for node that includes automatic HTTPS, WebSocket support, and Docker integration. It is an alternative to http-proxy with a focus on simplicity and ease of use.
Bouncy is a simple module for writing WebSocket and regular HTTP servers. It allows you to route requests to different destinations based on the request headers or other properties. It is less feature-rich compared to http-proxy but can be used for simpler proxying needs.
node-http-proxy is <= 0.8.x
compatible, if you're looking for a >= 0.10
compatible version please check caronte
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.
curl https://npmjs.org/install.sh | sh
npm install http-proxy
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:
In each of these scenarios node-http-proxy can handle any of these types of requests:
See the examples for more working sample code.
var http = require('http'),
httpProxy = require('http-proxy');
//
// Create your proxy server
//
httpProxy.createServer(9000, 'localhost').listen(8000);
//
// Create your target server
//
http.createServer(function (req, res) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.write('request successfully proxied!' + '\n' + JSON.stringify(req.headers, true, 2));
res.end();
}).listen(9000);
var http = require('http'),
httpProxy = require('http-proxy');
//
// Create a proxy server with custom application logic
//
httpProxy.createServer(function (req, res, proxy) {
//
// Put your custom server logic here
//
proxy.proxyRequest(req, res, {
host: 'localhost',
port: 9000
});
}).listen(8000);
http.createServer(function (req, res) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.write('request successfully proxied: ' + req.url +'\n' + JSON.stringify(req.headers, true, 2));
res.end();
}).listen(9000);
var http = require('http'),
httpProxy = require('http-proxy');
//
// Create a proxy server with custom application logic
//
httpProxy.createServer(function (req, res, proxy) {
//
// Buffer the request so that `data` and `end` events
// are not lost during async operation(s).
//
var buffer = httpProxy.buffer(req);
//
// Wait for two seconds then respond: this simulates
// performing async actions before proxying a request
//
setTimeout(function () {
proxy.proxyRequest(req, res, {
host: 'localhost',
port: 9000,
buffer: buffer
});
}, 2000);
}).listen(8000);
http.createServer(function (req, res) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.write('request successfully proxied: ' + req.url +'\n' + JSON.stringify(req.headers, true, 2));
res.end();
}).listen(9000);
var http = require('http'),
httpProxy = require('http-proxy');
//
// Create a new instance of HttProxy to use in your server
//
var proxy = new httpProxy.RoutingProxy();
//
// Create a regular http server and proxy its handler
//
http.createServer(function (req, res) {
//
// Put your custom server logic here, then proxy
//
proxy.proxyRequest(req, res, {
host: 'localhost',
port: 9000
});
}).listen(8001);
http.createServer(function (req, res) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.write('request successfully proxied: ' + req.url +'\n' + JSON.stringify(req.headers, true, 2));
res.end();
}).listen(9000);
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:
var options = {
router: {
'foo.com/baz': '127.0.0.1:8001',
'foo.com/buz': '127.0.0.1:8002',
'bar.com/buz': '127.0.0.1:8003'
}
};
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:
var proxyServer = httpProxy.createServer(options);
proxyServer.listen(80);
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:
var options = {
hostnameOnly: true,
router: {
'foo.com': '127.0.0.1:8001',
'bar.com': '127.0.0.1:8002'
}
}
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".
If you dont care about forwarding to different hosts, you can redirect based on the request path.
var options = {
pathnameOnly: true,
router: {
'/wiki': '127.0.0.1:8001',
'/blog': '127.0.0.1:8002',
'/api': '127.0.0.1:8003'
}
}
This comes in handy if you are running separate services or applications on separate paths. Note, using this option disables routing by hostname entirely.
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:
var proxyServerWithForwarding = httpProxy.createServer(9000, 'localhost', {
forward: {
port: 9000,
host: 'staging.com'
}
});
proxyServerWithForwarding.listen(80);
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'.
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.
var httpProxy = require('http-proxy');
var server = httpProxy.createServer(function (req, res, proxy) {
var buffer = httpProxy.buffer(req);
proxy.proxyRequest(req, res, {
host: '127.0.0.1',
port: 9000,
buffer: buffer
});
});
server.proxy.on('end', function () {
console.log("The request was proxied.");
});
server.listen(8000);
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.
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.
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.
Using HTTPS in node-http-proxy
is relatively straight-forward:
var fs = require('fs'),
http = require('http'),
https = require('https'),
httpProxy = require('http-proxy');
var options = {
https: {
key: fs.readFileSync('path/to/your/key.pem', 'utf8'),
cert: fs.readFileSync('path/to/your/cert.pem', 'utf8')
}
};
//
// Create a standalone HTTPS proxy server
//
httpProxy.createServer(8000, 'localhost', options).listen(8001);
//
// Create an instance of HttpProxy to use with another HTTPS server
//
var proxy = new httpProxy.HttpProxy({
target: {
host: 'localhost',
port: 8000
}
});
https.createServer(options.https, function (req, res) {
proxy.proxyRequest(req, res)
}).listen(8002);
//
// Create the target HTTPS server for both cases
//
http.createServer(function (req, res) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.write('hello https\n');
res.end();
}).listen(8000);
Suppose that your reverse proxy will handle HTTPS traffic for two different domains fobar.com
and barbaz.com
.
If you need to use two different certificates you can take advantage of Server Name Indication.
var https = require('https'),
path = require("path"),
fs = require("fs"),
crypto = require("crypto");
//
// generic function to load the credentials context from disk
//
function getCredentialsContext (cer) {
return crypto.createCredentials({
key: fs.readFileSync(path.join(__dirname, 'certs', cer + '.key')),
cert: fs.readFileSync(path.join(__dirname, 'certs', cer + '.crt'))
}).context;
}
//
// A certificate per domain hash
//
var certs = {
"fobar.com": getCredentialsContext("foobar"),
"barbaz.com": getCredentialsContext("barbaz")
};
//
// Proxy options
//
// This section assumes that myCert, myKey and myCa are defined (they are not
// in this example). With a SNICallback, the proxy needs a default set of
// certificates to use.
//
var options = {
https: {
SNICallback: function (hostname) {
return certs[hostname];
},
cert: myCert,
key: myKey,
ca: [myCa]
},
hostnameOnly: true,
router: {
'fobar.com': '127.0.0.1:8001',
'barbaz.com': '127.0.0.1:8002'
}
};
//
// Create a standalone HTTPS proxy server
//
httpProxy.createServer(options).listen(8001);
//
// Create the target HTTPS server
//
http.createServer(function (req, res) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.write('hello https\n');
res.end();
}).listen(8000);
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
.
var fs = require('fs'),
https = require('https'),
httpProxy = require('http-proxy');
var options = {
https: {
key: fs.readFileSync('path/to/your/key.pem', 'utf8'),
cert: fs.readFileSync('path/to/your/cert.pem', 'utf8')
},
target: {
https: true // This could also be an Object with key and cert properties
}
};
//
// Create a standalone HTTPS proxy server
//
httpProxy.createServer(8000, 'localhost', options).listen(8001);
//
// Create an instance of HttpProxy to use with another HTTPS server
//
var proxy = new httpProxy.HttpProxy({
target: {
host: 'localhost',
port: 8000,
https: true
}
});
https.createServer(options.https, function (req, res) {
proxy.proxyRequest(req, res);
}).listen(8002);
//
// Create the target HTTPS server for both cases
//
https.createServer(options.https, function (req, res) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.write('hello https\n');
res.end();
}).listen(8000);
node-http-proxy
now supports connect middleware. Add middleware functions to your createServer call:
httpProxy.createServer(
require('connect-gzip').gzip(),
9000, 'localhost'
).listen(8000);
A regular request we receive is to support the modification of html/xml content that is returned in the response from an upstream server.
Harmon is a stream based middleware plugin that is designed to solve that problem in the most effective way possible.
If you would like to handle errors passed to next()
then attach a listener to the proxy:
server = httpProxy.createServer(
myMiddleWare,
9000, 'localhost'
).listen(8000);
server.proxy.on('middlewareError', function (err, req, res) {
// handle the error here and call res.end()
});
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:
var options = {
....
};
var server = httpProxy.createServer(
callback/middleware,
options
);
server.listen(port, function () { ... });
server.on('upgrade', function (req, socket, head) {
server.proxy.proxyWebSocketRequest(req, socket, head);
});
If you would rather not use createServer call, and create the server that proxies yourself, see below:
var http = require('http'),
httpProxy = require('http-proxy');
//
// Create an instance of node-http-proxy
//
var proxy = new httpProxy.HttpProxy({
target: {
host: 'localhost',
port: 8000
}
});
var server = http.createServer(function (req, res) {
//
// Proxy normal HTTP requests
//
proxy.proxyRequest(req, res);
});
server.on('upgrade', function (req, socket, head) {
//
// Proxy websocket requests too
//
proxy.proxyWebSocketRequest(req, socket, head);
});
server.listen(8080);
var httpProxy = require('http-proxy')
var server = httpProxy.createServer(function (req, res, proxy) {
//
// Put your custom server logic here
//
proxy.proxyRequest(req, res, {
host: 'localhost',
port: 9000
});
})
server.on('upgrade', function (req, socket, head) {
//
// Put your custom server logic here
//
server.proxy.proxyWebSocketRequest(req, socket, head, {
host: 'localhost',
port: 9000
});
});
server.listen(8080);
By default, node-http-proxy
will set a 100 socket limit for all host:port
proxy targets. You can change this in two ways:
maxSockets
option to httpProxy.createServer()
httpProxy.setMaxSockets(n)
, where n
is the number of sockets you with to use.express.bodyParser will interfere with proxying of POST requests (and other methods that have a request body). With bodyParser active, proxied requests will never send anything to the upstream server, and the original client will just hang. See https://github.com/nodejitsu/node-http-proxy/issues/180 for options.
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:
usage: node-http-proxy [options]
All options should be set with the syntax --option=value
options:
--port PORT Port that the proxy server should run on
--target HOST:PORT Location of the server the proxy will target
--config OUTFILE Location of the configuration file for the proxy server
--silent Silence the log output from the proxy server
-h, --help You're staring at it
If you have a suggestion for a feature currently not supported, feel free to open a support issue. 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.
createServer()
supports the following options
{
forward: { // options for forward-proxy
port: 8000,
host: 'staging.com'
},
target : { // options for proxy target
port : 8000,
host : 'localhost',
};
source : { // additional options for websocket proxying
host : 'localhost',
port : 8000,
https: true
},
enable : {
xforward: true // enables X-Forwarded-For
},
changeOrigin: false, // changes the origin of the host header to the target URL
timeout: 120000 // override the default 2 minute http socket timeout value in milliseconds
}
The test suite is designed to fully cover the combinatoric possibilities of HTTP and HTTPS proxying:
vows test/*-test.js --spec
vows test/*-test.js --spec --https
vows test/*-test.js --spec --https --target=https
vows test/*-test.js --spec --target=https
(The MIT License)
Copyright (c) 2010 Charlie Robbins, Mikeal Rogers, Fedor Indutny, & Marak Squires
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
v0.10.4 - 2013-12-27
#521
#520
#416
#518
#502
#492
#484
#482
#476
#475
#472
#14
#11
#3
#341
#529
#341
#511
#510
#483
#478
#459
#473
#474
#469
#467
#8
17399e7
a255f98
335af81
ed8c9ee
7e25bde
bc236d7
dc9d7e5
d166354
8b3fe32
bb0d28c
c82ff2c
4d13156
b726116
d05af4a
5bb83b9
bdeabb7
07551c6
2a59366
f7f5fa7
7e44d36
0393b5d
e02317c
33a2462
886a870
d7064f2
588327c
e45bfd6
5dcdf2b
0bfb9be
831a44b
a74cd85
7c72f3b
881c7e6
8273cb6
0aeaba7
16a4d9d
d4f0da8
c75d06c
c65ffbb
356f43d
e592c53
b79bd29
f566a42
2142c50
601dbcb
1cb967b
79a14ac
dad211e
8085178
c7924e0
427d8d8
c961279
79f7f99
7599cee
31d919b
9ab8749
27df8d7
10c0f11
cedc5c4
ae0faef
10a0db4
bbe3bfd
a1b25a1
c4ddc4e
07091b5
d40e4be
8fc3389
a704213
2fac7b9
4f24664
07cfa6b
1d1ee88
3a39e44
ec981c5
04c1011
cde08fb
16eacfa
02007ed
babdf53
1a7bef0
90fb01d
7a3f6df
db12f6c
32a4088
de3ff11
b85aa16
common.setupOutgoing
12cda56
e0faaaf
4a4607d
004a46c
584ce76
13741a8
2c10f25
d0862af
8c8c455
cfd417d
x-forwarded-for-port
. 2d42709
edd8e2f
dcb873a
c02b721
9b3e1eb
5e130de
a51b062
39b0c46
6a6dfbb
1b867a7
ca09263
52ecd52
a467b7b
2bf20d6
3d8e538
6a4294c
cc09ae6
02df9a3
e08d4ed
455f97e
25bb3bf
8332e74
d85ccdd
0602500
7e8041d
8931009
781c038
03880d8
ws
and web
functions to use the global options object as a base 268afe3
c9cd6d2
f97c0c6
a9f9e21
f36cb4d
ef946a7
8eb6780
1204a35
1b5fb1d
7d840d3
57abb7f
a350fad
aaff196
6b61878
8663ac1
a81dd8d
4d3a4e1
26c4c43
ee3cc38
7d71a86
9243444
a6256ca
920f1e7
bc12ca3
7ad5c0f
8b05626
34f16e7
e3f8d5f
5823842
6e77cd3
bbe2b27
031aa0f
abf1d90
c4d56a5
162a42f
b333e63
bd106d6
f1aeb05
1333c0c
86750c7
1c7ace2
38e6d7c
6a03e5f
8eff1a1
0fb3381
98f29bd
bd3df45
ebbba73
1993faf
5a1504f
3c91ed3
1457980
4480699
d7078e2
dd0f7b8
0637322
adc5be0
da9de70
275a519
4090250
7c8ecc8
72a89ea
69f126b
8269eca
18341d5
npm test
while we fix coveralss.io integration e2a5d51
2e7343d
5d66ce1
d60353f
d83fdf6
590bb60
a2b1f0a
961d2f9
840f6d8
4d65280
dda6f7a
1ceea3e
c9f5772
4c2f2f3
FAQs
HTTP proxying for the masses
The npm package http-proxy receives a total of 14,116,641 weekly downloads. As such, http-proxy popularity was classified as popular.
We found that http-proxy demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 4 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Solo open source maintainers face burnout and security challenges, with 60% unpaid and 60% considering quitting.
Security News
License exceptions modify the terms of open source licenses, impacting how software can be used, modified, and distributed. Developers should be aware of the legal implications of these exceptions.
Security News
A developer is accusing Tencent of violating the GPL by modifying a Python utility and changing its license to BSD, highlighting the importance of copyleft compliance.