How to reverse proxy client POST & PUT requests using node-http-proxy
Solution 1
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();
}
Solution 2
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({});
Solution 3
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.
Jason Roberts
Updated on June 21, 2022Comments
-
Jason Roberts almost 2 years
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(); }