diff --git a/tests/protocols/test_http.py b/tests/protocols/test_http.py index 3900e3be6..891a259f2 100644 --- a/tests/protocols/test_http.py +++ b/tests/protocols/test_http.py @@ -674,3 +674,29 @@ def test_supported_upgrade_request(protocol_cls): protocol.data_received(UPGRADE_REQUEST) assert b"HTTP/1.1 426 " in protocol.transport.buffer + + +async def asgi3app(scope, receive, send): + pass + + +def asgi2app(scope): + async def asgi(receive, send): + pass + + return asgi + + +asgi_scope_data = [ + (asgi3app, {"version": "3.0", "spec_version": "2.1"}), + (asgi2app, {"version": "2.0", "spec_version": "2.1"}), +] + + +@pytest.mark.parametrize("asgi2or3_app, expected_scopes", asgi_scope_data) +@pytest.mark.parametrize("protocol_cls", HTTP_PROTOCOLS) +def test_scopes(asgi2or3_app, expected_scopes, protocol_cls): + protocol = get_connected_protocol(asgi2or3_app, protocol_cls,) + protocol.data_received(SIMPLE_GET_REQUEST) + protocol.loop.run_one() + assert expected_scopes == protocol.scope.get("asgi") diff --git a/tests/test_config.py b/tests/test_config.py index 1f3d34e87..c1f763b41 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -66,3 +66,19 @@ def test_ssl_config(certfile_and_keyfile): config.load() assert config.is_ssl is True + + +def asgi2_app(scope): + async def asgi(receive, send): + pass + + return asgi + + +@pytest.mark.parametrize( + "app, expected_interface", [(asgi_app, "3.0",), (asgi2_app, "2.0",)] +) +def test_asgi_version(app, expected_interface): + config = Config(app=app) + config.load() + assert config.asgi_version == expected_interface diff --git a/uvicorn/config.py b/uvicorn/config.py index 331f73842..c35b567bd 100644 --- a/uvicorn/config.py +++ b/uvicorn/config.py @@ -200,6 +200,10 @@ def __init__( else: self.forwarded_allow_ips = forwarded_allow_ips + @property + def asgi_version(self) -> str: + return {"asgi2": "2.0", "asgi3": "3.0"}[self.interface] + @property def is_ssl(self) -> bool: return bool(self.ssl_keyfile or self.ssl_certfile) diff --git a/uvicorn/protocols/http/h11_impl.py b/uvicorn/protocols/http/h11_impl.py index a1d87ebd7..5e15d0512 100644 --- a/uvicorn/protocols/http/h11_impl.py +++ b/uvicorn/protocols/http/h11_impl.py @@ -188,6 +188,10 @@ def handle_events(self): raw_path, _, query_string = event.target.partition(b"?") self.scope = { "type": "http", + "asgi": { + "version": self.config.asgi_version, + "spec_version": "2.1", + }, "http_version": event.http_version.decode("ascii"), "server": self.server, "client": self.client, diff --git a/uvicorn/protocols/http/httptools_impl.py b/uvicorn/protocols/http/httptools_impl.py index 6e53131f9..7a60733ce 100644 --- a/uvicorn/protocols/http/httptools_impl.py +++ b/uvicorn/protocols/http/httptools_impl.py @@ -214,6 +214,7 @@ def on_url(self, url): self.headers = [] self.scope = { "type": "http", + "asgi": {"version": self.config.asgi_version, "spec_version": "2.1"}, "http_version": "1.1", "server": self.server, "client": self.client, diff --git a/uvicorn/protocols/websockets/websockets_impl.py b/uvicorn/protocols/websockets/websockets_impl.py index 53f2d4245..37e2cb784 100644 --- a/uvicorn/protocols/websockets/websockets_impl.py +++ b/uvicorn/protocols/websockets/websockets_impl.py @@ -100,6 +100,7 @@ async def process_request(self, path, headers): self.scope = { "type": "websocket", + "asgi": {"version": self.config.asgi_version, "spec_version": "2.1"}, "scheme": self.scheme, "server": self.server, "client": self.client, diff --git a/uvicorn/protocols/websockets/wsproto_impl.py b/uvicorn/protocols/websockets/wsproto_impl.py index 5081c873a..307ab9f29 100644 --- a/uvicorn/protocols/websockets/wsproto_impl.py +++ b/uvicorn/protocols/websockets/wsproto_impl.py @@ -128,6 +128,7 @@ def handle_connect(self, event): raw_path, _, query_string = event.target.partition("?") self.scope = { "type": "websocket", + "asgi": {"version": self.config.asgi_version, "spec_version": "2.1"}, "http_version": "1.1", "scheme": self.scheme, "server": self.server,