node-http-proxy icon indicating copy to clipboard operation
node-http-proxy copied to clipboard

read POST data from client request

Open fsallstrom opened this issue 5 years ago • 11 comments
trafficstars

Hi, I have created a proxy server between my client device and server that I use to re-format the server response before it hits the client device. I have used the http-proxy successfully.

Now, I would like to add some logging to the proxy server so that I can see what POST data is sent from the client and has tried this:

proxy.on('proxyReq', function(proxyReq, req, res, options) {
	console.log('incoming client request');
	console.log(req);
}); 

as well as this:

proxy.on('proxyReq', function(proxyReq, req, res, options) {
	console.log('incoming client request');
	console.log(options);
});

without success. Perhaps I have completely misunderstood the concept. Where can I get access to the POST data from the client request? Thank you in advance!

fsallstrom avatar Jun 30 '20 15:06 fsallstrom

req.body may be what you are looking for.

Sebaci avatar Jul 03 '20 12:07 Sebaci

req.body may be what you are looking for.

Thanks, I tried this:

proxy.on('proxyReq', function(proxyReq, req, res, options) {
	console.log(req.body);
});

and get "undefined" in the console

fsallstrom avatar Jul 04 '20 11:07 fsallstrom

You need to use a body parsing middleware to populate req.body. It isn't a standard property.

Assuming you're using Express, see: http://expressjs.com/en/resources/middleware/body-parser.html

jsmylnycky avatar Jul 04 '20 16:07 jsmylnycky

You need to use a body parsing middleware to populate req.body. It isn't a standard property.

Assuming you're using Express, see: http://expressjs.com/en/resources/middleware/body-parser.html

Thank you for responding. I am not at all familiar with express and what it does. I'm pretty new to node in general and have used http-proxy to create a simple web proxy for doing some modifications of the target server's response. My entire code here:

var httpProxy = require('http-proxy');
const port = process.env.PORT;

var proxy = httpProxy.createServer({
 
  target: 'https://<my_target_hostname>',
  secure: false,
  followRedirects: true,
  autoRewrite: true,
  changeOrigin: true,
  selfHandleResponse: true
}).listen(port, () => {
  console.log(`Server running at port ${port}`)
 });
 
proxy.on('proxyReq', function(proxyReq, req, res, options) {
	console.log('incoming request: ', req.body); //this doesn't work: console output is undefined
});
 
proxy.on('proxyRes', function (proxyRes, req, res) {
        var body = '';
	var response = '';
	proxyRes.on('data', function (chunk) {
            body += chunk;
        });
        proxyRes.on('end', function () {
		response = JSON.parse(body);
		console.log(response);
		res.end(JSON.stringify({SessionID : response}));
        });
});  

Basically there are two things I want to add to my proxy-server; first I want to be able to log the request.body (at least parts of it) and second, I would like to change the reponseCode in the server response before I send it back to the client. The target server always sends back responseCode 200 even though the request could not be served properly.

fsallstrom avatar Jul 05 '20 13:07 fsallstrom

setting the response responseCode was pretty easy, using writeHead

res.writeHead(401);
res.end(...)

fsallstrom avatar Jul 05 '20 14:07 fsallstrom

You still need to use a library capable of parsing the body of a request. Look into using that module on its own if you're not using Express, otherwise there are probably numerous other options out there that do similar things.

jsmylnycky avatar Jul 05 '20 14:07 jsmylnycky

Thank you. I think it's a bit over my head. I solved it by having the client send the data I needed to monitor in a customer header, and used proxyReq.getHeader() to fetch it.

fsallstrom avatar Jul 05 '20 19:07 fsallstrom

@fsallstrom You can also take inspiration from this example:

https://github.com/http-party/node-http-proxy/blob/master/examples/middleware/bodyDecoder-middleware.js

Sebaci avatar Jul 06 '20 14:07 Sebaci

Hey, I had a similar issue today. Using your code above for reference:

console.log(response);

Did this return anything? For me it does; I can see all the expected data from the POST.

The problem I was having was that the data would never get sent back to the original client. Using your code above again as an example: res.end(JSON.stringify({SessionID : response})); this would not return and there wouldn't be any error.

What I tried was calling res.write with some non-empty value just before the response, and this works:

res.write('x');
res.write()res.end(JSON.stringify({SessionID : response}));

Unfortunately, the response that the client gets has a character that needs to be stripped.

Is this by design or is this a bug? Thanks!

gh-amistry avatar Mar 20 '21 01:03 gh-amistry

I had the same problem.

I am using express and body-parser to JSON.

I fixed adding this restream parsed body before proxying:

//restream parsed body before proxying
proxy.on('proxyReq', function(proxyReq, req, res, options) {
  if (!req.body || !Object.keys(req.body).length) {
    return;
  }

  var contentType = proxyReq.getHeader('Content-Type');
  var bodyData;

  if (contentType === 'application/json') {
    bodyData = JSON.stringify(req.body);
  }

  if (contentType === 'application/x-www-form-urlencoded') {
    bodyData = queryString.stringify(req.body);
  }

  if (bodyData) {
    proxyReq.setHeader('Content-Length', Buffer.byteLength(bodyData));
    proxyReq.write(bodyData);
  }
});

jeanffc avatar Apr 16 '21 15:04 jeanffc

what if header include form-data and want to parse file before proxy request ?

alijch89 avatar Dec 24 '21 09:12 alijch89