I'm trying to use the node-http-proxy as a reverse proxy, but I can't seem to get POST and PUT requests to work. The file server1.js is the reverse proxy (at least for requests with the url "/forward-this") and server2.js is the server that receives the proxied requests. Please explain what I'm doing incorrectly.
Here's the code for server1.js:
// File: server1.js
//
var http = require('http');
var httpProxy = require('http-proxy');
httpProxy.createServer(function (req, res, proxy) {
if (req.method == 'POST' || req.method == 'PUT') {
req.body = '';
req.addListener('data', function(chunk) {
req.body += chunk;
});
req.addListener('end', function() {
processRequest(req, res, proxy);
});
} else {
processRequest(req, res, proxy);
}
}).listen(8080);
function processRequest(req, res, proxy) {
if (req.url == '/forward-this') {
console.log(req.method + ": " + req.url + "=> I'm going to forward this.");
proxy.proxyRequest(req, res, {
host: 'localhost',
port: 8855
});
} else {
console.log(req.method + ": " + req.url + "=> I'm handling this.");
res.writeHead(200, { "Content-Type": "text/plain" });
res.write("Server #1 responding to " + req.method + ": " + req.url + "\n");
res.end();
}
}
And here's the code for server2.js:
// File: server2.js
//
var http = require('http');
http.createServer(function (req, res, proxy) {
if (req.method == 'POST' || req.method == 'PUT') {
req.body = '';
req.addListener('data', function(chunk) {
req.body += chunk;
});
req.addListener('end', function() {
processRequest(req, res);
});
} else {
processRequest(req, res);
}
}).listen(8855);
function processRequest(req, res) {
console.log(req.method + ": " + req.url + "=> I'm handling this.");
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.write("Server #2 responding to " + req.method + ': url=' + req.url + '\n');
res.end();
}
A reverse proxy is a server that sits in front of web servers and forwards client (e.g. web browser) requests to those web servers. Reverse proxies are typically implemented to help increase security, performance, and reliability.
NGINX Plus and NGINX are the best-in-class reverse proxy and load balancing solutions used by high-traffic websites such as Dropbox, Netflix, and Zynga.
What is a reverse proxy? As its name implies, a reverse proxy does the exact opposite of what a forward proxy does. While a forward proxy proxies on behalf of clients (or requesting hosts), a reverse proxy proxies on behalf of servers.
http-proxy depends on the data
and end
events for POST / PUT requests. The latency between the time that server1 receives the request and when it is proxied means that http-proxy misses those events entirely. You have two options here to get this to work correctly - you can buffer the request or you can use a routing proxy instead. The routing proxy seems the most appropriate here since you only need to proxy a subset of requests. Here's the revised server1.js:
// File: server1.js
//
var http = require('http');
var httpProxy = require('http-proxy');
var proxy = new httpProxy.RoutingProxy();
http.createServer(function (req, res) {
if (req.url == '/forward-this') {
return proxy.proxyRequest(req, res, {
host: 'localhost',
port: 8855
});
}
if (req.method == 'POST' || req.method == 'PUT') {
req.body = '';
req.addListener('data', function(chunk) {
req.body += chunk;
});
req.addListener('end', function() {
processRequest(req, res);
});
} else {
processRequest(req, res);
}
}).listen(8080);
function processRequest(req, res) {
console.log(req.method + ": " + req.url + "=> I'm handling this.");
res.writeHead(200, { "Content-Type": "text/plain" });
res.write("Server #1 responding to " + req.method + ": " + req.url + "\n");
res.end();
}
In addition to @squamos
How to write a node express app that serves most local files, but reroutes some to another domain?
var proxy = new httpProxy.RoutingProxy();
"Above code is working for http-proxy ~0.10.x. Since then lot of things had changed in library. Below you can find example for new version (at time of writing ~1.0.2)"
var proxy = httpProxy.createProxyServer({});
Here is my solution for proxying POST requests. This isn't the most ideal solution, but it works and is easy to understand.
var request = require('request');
var http = require('http'),
httpProxy = require('http-proxy'),
proxy = httpProxy.createProxyServer({});
http.createServer(function(req, res) {
if (req.method == 'POST') {
request.post('http://localhost:10500/MyPostRoute',
{form: {}},
function(err, response, body) {
if (! err && res.statusCode == 200) {
// Notice I use "res" not "response" for returning response
res.writeHead(200, {'Content-Type': "application/json"});
res.end(body);
}
else {
res.writeHead(404, {'Content-Type': "application/json"});
res.end(JSON.stringify({'Error': err}));
}
});
}
else if (req.method == 'GET') {
proxy.web(req, res, { target: 'http://localhost/9000' }, function(err) {
console.log(err)
});
}
The ports 10500
and 9000
are arbitrary and in my code I dynamically assign them based on the services I host. This doesn't deal with PUT and it might be less efficient because I am creating another response instead of manipulating the current one.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With