async def test_wsgi_stops_iterating_after_content_length_bytes(): """ Makes sure WsgiToAsgi does not iterate after than Content-Length bytes """ def wsgi_application(environ, start_response): start_response("200 OK", [("Content-Length", "4")]) yield b"0123" pytest.fail("WsgiToAsgi should not iterate after Content-Length bytes") yield b"4567" application = WsgiToAsgi(wsgi_application) instance = ApplicationCommunicator( application, { "type": "http", "http_version": "1.0", "method": "GET", "path": "/", "query_string": b"", "headers": [], }, ) await instance.send_input({"type": "http.request"}) assert (await instance.receive_output(1)) == { "type": "http.response.start", "status": 200, "headers": [(b"content-length", b"4")], } assert (await instance.receive_output(1)) == { "type": "http.response.body", "body": b"0123", "more_body": True, } assert (await instance.receive_output(1)) == {"type": "http.response.body"}
def __init__(self, app: Union[ASGIFramework, 'WSGIApplication'], *, termination_policy: Optional[TerminationPolicy] = None, port: Optional[int] = None): if not is_async_callable(app): app = WsgiToAsgi(app) if termination_policy is None: termination_policy = DEFAULT_TERMINATION_POLICY if port is None: try: port = int(os.environ['PORT']) except KeyError: port = DEFAULT_PORT except ValueError: raise PortParseError() self._app = cast(ASGIFramework, app) self._config = Config() self._config.bind = [f'0.0.0.0:{port}'] self._sockets = self._config.create_sockets() self._termination_policy = termination_policy self._task = None
async def test_wsgi_empty_body(): """ Makes sure WsgiToAsgi handles an empty body response correctly """ def wsgi_application(environ, start_response): start_response("200 OK", []) return [] application = WsgiToAsgi(wsgi_application) instance = ApplicationCommunicator( application, { "type": "http", "http_version": "1.0", "method": "GET", "path": "/", "query_string": b"", "headers": [], }, ) await instance.send_input({"type": "http.request"}) # response.start should always be send assert (await instance.receive_output(1)) == { "type": "http.response.start", "status": 200, "headers": [], } assert (await instance.receive_output(1)) == {"type": "http.response.body"}
def __call__(self, scope): path = scope["path"] root_path = scope.get("root_path", "") # Call into a submounted app, if one exists. for path_prefix, app in self.apps.items(): if path.startswith(path_prefix): scope["path"] = path[len(path_prefix):] scope["root_path"] = root_path + path_prefix try: return app(scope) except TypeError: app = WsgiToAsgi(app) return app(scope) return self.app(scope)
async def test_basic_wsgi(): """ Makes sure the WSGI wrapper has basic functionality. """ # Define WSGI app def wsgi_application(environ, start_response): assert environ["HTTP_TEST_HEADER"] == "test value" start_response("200 OK", [["X-Colour", "Blue"]]) yield b"first chunk " yield b"second chunk" # Wrap it application = WsgiToAsgi(wsgi_application) # Launch it as a test application instance = ApplicationCommunicator( application, { "type": "http", "http_version": "1.0", "method": "GET", "path": "/foo/", "query_string": b"bar=baz", "headers": [[b"test-header", b"test value"]], }) await instance.send_input({ "type": "http.request", }) # Check they send stuff assert (await instance.receive_output(1)) == { "type": "http.response.start", "status": 200, "headers": [(b"X-Colour", b"Blue")], } assert (await instance.receive_output(1)) == { "type": "http.response.body", "body": b"first chunk ", "more_body": True, } assert (await instance.receive_output(1)) == { "type": "http.response.body", "body": b"second chunk", "more_body": True, } assert (await instance.receive_output(1)) == { "type": "http.response.body", }
def construct_app(): flask = App(__name__) flask.load() flask.load_phase_2() api_v2 = APIv2(flask) _setup_context(flask) routes = [ Route("/api/v2", endpoint=redirect), Mount("/api/v2/", app=api_v2), Mount("/", app=WsgiToAsgi(flask)), ] app = Starlette(routes=routes, debug=True) flask.run_hook("asgi-setup", app) return app
async def test_wsgi_clamped_body(): """ Makes sure WsgiToAsgi clamps a body response longer than Content-Length """ def wsgi_application(environ, start_response): start_response("200 OK", [("Content-Length", "8")]) return [b"0123", b"45", b"6789"] application = WsgiToAsgi(wsgi_application) instance = ApplicationCommunicator( application, { "type": "http", "http_version": "1.0", "method": "GET", "path": "/", "query_string": b"", "headers": [], }, ) await instance.send_input({"type": "http.request"}) assert (await instance.receive_output(1)) == { "type": "http.response.start", "status": 200, "headers": [(b"content-length", b"8")], } assert (await instance.receive_output(1)) == { "type": "http.response.body", "body": b"0123", "more_body": True, } assert (await instance.receive_output(1)) == { "type": "http.response.body", "body": b"45", "more_body": True, } assert (await instance.receive_output(1)) == { "type": "http.response.body", "body": b"67", "more_body": True, } assert (await instance.receive_output(1)) == {"type": "http.response.body"}
def on_add_routes(self, route_table): db = self.app.database api = APIv1(db) # Register all views in schema for tbl in db.entity_names(schema="core_view"): if tbl.endswith("_tree"): continue api.build_route(tbl, schema="core_view") for tbl in db.entity_names(schema="lab_view"): api.build_route(tbl, schema="lab_view") self.api = api self._flask = App(self.app, __name__) self._flask.register_blueprint(api.blueprint, url_prefix="") self._flask.config["RESTFUL_JSON"] = dict(cls=JSONEncoder) route_table.append(Mount("/api/v1/", WsgiToAsgi(self._flask))) self.app.run_hook("api-v1-initialized", api)
async def test_wsgi_path_encoding(): """ Makes sure the WSGI wrapper has basic functionality. """ # Define WSGI app def wsgi_application(environ, start_response): assert environ["SCRIPT_NAME"] == "/中国".encode("utf8").decode("latin-1") assert environ["PATH_INFO"] == "/中文".encode("utf8").decode("latin-1") start_response("200 OK", []) yield b"" # Wrap it application = WsgiToAsgi(wsgi_application) # Launch it as a test application instance = ApplicationCommunicator( application, { "type": "http", "http_version": "1.0", "method": "GET", "path": "/中文", "root_path": "/中国", "query_string": b"bar=baz", "headers": [], }, ) await instance.send_input({"type": "http.request"}) # Check they send stuff assert (await instance.receive_output(1)) == { "type": "http.response.start", "status": 200, "headers": [], } assert (await instance.receive_output(1)) == { "type": "http.response.body", "body": b"", "more_body": True, } assert (await instance.receive_output(1)) == {"type": "http.response.body"}
async def test_receive_nothing(): """ Tests ApplicationCommunicator.receive_nothing to return the correct value. """ # Get an ApplicationCommunicator instance def wsgi_application(environ, start_response): start_response("200 OK", []) yield b"content" application = WsgiToAsgi(wsgi_application) instance = ApplicationCommunicator( application, { "type": "http", "http_version": "1.0", "method": "GET", "path": "/foo/", "query_string": b"bar=baz", "headers": [], }, ) # No event assert await instance.receive_nothing() is True # Produce 3 events to receive await instance.send_input({"type": "http.request"}) # Start event of the response assert await instance.receive_nothing() is False await instance.receive_output() # First body event of the response announcing further body event assert await instance.receive_nothing() is False await instance.receive_output() # Last body event of the response assert await instance.receive_nothing() is False await instance.receive_output() # Response received completely assert await instance.receive_nothing(0.01) is True
async def test_wsgi_multi_body(): """ Verify that multiple http.request events with body parts are all delivered to the WSGI application. """ def wsgi_application(environ, start_response): infp = environ["wsgi.input"] body = infp.read(12) assert body == b"Hello World!" start_response("200 OK", []) return [] application = WsgiToAsgi(wsgi_application) instance = ApplicationCommunicator( application, { "type": "http", "http_version": "1.0", "method": "POST", "path": "/", "query_string": b"", "headers": [[b"content-length", b"12"]], }, ) await instance.send_input({ "type": "http.request", "body": b"Hello ", "more_body": True }) await instance.send_input({"type": "http.request", "body": b"World!"}) assert (await instance.receive_output(1)) == { "type": "http.response.start", "status": 200, "headers": [], } assert (await instance.receive_output(1)) == {"type": "http.response.body"}
def __call__(self, scope): path = scope["path"] root_path = scope.get("root_path", "") # Call into a submounted app, if one exists. for path_prefix, app in self.apps.items(): if path.startswith(path_prefix): scope["path"] = path[len(path_prefix):] scope["root_path"] = root_path + path_prefix try: return app(scope) except TypeError: app = WsgiToAsgi(app) return app(scope) # Call the main dispatcher. async def asgi(receive, send): nonlocal scope, self req = models.Request(scope, receive=receive) resp = await self._dispatch_request(req) await resp(receive, send) return asgi
async def test_wsgi_multiple_start_response(): """ Makes sure WsgiToAsgi only keep Content-Length from the last call to start_response """ def wsgi_application(environ, start_response): start_response("200 OK", [("Content-Length", "5")]) try: raise ValueError("Application Error") except ValueError: start_response("500 Server Error", [], sys.exc_info()) return [b"Some long error message"] application = WsgiToAsgi(wsgi_application) instance = ApplicationCommunicator( application, { "type": "http", "http_version": "1.0", "method": "GET", "path": "/", "query_string": b"", "headers": [], }, ) await instance.send_input({"type": "http.request"}) assert (await instance.receive_output(1)) == { "type": "http.response.start", "status": 500, "headers": [], } assert (await instance.receive_output(1)) == { "type": "http.response.body", "body": b"Some long error message", "more_body": True, } assert (await instance.receive_output(1)) == {"type": "http.response.body"}
def padding(request): """ Dynamically generated data, maximum 50MB. """ size = min(50000000, request.path_params["size"]) return PlainTextResponse("Z" * size) @app.websocket_route("/ws") async def ws(websocket): """ WebSocket echo endpoint. """ if "chat" in websocket.scope["subprotocols"]: subprotocol = "chat" else: subprotocol = None await websocket.accept(subprotocol=subprotocol) try: while True: message = await websocket.receive_text() await websocket.send_text(message) except WebSocketDisconnect: pass app.mount("/httpbin", WsgiToAsgi(httpbin.app)) app.mount("/", StaticFiles(directory=os.path.join(ROOT, "htdocs"), html=True))
start_response(status, headers) return [body] @pytest.fixture(scope="module", autouse=True) def print_title(): print(f"\n{'Name':^30}", "Average Time", end="", flush=True) @pytest.mark.parametrize( "app, name", [ (asgi_echo, "pure-ASGI"), (WSGIMiddleware(wsgi_echo), "a2wsgi-WSGIMiddleware"), (UvicornWSGIMiddleware(wsgi_echo), "uvicorn-WSGIMiddleware"), (WsgiToAsgi(wsgi_echo), "asgiref-WsgiToAsgi"), ], ) @pytest.mark.asyncio async def test_convert_wsgi_to_asgi(app, name): async with httpx.AsyncClient(app=app, base_url="http://testserver") as client: start_time = time.time_ns() await asyncio.gather( *[client.post("/", data=b"hello world") for _ in range(100)]) time_count_100 = time.time_ns() - start_time start_time = time.time_ns() await asyncio.gather( *[client.post("/", data=b"hello world") for _ in range(10100)]) time_count_100100 = time.time_ns() - start_time print(
# 定义 WSGI 程序 def wsgi(environ, start_response): status = '200 OK' output = b'Hello WSGI in WSGI!' response_headers = [('Content-type', 'text/plain'), ('Content-Length', str(len(output)))] start_response(status, response_headers) return [output] # 将 WSGI 包装为 ASGI wsgi_to_asgi_app = WsgiToAsgi(wsgi) async def application(scope, receive, send): # 获取请求类型 request_type = scope['type'] # 如果是 http 类型的请求,则由该程序段处理 if request_type == 'http': # 如果路径以 /socket.io 开始,则使用 socket.io app 进行处理 if scope['path'].startswith("/socket.io"): return await sio_asgi_app(scope, receive, send) # 如果路径以 /wsgi 开始,则由 asgiref 将请求转交给wsgi程序处理 if scope['path'].startswith("/wsgi"): return await wsgi_to_asgi_app(scope, receive, send)
def create_asgi_app(): """ create the asgi appliaction to run the project using any asgi server like uvicorn. """ return WsgiToAsgi(create_wsgi_app())
from Statistics import app from asgiref.wsgi import WsgiToAsgi app = WsgiToAsgi(app)
return response with Configurator(settings=settings) as pyramid_config: pyramid_config.add_route("employees", "/employees") pyramid_config.add_view(employees, route_name="employees") engine = db.create_engine("sqlite:///employees.db") models.initialize_sql(engine) session_factory = get_session_factory(engine) pyramid_config.registry['dbsession_factory'] = session_factory pyramid_config.include('pyramid_tm') pyramid_config.include('pyramid_retry') pyramid_config.add_request_method( lambda r: get_tm_session(session_factory, r.tm), 'dbsession', reify=True) initialize(statsd_host=os.getenv("DATADOG_HOST"), statsd_port=8125, host_name="pyramid") tracer.configure(hostname=os.getenv("DATADOG_HOST"), port=8126, enabled=True) trace_pyramid(pyramid_config) patch(sqlalchemy=True, logging=True, sqlite3=True) wsgi_app = pyramid_config.make_wsgi_app() app = WsgiToAsgi(wsgi_app)
def on_finalize_routes(self): app = Flask(__name__) app.register_blueprint(web, url_prefix="/") self.app.mount("/", WsgiToAsgi(app))
import httpbin from asgiref.wsgi import WsgiToAsgi app = WsgiToAsgi(httpbin.app)
def __init__(self, wsgi_app) -> None: super().__init__(WsgiToAsgi(wsgi_app))
import os from asgiref.wsgi import WsgiToAsgi from asgi_middleware_static_file import ASGIMiddlewareStaticFile BASE_DIR = os.path.dirname(__name__) STATIC_DIRS = [os.path.join(BASE_DIR, "example_static")] def wsgi_app(environ, start_response): status = "200 OK" response_headers = [("Content-type", "text/plain")] start_response(status, response_headers) return ["Hello world!"] app = ASGIMiddlewareStaticFile(WsgiToAsgi(wsgi_app), static_url="static", static_root_paths=STATIC_DIRS)