import asyncio import flask import aiohttp.web from aiohttp import hdrs from flask.ctx import RequestContext from werkzeug.local import LocalProxy def is_websocket_request(request: aiohttp.web.Request) -> bool: """Is the request websocket request? :param request: aiohttp web request object """ upgrade = request.headers.get(hdrs.UPGRADE, '').lower().strip() connection = request.headers.get(hdrs.CONNECTION, '').lower() return 'websocket' == upgrade and 'upgrade' in connection def freeze(object_or_proxy): """Get current object of `object_or_proxy` if it is LocalProxy""" if isinstance(object_or_proxy, LocalProxy): return object_or_proxy._get_current_object() return object_or_proxy def async_response(coroutine, app: flask.Flask or LocalProxy, request: flask.Request or LocalProxy) -> \ flask.Response: """Convert coroutine to asynchronous flask response. :param coroutine: coroutine :param app: Flask application :param request: Current request :returns: asynchronous Flask response """ #: :type: flask.Flask app = freeze(app) # :type: flask.Request request = freeze(request) class AsyncResponse(app.response_class): def __init__(self): super().__init__(coroutine) @asyncio.coroutine def call_response(self): rv = app.preprocess_request() if rv is None: try: rv = yield from self.response except Exception as e: rv = app.handle_user_exception(e) if asyncio.iscoroutine(rv): rv = yield from rv response = app.make_response(rv) response = app.process_response(response) return response @asyncio.coroutine def __call__(self, environ, start_response): with RequestContext(app, environ, request): try: # Fetch data from coroutine rv = yield from self.call_response() except Exception as e: rv = app.handle_exception(e) if asyncio.iscoroutine(rv): rv = yield from rv rv = app.make_response(rv) if asyncio.iscoroutine(rv): rv = yield from rv # Call as WSGI app if isinstance(rv, app.response_class): return rv(environ, start_response) status = self.status headers = self.get_wsgi_headers(environ) app_iter = [] start_response(status, headers) return app_iter return AsyncResponse()