Version 1.3.13 of nginx is out and with it comes support for Connection: upgrade and Upgrade header, meaning proxying of WebSockets! Many people have been waiting for this and “are websockets in nginx supported?” is one of the most frequent questions in #nginx on freenode. With that out of the way, time to have a look at the nginx WebSocket implementation.
This is indeed fairly simple and configuring the HTTP version used isn’t even new at all. We can go ahead and improve the versatility a bit by creating a connection variable thus allowing us to move these proxy_set_headers into a generic included file.
This makes the variable $upgrade_requested available to proxy_set_header Connection and if connection upgrade wasn’t requested then it will default back to “” to not interfere with normal requests. The idea here being that if you always proxy HTTP/1.1 then you don’t need a location specifically to handle WebSockets.
Connection upgrading seems unlikely to be back ported into the stable branch so if you wish to use this you will have to use the development branch. Thankfully development in nginx does not mean that it’s not run-time stable, it just means that the API might change and as such it only affects module authors. Don’t be afraid to install the development version to play around with this new feature.
So far a few limitations are known in the websocket implementation.
Client Must Specify Connection Upgrade The client need to have requested the connection upgrade, otherwise nginx will fail. Currently that part is listed as a todo in the code so I can’t say how it will fail, but I’m sure it will be implemented eventually so don’t rely on it. This limitation should not be an issue to anyone and the only issue with it is a theoretical situation where a module author might want to use connection upgrade to a backend and then process the response itself.
WebSockets Time Out WebSockets are still affected by proxy_read_timeout which defaults to 60 seconds. This means that if you have an application using WebSockets but not sending any data more than once per 60 seconds you either need to increase the timeout or implement a ping message to keep the connection alive. The ping solution has the added benefit of discovering if the connection was closed unexpectedly.
Keep-Alive & WebSockets Keep-alive pings aren’t usable for working around the above mentioned timeout as they work on the TCP level are are just empty packets. They aren’t reported to the application and thus the application will never respond to them meaning that proxy_read_timeout will still trigger.
WebSockets Supports SSL Since WebSockets tie into the normal proxy module SSL works the exact same way it normally would.
Proxy Buffers WebSockets utilize two memory buffers the size of proxy_buffer_size, one for upstream data and another for downstream data. The difference between WebSockets and a normal proxy request is that WebSockets will never buffer to disk.
Case Sensitive Upgrade Header Some backends do a case sensitive check on the upgrade header and will require the header to be either “upgrade” or “Upgrade”, failing on one and working on the other. If things seem to be right but doesn’t work then try changing the case of the header.