首页 > 解决方案 > 龙卷风中的异步中间件

问题描述

我的目标是在每个 websocket 请求初始化之前验证访问令牌。为此,我需要调用我的 oauth 服务器。所以试图添加一个中间件来检查访问令牌。我在此链接https://github.com/tornadoweb/tornado/issues/49中找到了如何添加中间件,它工作正常。但问题是当我调用我的 oauth 服务器时,我是在异步进行的,而且看起来中间件不能是异步的。这是我的示例代码

app = Application()


async def middleware(request):
    userToken = request.headers.get('Authorization')
    active = await check_accesstoken(userToken)
    if not active:
      return error
    app(request)

async def check_accesstoken(userToken):
    http_client = httpclient.AsyncHTTPClient()
    post_data = {'token': userToken, 'scope': 'email phone'}
    api_endpoint = 'https://192.168.0.4:1445/oauth2/introspect'
    json_data = json.dumps(post_data)

    response = await http_client.fetch(api_endpoint,
                                       raise_error=False,
                                       method='POST',
                                       body=json_data
                                       # headers=headers
                                       )
    return response.body.active:


def main():    
    http_server = tornado.httpserver.HTTPServer(middleware)
    http_server.listen(PORT, HOST) 
    tornado.ioloop.IOLoop.current().start()

if __name__ == '__main__':
    main()

出现以下错误。

RuntimeWarning:从未等待协程“中间件”
self.request_callback(self.request)

问题

  1. 如何添加 aync 中间件?

  2. 或者我应该对 oauth 服务器进行同步调用?

  3. 或者还有其他地方我应该检查访问令牌吗?

标签: pythontornadomiddleware

解决方案


是的,这比覆盖更麻烦HTTPServer

想到的一个更明智的解决方案是,您可以子类化RequestHandler并在该子类上创建一个prepare()方法,您可以在其中检查访问令牌。

然后从该子类创建所有处理程序。这是一个例子:

class BaseHandler(web.RequestHandler):
    async def prepare(self):
        active = await check_accesstoken(userToken)
        if not active:
            self.write("Error")
            self.finish()


class SomeHandler(BaseHandler):
    ...

如果您还需要在处理程序上创建方法prepare(),只需调用using 。BaseHandlerpreparesuper()


推荐阅读