My express server has to proxy requests to another server listening on a unix socket file.
app.all('*', (req, res) => {
let opts = {
socketPath: 'file.sock',
path: req.url,
method: req.method,
headers: req.headers
};
const proxyReq = http.request(opts, (proxyRes) => {
proxyRes.pipe(res, {
end: true
});
});
req.pipe(proxyReq, { end: true });
});
The problem is that the response headers are not being passed on from the proxied server to the Express response. The client gets the Express server headers instead.
My questions:
How do I correctly pipe all of proxyRes into res?
Is there a way I can avoid having the proxied server response parsed and pipe the raw socket data back to the client? The same applies to the request. I'd like making the proxying as transparent as possible while keeping Express as the top level server.
Related
My Node.js server receives http soap requests. I would like to clone/duplicate each requests in order to send one to server A and the other to server B. How can I do that? Thanks
var proxy = httpProxy.createProxyServer({changeOrigin: true});
app.all('/', (req, res) =>{
// Duplicate or clone request
// ..... and send it to server B
// Forward original request to Server A
proxy.web(req, res, { target: url_serverA }, function(e) {})
});
I have a Nodejs Proxy server like this:
`var http = require('http'),
httpProxy = require('http-proxy');
var proxy = httpProxy.createProxyServer({});
proxy.on('proxyReq', function(proxyReq, req, res, options) {
proxyReq.setHeader('X-Special-Proxy-Header', 'foobar');
});
var server = http.createServer(function(req, res) {
console.log(req.body);
proxy.web(req, res, {
target: 'http://localhost:3000'
});
});
console.log("listening on port 9000")
server.listen(9000);`
What i want is get the req.body at the proxy server when i post a request to the Origin server, go through the proxy server.
I used "console.log(req.body);" at both proxy server and the origin server. I get the body object {"id": "user003"} at origin server, but undefined at the proxy server.
So how can i get the req.body at proxy server?
I suspect the problem here is that you don't have a body parser on your proxy server, but do have one on your origin.
req.body itself isn't set by node. Instead, you have to handle events emitted by the req stream:
let body = '';
req.on('data', (data) => {
// data is a buffer so need toString()
body += data.toString();
});
req.on('end', () => {
// at this point you'll have the full body
console.log(body);
});
You can make this easier with a body parser (e.g https://www.npmjs.com/package/body-parser) but since you're running a proxy server, you probably don't want to parse the entire req stream before forwarding onto your origin. So I'd maybe stick with handling the events.
Can anyone please explain what the router in options does in this code. I got this code from a blog. I am trying to implement node http-proxy.
var http = require('http'),
httpProxy = require('http-proxy');
//
//Leave out the hostnameOnly field this time, or set it to false...
//
var options = {
router: {
'domainone.com/appone': '127.0.0.1:9000',
'domainone.com/apptwo': '127.0.0.1:9001',
'domaintwo.net/differentapp': '127.0.0.1:9002'
}
}
//
//...and then pass in your options like last time.
//
var proxyServer = httpProxy.createServer(options).listen(80);
//
// ...and a simple http server to show us our request back.
//
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);
The proxy library will take all incoming requests and attempt to match it with a rule in your router table. Assuming it finds a match, it will forward that request to the IP address associated with the DNS name you provided.
For example, requests going to domainone.com/appone will be forwarded to 127.0.0.1:9000
One problem that I see here is that you are listening on port 9000, and your first rule re-routes to 127.0.0.1:9000.
I am working on a project that has a mobile appplication, and two web servers(let it be named tub and cloud). THe web servers are developed in node.js environment.
The mobile app will request for some information from the web server named 'tub' ;
this 'tub' will in turn act as a http client and request some information from the web server named 'cloud'.
When the 'tub' requests the 'cloud', the 'cloud' has to process the incoming request and then has to do header redirection to another url(possibly in the 'cloud' or some other server) and return the response back to the 'tub'.
I am facing certain difficulty in figuring out header redirection in the 'cloud' server. Below I have mentioned the coding for putting a rest api call from 'tub' to 'cloud' :
var options =
{
hostname: '10.0.0.1',
port: 1048,
path: '/api/v1/vendor?DevType=mobile,
method: 'GET',
headers:
{
'Content-Type': 'application/x-www-form-urlencoded'
}
};
var request = http.request(options, function(cloudres)
{
cloudres.setEncoding('utf8');
cloudres.on('data', function (chunk)
{
console.log("chunk");
console.log(chunk);
});
});
request.on('error', function(e)
{
console.log('Cloud Package http Request Error : ' + e.message);
});
request.end();
Below mentioned code is in the 'cloud' server for header redirection :
var express = require('express');
var http = require('http');
var app = express(); // Create an Express instance.
var httpserver = http.createServer(app); // Create a http server and hook the Express instance to it.
httpserver.listen(1048,function() // Make the http server listen to a port.
{
console.log("Http Server Listening On Port : 1048");
});
app.get('/api/v1/vendor',function(req,res)
{
res.statusCode = 302;
res.setHeader('Content-Disposition', 'attachment');
res.setHeader('Location', 'http://10.0.0.1:80/mobilelib.zip');
res.end();
});
I am not getting neither any response nor any error in the 'tub' . Am I going wrong anywhere ? How can we track whether header redirection is taking place or not.
Express can handle the redirection response automatically, using res.redirect('/foo/bar');
app.get('/api/v1/vendor',function(req,res)
{
res.redirect('http://10.0.0.1:80/mobilelib.zip');
});
It's inadvisable to set both the Location and Content-Disposition headers together: Content-Disposition with 302 redirect
I'm expanding on a node.js reverse proxy I put together with mikeal's request module: https://github.com/mikeal/request . It is a connect app that uses a small piece of custom middleware to check if the the current request is for an API route and if so it proxies it to and from a different API server like this:
.use(function(req, res, next){
if( /^\/api\//.test(req.url) ){
req.pipe(request(apiUrl + req.url))
.on('error', function(err){
handlePipeError(err, 'Error piping request to proxy server. Details: ');
})
.pipe(res)
.on('error', function(err){
handlePipeError(err, 'Error piping proxy response to client. Details: ')
});
function handlePipeError(err, customMsg) {
console.log( customMsg, err );
res.writeHead(503, {
'Content-Length': Buffer.byteLength(err.message, 'utf8'),
'Content-Type': 'text/plain' });
res.end(err.message);
}
}
else {
next();
}
There is also some other middleware to handle static file serving and some other stuff. Once all the middleware is setup I start the server like this:
var server = require('http').createServer(app);
server.listen(port)
I would now like to expand this script to allow reverse proxying websocket connections. I tried using the nodejitsu/node-http-proxy to do modify the previous portion of the code like so:
var options = {
ws: true,
target: apiUrl,
secure: false,
xfwd: true
};
var wsProxy = require('http-proxy').createProxyServer(options);
var server = require('http').createServer(app);
server.on('upgrade', function (req, socket, head) {
console.log("--- CAUGHT UPGRADE ----");
wsProxy.ws(req, socket, head);
});
server.listen(port);
I notice the upgrade event fires off and the callback function does run but the websockets request isn't actually working (the client seems to never establish a connection). Is there a better way to achieve this