[英]How can I serve a HTTP page and a websocket on the same url in tornado
I have an API and, depending on the request protocol, I want to either serve the client an HTTP response, or I want to connect a websocket and send the response followed by incremental updates. 我有一个API,并且根据请求协议,我想为客户端提供HTTP响应,或者我想连接一个websocket并发送响应,然后进行增量更新。 However in Tornado I can only specify a single handler for any URL. 但是在龙卷风中,我只能为任何URL指定一个处理程序。
The difference between a request for an HTTP page and a websocket is the presence of a header. HTTP页面请求和Websocket之间的区别是标头的存在。 Unfortunately afaik there is no way to tell the tornado router to choose one or the other handler based on a header (other than host). 不幸的是,afaik无法告诉龙卷风路由器根据标头(主机除外)选择一个或另一个处理程序。
I can however make a handler that inherits from both my already quite elaborate MyBaseRequestHandler
and WebSocketHandler
, with some magic. 但是,我可以制作一个从我已经非常精巧的MyBaseRequestHandler
和WebSocketHandler
继承的处理程序,并且具有一些魔力。 The following code works in python 3.5 and tornado 4.3, your mileage may vary on other versions: 以下代码可在python 3.5和龙卷风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)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.