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

Created on 7 Dec 2015  路  25Comments  路  Source: chimurai/http-proxy-middleware

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?

question

Most helpful comment

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.

All 25 comments

I haven't tested the proxyTable option with POST requests yet.

Which version of http-proxy-middleware are you using?
And which server/version do you use? (connect, express or something else?)

Could you provide an example to show this problem?
This will speed up the debugging process.

Hi,
I use:
"express": "~4.0.0",
"http-proxy-middleware": "^0.9.0",

Thanks.

How does your post request (url) look like?

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)

@chimurai it looks like:
POST http://my.app.host:2000/api/operation/zero/minus/something/else
or
POST http://my.app.host:2000/api/one/something

and in both cases data which I'm sending is:
{something: 'one', else: 'two'}

Sorry - do you mean this works for you or am I doing something wrong with my post request ?

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.

Yes, this solved my problem. Thank you very much for your help.

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)?

The same question :)

I'm having this same (or a very similar) problem when using browser-sync with http-proxy-middleware. The middleware is moving my POST request to a GET request using x-www-form-urlencoded, which is being rejected by the server.

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)

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!

For my purpose, I was able to make this work by changing the order i.e. putting body-parser after proxy-middleware..
Thanks.

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.

It seems to work now with Webpack 3.6.0 - I tried removing my fix after I had an issue trying to post JSON.stringify(true), and the proxy no longer chokes on the json body, no matter the shape!

I ran into a similar issue where the proxied post parameters weren't being included. The issue was that the request headers didn't specify application/json.
const headers = { Accept: "application/json", "Content-Type": "application/json", };
It is strange that isn't any error being specified or logged and that the post body is just ignored.

@chimurai why ? This solved my problem ,but why body-parser middleware is causing the problem.

@chimurai becuase it changes the req.body property

@chping2125 Not sure about @aryeharmon answer, but as I understand, the request body data is a node stream (if you remember express tutorials, the req object inherits from a node's stream), which bodyparser pipes (and this thus "empties") out the data from the request stream.

See this here https://github.com/expressjs/body-parser/blob/master/lib/read.js#L162

That is why chimurai said on his post (https://github.com/chimurai/http-proxy-middleware/issues/40#issuecomment-249430255) that his middleware patch "restreams" the body data, not to the original req stream (since is a "read only "ReadableStream") but into the proxy middleware's request stream (like if bodyparser never emptied out the request data body).

This kind of transforms the data 2 times, but its an example solution that he proposed (and doesn't handles if was parsed from application/x-www-form-urlencoded).

Hope it's clearer now.

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!

https://github.com/chimurai/http-proxy-middleware/blob/master/recipes/modify-post.md
line 39 // Remove body-parser body object from the request

Why delete body-parser in http-proxy-middleware?

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..

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 you're GET requests being proxied just fine, but your POST requests seem to hang and not being proxied, this issue is providing solutions.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

gajus picture gajus  路  8Comments

udayms picture udayms  路  8Comments

dzz9143 picture dzz9143  路  3Comments

zh-h picture zh-h  路  3Comments

DylanPiercey picture DylanPiercey  路  6Comments