Search code examples
pythondjangonginxwebsocketdjango-channels

Running daphne behind nginx reverse proxy with protocol upgrade always routes to http instead of websocket


I am trying to deploy django channels powered notification application behind Nginx reverse proxy server to only serve the websocket communications, while having Nginx + uWSGI setup to serve the django application.

The application works in my local machine seamlessly when run with either python manage.py runserver --noasgi + daphne -p 8000 myproject.asgi:application or python manage.py runserver with daphne handling all the requests internally.

Problem:

All the websocket requests are routed to http protocol type instead of websocket protocol type and it returns WebSocket connection to 'ws://ip_address/ws/' failed: Error during WebSocket handshake: Unexpected response code: 404

Packages Installed:

Django==2.0.3
channels==2.0.2
channels-redis==2.1.1
daphne==2.1.0
asgiref==2.3.0
Twisted==17.9.0
aioredis==1.0.0
autobahn==18.4.1

Environment:

Ubuntu - 16.04
Nginx - 1.12.0

Nginx Configuration for upgrading the request:

map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

# the upstream component nginx needs to connect to websocket requests
upstream websocket {
    server unix:/path/to/my/app/daphne.sock;
}

# configuration of the server
server {

        # the port your site will be served on
        listen      80;

        # the domain name it will serve for
        server_name ip_address;
        charset     utf-8;

       # Sending all non-media requests for websockets to the Daphne server.
        location /ws/ {
            proxy_pass http://websocket;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;
        }

}

routing.py

from django.conf.urls import url

from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from myapp import consumers

application = ProtocolTypeRouter({
    'websocket': AuthMiddlewareStack(
        URLRouter([
            url(r'^ws/$', consumers.MyConsumer),
        ])
    ),
})

Daphne Logs:

None - - [TimeStamp] "GET /ws/" 404 3
None - - [TimeStamp] "GET /ws/" 404 3
None - - [TimeStamp] "GET /ws/" 404 3

Kindly let me know if anything in addition is required to help.

P.S: I have deployed the same application in two servers(both having the same configuration and environment as above) and the result was same.


Solution

  • Finally I found that the culprit was my company's firewall, which was stripping the upgrade headers when application was accessed over http. So after upgrading http to https, it started working as expected.