Search code examples
pythonproxywebsocketautobahn

Autobahn 0.7.3 - Proxied Websocket fails when a client is behind a http Proxy


I'm proxying my test websocket using nginx from 9000 to 80 port and all my tests are ok until the client is behind a web proxy, then the handshake process fails, where can be the problem? Thanks in advance for your time.

I'm getting these errors:
Client:

WebSocket connection to 'ws://myserver/ws/' failed: Error during WebSocket handshake: Unexpected response code: 502 autobahn.min.js:62

Server:

2014-01-10 19:51:22-0300 [PubSubServer1,19,127.0.0.1] Unhandled Error
    Traceback (most recent call last):
      File "/usr/lib/python2.7/dist-packages/twisted/python/log.py", line 84, in callWithLogger
        return callWithContext({"system": lp}, func, *args, **kw)
      File "/usr/lib/python2.7/dist-packages/twisted/python/log.py", line 69, in callWithContext
        return context.call({ILogContext: newCtx}, func, *args, **kw)
      File "/usr/lib/python2.7/dist-packages/twisted/python/context.py", line 118, in callWithContext
        return self.currentContext().callWithContext(ctx, func, *args, **kw)
      File "/usr/lib/python2.7/dist-packages/twisted/python/context.py", line 81, in callWithContext
        return func(*args,**kw)
    --- <exception caught here> ---
      File "/usr/lib/python2.7/dist-packages/twisted/internet/posixbase.py", line 586, in _doReadOrWrite
        why = selectable.doRead()
      File "/usr/lib/python2.7/dist-packages/twisted/internet/tcp.py", line 199, in doRead
        rval = self.protocol.dataReceived(data)
      File "/usr/local/lib/python2.7/dist-packages/autobahn-0.7.3-py2.7.egg/autobahn/twisted/websocket.py", line 77, in dataReceived
        self._dataReceived(data)
      File "/usr/local/lib/python2.7/dist-packages/autobahn-0.7.3-py2.7.egg/autobahn/websocket/protocol.py", line 1270, in _dataReceived
        self.consumeData()
      File "/usr/local/lib/python2.7/dist-packages/autobahn-0.7.3-py2.7.egg/autobahn/websocket/protocol.py", line 1303, in consumeData
        self.processHandshake()
      File "/usr/local/lib/python2.7/dist-packages/autobahn-0.7.3-py2.7.egg/autobahn/websocket/protocol.py", line 2819, in processHandshake
        self.sendServerStatus()
      File "/usr/local/lib/python2.7/dist-packages/autobahn-0.7.3-py2.7.egg/autobahn/websocket/protocol.py", line 3276, in sendServerStatus
        self.sendHtml(html)
      File "/usr/local/lib/python2.7/dist-packages/autobahn-0.7.3-py2.7.egg/autobahn/websocket/protocol.py", line 3219, in sendHtml
        response += "Content-Length: %d\x0d\x0a" % len(raw)
    exceptions.NameError: global name 'raw' is not defined

My Test server:

import sys
from twisted.python import log
from twisted.internet import reactor
from autobahn.twisted.websocket import listenWS
from autobahn.wamp import WampServerFactory, \
                          WampServerProtocol

class PubSubServer1(WampServerProtocol):

   def onSessionOpen(self):

      self.registerForPubSub("http://test.com/test")

if __name__ == '__main__':

   log.startLogging(sys.stdout)

   factory = WampServerFactory("ws://localhost:9000", debugWamp = 'debug',externalPort=80)
   factory.protocol = PubSubServer1
   factory.setProtocolOptions(allowHixie76 = True)
   listenWS(factory)

   #reactor.listenTCP(9000, factory)
   reactor.run()

Command:

~$ python /home/my/wsbroker.py 
/usr/local/lib/python2.7/dist-packages/zope.interface-4.0.5-py2.7-linux-x86_64.egg/zope/__init__.py:3: UserWarning: Module twisted was already imported from /usr/lib/python2.7/dist-packages/twisted/__init__.pyc, but /usr/local/lib/python2.7/dist-packages/autobahn-0.7.3-py2.7.egg is being added to sys.path

Edited:
Debug info for a failed handshake (Client using a web proxy):http://pastebin.com/aN4ppA2e
Debug info for a done handshake (Client without proxy):http://pastebin.com/5rXREY2q


Solution

  • The traceback you see above is due to a bug introduced with Autobahn 0.7.0 and fixed in 0.7.4.

    However, the bug is likely not the cause of your actual problem: the traceback shows that Autobahn was trying to render a plain HTML server status page - and it does so, when the HTTP request it receives does not contain Upgrade to Websocket headers. You proxy might not (yet) be configured to properly forward WebSocket.

    Another thing you might run into: WebSocketServerFactory of Autobahn provides an option to set the externalPort. This should be set to the TCP/IP port of your proxy under which it accepts WebSocket connections. This is needed since Autobahn will (in compliance with the WebSocket specification) check if the WebSocket opening HTTP request host and port matches the one it runs on (and if it's different, bail out). The mentioned option allows you to override that behavior.