So I have been banging my head against the wall for the better part of 2 days, please help.
I am attempting to establish a Websocket connection using this django-websocket-redis configuration. There are 2 instances of uwsgi running, one for the website and one for the websocket communication.
I used wireshark heavily to find out what exactly is happening, and apparently nginx is eating the headers "Connection: Upgrade" and "Upgrade: websocket".
here is the critical nginx config part:
upstream websocket {
server 127.0.0.1:9868;
}
location /ws/ {
proxy_pass_request_headers on;
access_log off;
proxy_http_version 1.1;
proxy_pass http://websocket;
proxy_set_header Connection "Upgrade";
proxy_set_header Upgrade websocket;
}
As you can see on those 2 screenshots, tcpdump of internal communication shows that the handshake works nicely. but in my browser (second image) the headers are missing.
Any ideas are greatly appreciated. I am truly stuck here :(
Versions:
nginx - 1.7.4
uwsgi - 2.0.7
pip freeze: Django==1.7 MySQL-python==1.2.5 django-redis-sessions==0.4.0 django-websocket-redis==0.4.2 gevent==1.0.1 greenlet==0.4.4 redis==2.10.3 six==1.8.0 uWSGI==2.0.7 wsgiref==0.1.2
Passing Request HeadersBy default, NGINX redefines two header fields in proxied requests, “Host” and “Connection”, and eliminates the header fields whose values are empty strings. “Host” is set to the $proxy_host variable, and “Connection” is set to close .
The proxy_pass setting makes the Nginx reverse proxy setup work. The proxy_pass is configured in the location section of any virtual host configuration file. To set up an Nginx proxy_pass globally, edit the default file in Nginx's sites-available folder.
proxy_set_header Upgrade $http_upgrade; Is actually doing what you want because $http_upgrade comes from the header sent by the client. So if the client doesn't request an upgrade, it doesn't get passed along. Save this answer.
Security and anonymity – By intercepting requests headed for your backend servers, a reverse proxy server protects their identities and acts as an additional defense against security attacks.
I would use gunicorn for deploying a django application, but anyway.
I remembered that I saw this on the gunicorn docs:
If you want to be able to handle streaming request/responses or other fancy features like Comet, Long polling, or Web sockets, you need to turn off the proxy buffering. When you do this you must run with one of the async worker classes.
To turn off buffering, you only need to add proxy_buffering off; to your location block:
In your location would be:
location /ws/ {
proxy_pass_request_headers on;
access_log off;
proxy_http_version 1.1;
proxy_redirect off;
proxy_buffering off;
proxy_pass http://websocket;
proxy_set_header Connection "upgrade";
proxy_set_header Upgrade websocket;
}
Link to the guide of gunicorn for deploying in nginx. http://docs.gunicorn.org/en/latest/deploy.html?highlight=header
Hope this helps
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With