igrigorik / em-websocket

EventMachine based WebSocket server
http://www.igvita.com/2009/12/22/ruby-websockets-tcp-for-the-browser/
MIT License
1.69k stars 187 forks source link

support haproxy #23

Open taf2 opened 13 years ago

taf2 commented 13 years ago

Apparently, to support operating behind an haproxy you can't wait for the nonce string. see the gist: https://gist.github.com/729332

I'm not 100% sure about how this works but reading references in other servers: https://github.com/Worlize/Socket.IO-node/commit/b9bef2b2660526768c1cd21ad1ef77f72ec0fc62

and https://github.com/facebook/tornado/pull/153

It appears the nonce e.g. the request body is optional? From my gist it's clear that it's not included when proxied behind HAProxy... I'm just getting setup with em-* so will take a shot at a patch but thought it'd be helpful to get some more eyes on this...

I'm using the following to manage haproxy locally for testing: https://gist.github.com/729335

I've messed around with changing the websock from mode http and mode tcp - believe with the changes in the other mentioned servers mode http would/can work... i've also tested running on the same or different ports.

taf2 commented 13 years ago

more information - after hacking a little it appears you can wait for the third key (e.g. nonce) when receiving the 101 header

[[:upgrade_headers, "HTTP/1.1 101 WebSocket Protocol Handshake\r\nUpgrade: WebSocket\r\nConnection: Upgrade\r\nSec-WebSocket-Location: ws://127.0.0.1:8888/\r\nSec-WebSocket-Origin: http://127.0.0.1:9000\r\n\r\n\x1E\xDC\xEB\xC2aRe\xBD\xAD\xE0]\x1C\xDE\e'\x8D"]]

igrigorik commented 13 years ago

Hmm, that's a gotcha. I've been running an older version of em-websocket behind haproxy, so haven't run into this. Having said that, I'm pretty sure pusherapp is running on latest version -- kinda surprised Martyn haven't run into this already?

mloughran commented 13 years ago

You're running into the issue that the third key data is not HTTP compliant, and HAProxy is doing the correct thing by not sending it when operating in layer 7 mode. Unfortunately those bytes are required as part of the handshake process in draft 76. This has been subject to more discussion than you want to imagine on the hybi list. Suffice to say that the protocol will change to remove this issue. Willy Tarreau (creator of HAProxy) is very active in protocol discussions, so eventually I'm certain that HAProxy will have good support for WebSockets.

As Illya says, we use HAProxy for pusherapp, but we use it in layer 4 mode (set mode tcp) for exactly this reason. This works fine for us, since we have dedicated hosts serving websocket traffic, but it would be an issue if you wanted to serve HTTP and WebSocket traffic on the same port. I don't have a solution for that I'm afraid.

taf2 commented 13 years ago

Thank you for the very detailed explanation - I'm on vacation for the next few days. When I get back I plan to try using the alternate port in mode tcp, my goal to have a workable configuration that could be used as reference.

mloughran commented 13 years ago

Closing

masterkain commented 12 years ago

Sorry to 'revive' an old ticket, I would like to know if steps has been taken to support this situation.

I'm using Haproxy 1.5-dev11/em-websocket and so far I'm getting 502 all the way in http mode due to HandshakeError, "Connection and Upgrade headers required".

Switching to tcp mode works of course, but I'm curious if anyone has progress info to share about this specific issue.

AFAIK there's no option in haproxy to handle a situation like this, yet.

Thanks.

masterkain commented 12 years ago

Similar: https://github.com/LearnBoost/socket.io/commit/9982232032771574ceb68e2bccee4e43fd5af887

mloughran commented 12 years ago

I haven't investigated this issue in recent memory I'm afraid. @jcoglan am I right in think that you've got this working?

jcoglan commented 12 years ago

Yep, including for draft-76 with HAProxy in http mode, which is really annoying. Here's the commit, can't remember if it's the complete picture but it's relevant.

https://github.com/faye/faye-websocket-ruby/commit/7f88e28ba553b255dd457c5ab17445f8d0decf25

masterkain commented 12 years ago

Sorry I'm a bit confused, is that something I should fix on my app rather than directly in em-websocket?

Thanks.

jcoglan commented 12 years ago

It's something that (IMO) should be handled by a WebSocket library. Part of this is a historical problem with how draft-76 does handshakes, which ought to be covered up by a library API.

mloughran commented 12 years ago

Thanks James. I've reopened this issue since it's clear that a workaround is possible, and probably desirable.

I'm unlikely to get around to this one but I'm very happy to accept a pull request if anyone wants to take it on.

jonathanhoskin commented 9 years ago

Is this still a known issue in 2015? We are trying to load balance using HAproxy and we're seeing odd behaviour.