I have been searching for many examples to demonstrate how to access a Autobahn Twisted WebSocketResource , but can't seem to find examples that show this.
I understand from this example Autobahn Twisted WebSocketResource example that you instantiate a WebSocketServerFactory
, set the websocket protocol and then use WebSocketResource(factory)
to create the websocket resource. Once you have the websocket resource, this can be added on the main Twisted Web resource path before creating the Site
instance like so:
class WebSocketProtocol(WebSocketServerProtocol):
def onConnect(self, request):
print("WebSocket connection request: {}".format(request))
def onMessage(self, payload, isBinary):
self.sendMessage(payload, isBinary)
class HttpResource(resource.Resource):
isLeaf = True
def render_GET(self, request):
return "<html><h1>Hello World!</h1></html>"
factory = WebSocketServerFactory(u"ws://127.0.0.1:8000")
factory.protocol = WebSocketProtocol
ws_resource = WebSocketResource(factory)
root = HttpResource()
root.putChild(b"ws", ws_resource)
site = Site(root)
So my understanding is that all requests on ws://127.0.0.1:8000/ws
will be routed to the websocket resource. However the /ws
resource doesn't appear to be discovered by the browser. The GET requests work fine, but the websocket requests do not.
As far as the websocket requests goes, here is the flow of events that I believe should fix this issue (I am just not sure how to implement them):
GET
request with Upgrade
to websocket in the header.render_GET
method on HttpResource
needs to recognize this in the request and set the response code to 101 and/or locate the ws
resource to handle data communication.How do you switch from the root resource to a child resource so that the websocket can handle websocket requests?
My initial thought was to use the getChild
method on the root resource to check for ws
. If name is ws
then return the websocket resource. I also read here: Twisted Web (isLeaf) that the isLeaf
attribute under the root resource class HttpResource
cannot be present or you can't access the children on the root resource.
Any help would be great. Thank you so much in advance for any help you can provide.
Cheers!
Brian
After some time reading about Autobahn and Twisted, I have arrived at a snippet of code that works. Autobahn's onConnect
method handles the request and peaks into the header if need be.
class WebSocketProtocol(WebSocketServerProtocol):
def onConnect(self, request):
custom_header = {}
if request.headers['sec-websocket-key']:
custom_header['sec-websocket-protocol'] = 'graphql-ws'
return (None, custom_header)
def onMessage(self, payload, isBinary):
self.sendMessage(payload, isBinary)
class HttpResource(Resource):
isLeaf = True
def render_GET(self, request):
return "<html><h1>Hello World!</h1></html>"
factory = WebSocketServerFactory()
factory.protocol = WebSocketProtocol
ws_resource = WebSocketResource(factory)
root = Resource()
root.putChild("", HttpResource())
root.putChild(b"ws", ws_resource)
site = Site(root)
reactor.listenTCP(8000, site)
reactor.run()