node.jsnode.js-connectnode-http-proxy

How to retrieve POST request body before proxying it


Using connect library on Node, I tried to retrieve request body before proxying it with node-http-proxy.

Since Node v4, we have to use some middleware like bodyParser (or just data/end events on request) to retrieve POST request body.

Problem is, it seems to consume the request stream, and the request timeout when being proxied.

Here is the code, first I retrieve the body with data event, then I give it to http-proxy, but the request timeouts.

var httpProxy = require('http-proxy');
var connect = require('connect');

var proxy = new httpProxy.createProxyServer({
  target: {
    host: 'localhost',
    port: 9015
  }
});

var app = connect()
  .use(function (req, res, next) {
    var bodyBuffer = '';

    req.on('data', function (data) {
      bodyBuffer += data;
    });

    req.on('end', function () {
      req.body = buffer;

      next();
    });
  })
  .use(function (req, res) {

    //I can use req.body now
    //But the proxy request timeouts
    proxy.web(req, res);
  });

http.createServer(app).listen(3000);

Solution

  • As the stream is read to retrieve request body, it can not be sent a second time when proxying the request.

    To do so, there is an option on http-proxy web() method to send an already buffered request.

    On the first middleware, construct a PassThrough stream with a buffer containing the body you retrieve. Store it on the request for example (there might be better ways to store it), for later use.

    var stream = require('stream');
    
    req.on('end', function() {
      req.body = buffer;
    
      var bufferStream = new stream.PassThrough();
      bufferStream.end(new Buffer(buffer));
      req.bodyStream = bufferStream;
    
      next();
    });
    

    Then add it on the third parameter of proxy.web() call, on the buffer property.

    proxy.web(req, res, {buffer: req.bodyStream});