如何从 Twisted Root 资源访问 Autobahn WebSocketResource?

How to access Autobahn WebSocketResource from Twisted Root Resource?

我一直在搜索许多示例来演示如何访问 Autobahn Twisted WebSocketResource ,但似乎找不到说明这一点的示例。

我从这个例子Autobahn Twisted WebSocketResource example了解到,您实例化一个WebSocketServerFactory,设置websocket协议,然后使用WebSocketResource(factory)创建websocket资源。拥有 websocket 资源后,可以在创建 Site 实例之前将其添加到主 Twisted Web 资源路径中,如下所示:

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)

所以我的理解是 ws://127.0.0.1:8000/ws 上的所有请求都将路由到 websocket 资源。但是 /ws 资源似乎没有被浏览器发现。 GET 请求工作正常,但 websocket 请求不工作。

就 websocket 请求而言,这是我认为应该解决此问题的事件流(我只是不确定如何实现它们):

  1. 浏览器向 header.
  2. 中的 websocket 发送一个带有 UpgradeGET 请求
  3. render_GET HttpResource 上的方法需要在请求中识别这一点并将响应代码设置为 101 and/or 找到 ws 资源来处理数据通信。

如何从根资源切换到 child 资源,以便 websocket 可以处理 websocket 请求?

我最初的想法是在根资源上使用 getChild 方法来检查 ws。如果名称是 ws 那么 return websocket 资源。我还在这里阅读:Twisted Web (isLeaf) 根资源 class HttpResource 下的 isLeaf 属性无法存在或者您无法访问 children根资源。

任何帮助都会很棒。非常感谢您提供的任何帮助。

干杯!

布莱恩

在阅读了一些有关 Autobahn 和 Twisted 的内容后,我找到了一段有效的代码。 Autobahn 的 onConnect 方法处理请求并在需要时达到 header。

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()