I've come across what I think is a bug (or at least an incompatibility) within http-proxy.
What I expect to happen: when I make a proxied POST request to the backend, it should process the request normally.
What happens instead: when I make a proxied POST request with the Connect.bodyDecoder() middleware installed, the request hangs forever in the proxy.
I created a very simple test case here: http://vivoh.com/node-proxy.zip
If you unzip this (and have ruby and the sinatra gem installed), you can see what I mean.
Run as is using the run.sh script, and then hit http://localhost:4568. Then, hit the "Submit Query" button. You'll see the http-proxy module successfully proxies the POST request request to the backend sinatra ruby server.
If you then edit "app.js" and uncomment the Connect.bodyDecoder() line, and then kill the node and ruby servers, and then restart using run.sh, if you try the POST request again, you'll see it hangs forever. I speculate there is something happening inside the bodyDecoder() middleware which is incompatible with the http-proxy module. I've looked around, but have not figured it out myself.
I think this makes a lot of sense actually.
If you look at the bodyDecoder middleware you can see it's processing the request object and adding an event listener to the completion of the request. https://github.com/senchalabs/connect/blob/master/lib/connect/middleware/bodyDecoder.js#L40
To my understanding, since the request has already had it's end event fire, it's already been processed and cannot be proxied. http-proxy is hanging because the end and data event of the incoming request have already fired.
I'm sure there is a way around this, it's just a matter of figuring out which library needs to get patched. Wrapping http-proxy up as a proper connect middleware might also be a solution.
Let me talk to the Connect guys and I'll see what we can figure out.
Sounds great. I really appreciate this module, it makes it so easy to do what I need to do and proxy out to other servers within node. Please let me know if there is anything I can do to help troubleshoot any solutions you come across.
And, really what I want to do with the bodyDecoder middleware is pull out certain parameters from the post request. I need to do this for my connect-rpx module. If there were a better way to do this than use bodyDecoder() I would be OK with this too. If I understand you correctly, it seems like the problem is that if you want access to the body of the incoming request (like I need) then it is a bit too late to proxy it.
I got things working. My solution was to remove the bodyDecoder from the filter chain, and then call it only when I need it inside my connect-rpx module.
Thanks for your help, your explanation was very helpful in having my understand where the issue was happening.
Cool! You are very welcome. Let me know if you run into any additional issues. Closed.
FYI I have this issue as well, both with one node.js web app proxying AJAX POST requests via http-proxy to another one as well as just a single node.js web app handling AJAX POSTs straight from the browser independently. I found depending on where in the filter chain express.bodyParser() is, I can get this hang. I can work around it by emitting a duplicate 'end' event from the request, but I'd like to understand exactly what I'm doing wrong that is causing this.
@focusaurus If you buffer and parse the incoming request of the body before you proxy the request, you can't proxy the original request anymore.
Yes that makes sense. I have removed the bodyParser middleware from my front end web server, but I'm still hitting some variant of this issue on my back end web server, which is using bodyParser but is NOT proxying the request. Still digging through code to try to understand what other code in my back end web server is waiting for but not seeing the "end" event on the request.