http-proxy-middleware: POST request body is not proxied to the servers

I have in my backend defined:

var proxy = proxyMiddleware('/api', {
        target: 'http://somehost.zero',
        proxyTable: {
            '/api/one': 'http://somehost.one',
            '/api/two': 'http://somehost.two',
        }
    });
app.use(proxy);

and when I’m proxing POST request (lets say to the ‘/api/one’: ‘http://somehost.one’ ) I don’t know why but server http://somehost.one get request without body.

Did you had similar problem?

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Reactions: 1
  • Comments: 31 (4 by maintainers)

Commits related to this issue

Most upvoted comments

Did a little test and I am able to receive POST data at the target server.

I noticed you are using the body-parser middleware: https://github.com/dejewi/proxy-bug/blob/master/app.js#L16

You might want to change to order of the middlwares you are using. Try moving the http-proxy-middleware above the body-parser

source: http://stackoverflow.com/a/25651651/3841188

Hope this solves the issue.

If you can’t change the order of the middleware; You can restream the parsed body before proxying the request. This should fix the POST request:

// restream parsed body before proxying
var restream = function(proxyReq, req, res, options) {
    if (req.body) {
        let bodyData = JSON.stringify(req.body);
        // incase if content-type is application/x-www-form-urlencoded -> we need to change to application/json
        proxyReq.setHeader('Content-Type','application/json');
        proxyReq.setHeader('Content-Length', Buffer.byteLength(bodyData));
        // stream the content
        proxyReq.write(bodyData);
    }
}

var apiProxy = proxyMiddleware('/api', {
    target: 'https://xxx.xxx.xxx.xxx',
    onProxyReq: restream
});


var app = express();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(apiProxy);                // with restreaming

source: node-http-proxy/examples/middleware/bodyDecoder-middleware.js. (https://github.com/nodejitsu/node-http-proxy/pull/1027)

Is there any way for http-proxy-middleware to do a check for stuff like this in the future? I just spend 2 days ripping out my hair because I had absolutely zero debug info to go on? Just a proxy that did nothing until it timed out…

Apologies for resurrecting this, but anybody aware of another way to avoid this issue when you can’t change the order of middleware (e.g. if you’re adding proxies at runtime)?

Here https://github.com/chimurai/http-proxy-middleware/issues/40#issuecomment-420259997

I just spend 2 days ripping out my hair

And here https://github.com/chimurai/http-proxy-middleware/issues/177#issuecomment-364054609

I just spent three days trying to figure out why my proxy was hanging, until I stumbled upon this issue.

And here https://github.com/chimurai/http-proxy-middleware/issues/150#issuecomment-284083246

OMFG I have been trying to make this work for 2 days and that totally did it

And I just lost a few hours as well.

Just underscoring that if you see your GET requests being proxied just fine, but your POST requests seem to hang and not being proxied, this issue is providing solutions.

Using @chimurai’s method above to restream code, I’m hitting an error saying that I cannot set the headers because they have been sent to client already. Any idea why?

_http_outgoing.js:503 throw new errors.Error('ERR_HTTP_HEADERS_SENT', 'set'); ^ Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client at validateHeader (_http_outgoing.js:503:11) at ClientRequest.setHeader (_http_outgoing.js:510:3) at ProxyServer.restream (/usr/src/app/node/routes.js:103:20) at ProxyServer.emit (/usr/src/app/node_modules/eventemitter3/index.js:184:35) at ClientRequest. (/usr/src/app/node_modules/http-proxy/lib/http-proxy/passes/web-incoming.js:132:27) at ClientRequest.emit (events.js:185:15) at tickOnSocket (_http_client.js:649:7) at onSocketNT (_http_client.js:665:5) at process._tickCallback (internal/process/next_tick.js:178:19)

For now, I’m going to find a way to use bodyParser only on the specific routes which don’t use http-proxy-middleware. Thanks!

If you can’t change the order of the middleware; You can restream the parsed body before proxying the request. This should fix the POST request:

6+ years later and this is still a lifesaver. Thank you!!

Still is for sure 😎

If you really cant rewrite the order, you can rebuild back the body, mind you this is in JSON format.


onProxyReq : (proxyReq, req, res) => {
        if ((req.method == "POST" ||req.method == "PUT")  && req.body) {
           let body = req.body;
           let newBody = '';
           delete req.body;

           try {
             newBody = JSON.stringify(body);
             proxyReq.setHeader( 'content-length', Buffer.byteLength(newBody, 'utf8'));
             proxyReq.write( newBody );
             proxyReq.end();
           } catch (e) {
             console.log('Stringify err', e)
           }
         }
     },
}

GRRR! Hi 😃 I arrived here from trying to figure out why webpack-dev-server was proxying a POST request and dropping the json body content somewhere on its way to the server. @chimurai 's fix ended up working, but I wasn’t even using bodyParser to start with. Are there any webpack-dev-server gurus that know any simpler solution than:

1. npm install --save body-parser
2. adding in webpack.config.js: devServer.setup = function (app) { app.use(require('body-parser').json()); }
3. adding devServer.proxy["/url/to/proxy"].onProxyReq = /*the function @chimurai so generously provided
4. making sure that the request (which uses fetch) adds the Content-Type: application/json header to the options

which all works, again, finally, but is there any easier way? I’m worried about others who might have to spend a lot of time tracking down that issue.

Spent a few hours trying to debug this same issue while setting up multiple proxies. The request would hang at the target. Moving proxyMiddleware above bodyParser solved my problem as well. Thank you!

Hi, I’m seeing this issue too using browsersync.

var proxy = proxyMiddleware('/api', {
  target: 'https://xxx.xxx.xxx.xxx',
  changeOrigin: true,    // for vhosted sites, changes host header to match to target's host
  secure: false
});

My API does not appear to get the body:

POST https://xxx.xxx.xxx.xxx/api/authorize/ 415 (Unsupported Media Type)

If I remove body-parser middleware then req.body is always undefined and restream fails because it has nothing to parse.

If you can’t change the order of the middleware; You can restream the parsed body before proxying the request. This should fix the POST request:

6+ years later and this is still a lifesaver. Thank you!!