django-websocket-redis icon indicating copy to clipboard operation
django-websocket-redis copied to clipboard

HTTP_SEC_WEBSOCKET_KEY

Open taylorc93 opened this issue 10 years ago • 4 comments

Good evening!

I'm currently trying to integrate websockets into my django app. I'm using nginx to proxy my client side requests to the uWSGIWebsocketServer. I've been following your guide here with setting up two different uWSGI instances: https://django-websocket-redis.readthedocs.org/en/latest/running.html#django-with-websockets-for-redis-behind-nginx-using-uwsgi. Currently, my setup works fine locally: I can connect successfully and receive messages. However, when I try to deploy my site on docker, I can't connect at all and get a 500 error saying that the HTTP_SEC_WEBSOCKET_KEY isn't set in environ here: https://github.com/jrief/django-websocket-redis/blob/master/ws4redis/uwsgi_runserver.py#L52. All of my processes are running and I can hit my site fine, I just can't connect with websockets.

I've checked and can see that when trying to connect to my docker container, the Sec-Websocket-Key is set in the request header and the request looks almost identical to the local one. The only difference is that nginx is version 1.6.8 on my docker image vs 1.8.0 on my local machine. This shouldn't be an issue though since websockets have been supported since 1.3. I'm really not sure what's happening so I was wondering if you have any ideas. Here are my relevant files:

nginx.conf:

daemon off;
error_log /dev/stdout info;
user root;
worker_processes 2;
worker_rlimit_nofile 100000;
events {
    worker_connections 50000;
    accept_mutex off;
}

http {
    access_log off;
    sendfile on;

    server {
        listen       80;
        server_name  _;
        charset     utf-8;
        include     /etc/nginx/mime.types;
        root        /srv/site/;

        # max upload size
        client_max_body_size 75M;   # adjust

        location / {
            include               /etc/nginx/uwsgi_params.default;
            proxy_pass            http://localhost:8000;
            proxy_set_header      X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header      X-Real-IP $remote_addr;
            proxy_set_header      Host $host:$server_port;
            proxy_redirect        off;
            proxy_buffering       off;
            proxy_read_timeout    600s;

            gzip                  on;
            gzip_http_version     1.0;
            gzip_comp_level       5;
            gzip_min_length       256;
            gzip_disable          "MSIE [1-6]\.";
            gzip_types            application/atom+xml
                                  application/javascript
                                  application/json
                                  application/ld+json
                                  application/manifest+json
                                  application/rss+xml
                                  application/vnd.geo+json
                                  application/vnd.ms-fontobject
                                  application/x-font-ttf
                                  application/x-web-app-manifest+json
                                  application/xhtml+xml
                                  application/xml
                                  font/opentype
                                  image/bmp
                                  image/svg+xml
                                  image/x-icon
                                  text/cache-manifest
                                  text/css
                                  text/plain
                                  text/vcard
                                  text/vnd.rim.location.xloc
                                  text/vtt
                                  text/x-component
                                  text/x-cross-domain-policy;
        }

        location /ws/ {
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_pass http://localhost:8001;
        }
    }
}

websocket ini file:

[uwsgi]
umask = 002
chdir = /srv/site/
pythonpath = server/
module = base.wsgi_websocket:application
no-orphans = true
die-on-term = true
memory-report = true
http-socket = 0.0.0.0:8001
http-websockets = true
gevent = 1000
threads = 1
processes = 1
master = true

Dockerfile:

FROM centos:latest

RUN yum -y update
RUN yum group install -y "Development Tools"
RUN yum install -y epel-release
RUN yum -y install supervisor nginx python-devel python-setuptools postgresql-devel ncurses-devel

RUN easy_install pip

ADD . /srv/site
WORKDIR /srv/site

ADD scripts/assets/requirements.txt /srv/site/scripts/assets/requirements.txt
RUN pip install -r scripts/assets/requirements.txt
RUN pip install uwsgi

WORKDIR /srv/site
EXPOSE 80
CMD ["/usr/bin/supervisord", "-c", "/srv/site/deploy/supervisord.conf"]

supervisord.conf

[supervisord]
nodaemon = true

[program:nginx]
user=root
command = /usr/sbin/nginx -p /srv/site/deploy/ -c /srv/site/deploy/nginx.conf
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0

[program:app-site]
command = /usr/bin/uwsgi --ini /srv/site/deploy/webserver.ini
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0

[program:app-websockets]
command = /usr/bin/uwsgi --ini /srv/site/deploy/websocket.ini
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0

Looking forward to hearing back!

taylorc93 avatar Dec 01 '15 22:12 taylorc93

Are you developing on Linux or do you use boot2docker? In the latter case, this could be an issue because of some NAT/Bridging stuff.

jrief avatar Dec 02 '15 16:12 jrief

I use docker machine (the newer, officially supported version of boot2docker). Do you have any suggestions on how to inspect the NAT/bridge configurations?

taylorc93 avatar Dec 02 '15 16:12 taylorc93

Its about a year, since I used Docker the last time. I believe that you can access the VM guest, which runs the real Docker containers. However without having hand on your environment, its rather difficult to give advice.

BTW, why do you use supervisor to spawn uwsgi and nginx? uwsgi can be used in emperor mode for this job. Also, I don't see where you start the Redis daemon on your Docker guest.

jrief avatar Dec 02 '15 17:12 jrief

I am currently facing a similar issue. Locally, I am able to connect to the websocket and exchange messages, but when I try toi deploy it to a vm I get this:

Traceback (most recent call last): File "/home/minus/minus_env/local/lib/python2.7/site-packages/ws4redis/wsgi_server.py", line 113, in __call__ websocket = self.upgrade_websocket(environ, start_response) File "/home/minus/minus_env/local/lib/python2.7/site-packages/ws4redis/uwsgi_runserver.py", line 52, in upgrade_websocket uwsgi.websocket_handshake(environ['HTTP_SEC_WEBSOCKET_KEY'], environ.get('HTTP_ORIGIN', '')) IOError: unable to complete websocket handshake Starting late response on websocket Finish non-websocket response with status code: 500 [pid: 1516|app: 0|req: 1/2] 0.0.0.0 () {44 vars in 905 bytes} [Thu Oct 5 12:01:27 2017] GET /ws/live-score?subscribe-broadcast&publish-broadcast&echo => generated 38 bytes in 6 msecs (HTTP/1.1 500) 1 headers in 78 bytes (3 switches on core 999) Nginx: version - 1.4.6 location /ws/ { proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_pass http://unix:/home/minus/home-screen/uwsgi_socket.sock; }

Uwsgi: version - 2.0.14 `[uwsgi]

virtualenv = /home/minus/minus_env/ chdir = /home/minus/home-screen/ http-socket = /home/minus/home-screen/uwsgi_socket.sock chmod-socket = 664 gevent = 1000 http-websockets = true workers = 2 master = true module = minus.websocket_wsgi:application`

Any idea, what's wrong?

ghost avatar Oct 05 '17 06:10 ghost