如何在龙卷风中在同一个url上提供HTTP页面和websocket



我有一个API,根据请求协议,我想为客户端提供HTTP响应,或者我想连接一个websocket并发送响应,然后进行增量更新。然而,在Tornado中,我只能为任何URL指定一个处理程序。

HTTP页面请求和websocket之间的区别在于是否存在标头。不幸的是,afaik没有办法告诉龙卷风路由器根据标头(而不是主机)选择一个或另一个处理程序。

然而,我可以制作一个处理程序,它继承了我已经非常复杂的MyBaseRequestHandlerWebSocketHandler,并具有一些魔力。以下代码适用于python 3.5和Toronto 4.3,您的里程数可能因其他版本而异:

class WebSocketHandlerMixin(tornado.websocket.WebSocketHandler):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # since my parent doesn't keep calling the super() constructor,
        # I need to do it myself
        bases = type(self).__bases__
        assert WebSocketHandlerMixin in bases
        meindex = bases.index(WebSocketHandlerMixin)
        try:
            nextparent = bases[meindex + 1]
        except IndexError:
            raise Exception("WebSocketHandlerMixin should be followed "
                            "by another parent to make sense")
        # undisallow methods --- t.ws.WebSocketHandler disallows methods,
        # we need to re-enable these methods
        def wrapper(method):
            def undisallow(*args2, **kwargs2):
                getattr(nextparent, method)(self, *args2, **kwargs2)
            return undisallow
        for method in ["write", "redirect", "set_header", "set_cookie",
                       "set_status", "flush", "finish"]:
            setattr(self, method, wrapper(method))
        nextparent.__init__(self, *args, **kwargs)
    async def get(self, *args, **kwargs):
        if self.request.headers.get("Upgrade", "").lower() != 'websocket':
            return await self.http_get(*args, **kwargs)
        # super get is not async
        super().get(*args, **kwargs)

class MyDualUseHandler(WebSocketHandlerMixin, MyBaseHandler):
    def http_get():
        self.write("My HTTP page")
    def open(self, *args, **kwargs):
        self.write_message("Hello WS buddy")
    def on_message(self, message):
        self.write_message("I hear you: %s" % message)

相关内容

  • 没有找到相关文章

最新更新