Repository: django/channels

Issue:
nginx websocket proxy
Hi,

I'm currently playing with django channels and it looks really great. I have tried several other websocket stuff in the last weeks, like crossbar (http://crossbar.io) and something I have build with tornado.

I have added following snippet to my nginx configuration:

```
    location /ws/ {
       rewrite  ^/(.*)  /$1 break;
       proxy_set_header X-Real-IP $remote_addr;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header Host $http_host;
       proxy_redirect off;

       proxy_pass http://localhost:8080/;
       proxy_http_version 1.1;
       proxy_set_header Upgrade $http_upgrade;
       proxy_set_header Connection "upgrade";
    }
```

which works fine with other websocket servers, but it looks like it won't work with runwsserver.
(I tried asyncio and twisted).
The error I see in the browser is: `WebSocket connection to 'ws://localhost/ws/asd' failed: Error during WebSocket handshake: Unexpected response code: 400`
I can see that the websocket server is reached since it prints some debug lines:

```
INFO asyncio poll 1.000 took 1.001 seconds
DEBUG asyncio poll 1.000 took 0.817 seconds
DEBUG asyncio poll 0.000 took 0.000 seconds
DEBUG asyncio poll 0.000 took 0.000 seconds
DEBUG asyncio poll 0.000 took 0.000 seconds
DEBUG asyncio poll 0.181 took 0.182 seconds
```

but thats not really helpful ;)

I'll try to dig into the code at the weekend, but maybe someone can help me before that ;)

Thanks,
  Bastian



Discussion:
Does the connection work from your browser directly? Would be good to establish that it works without the proxy in the way; might be a browser-specific bug as well.

That said, the current `runwsserver` code is being retired in favour of an all-combined HTTP+WebSocket server, which you can try out with `runallserver` right now, but that's still under development so it might not work (but might give a different error, or might work?)

I found the culprit. It looks like specifying the ws:// url for `WebSocketServerFactory` is optional. If specified autobahn will check if the header in the connection matches.

the code for that in autobahn is at : https://github.com/crossbario/autobahn-python/blob/a771b54bc93f4d0cc273162dc737f2c528a92fdd/autobahn/websocket/protocol.py#L2508

by removing the url at https://github.com/andrewgodwin/channels/blob/master/channels/interfaces/websocket_asyncio.py#L23 my errors goes away and it looks like everything is working now.

Fantastic, thanks for investigating - will remove that now.


Resolving patch:
diff --git a/channels/interfaces/websocket_twisted.py b/channels/interfaces/websocket_twisted.py
--- a/channels/interfaces/websocket_twisted.py
+++ b/channels/interfaces/websocket_twisted.py
@@ -20,7 +20,7 @@ def __init__(self, channel_backend, port=9000):
         self.port = port
 
     def run(self):
-        self.factory = get_factory(WebSocketServerFactory)("ws://0.0.0.0:%i" % self.port, debug=False)
+        self.factory = get_factory(WebSocketServerFactory)(debug=False)
         self.factory.protocol = get_protocol(WebSocketServerProtocol)
         reactor.listenTCP(self.port, self.factory)
         reactor.callInThread(self.backend_reader)


Test patch: