Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose scope parameter in request object #2432

Merged
merged 15 commits into from Apr 26, 2022
Merged
12 changes: 12 additions & 0 deletions sanic/request.py
Expand Up @@ -14,6 +14,7 @@

from sanic_routing.route import Route # type: ignore

from sanic.models.asgi import ASGIScope
from sanic.models.http_types import Credentials


Expand Down Expand Up @@ -819,6 +820,17 @@ def url_for(self, view_name: str, **kwargs) -> str:
view_name, _external=True, _scheme=scheme, _server=netloc, **kwargs
)

@property
def scope(self) -> ASGIScope:
"""
:return: The ASGI scope of the request. If the app isn't an ASGI app, then raises an exception.
:rtype: Optional[ASGIScope]
"""
if not self.app.asgi:
raise NotImplementedError("App isn't running in ASGI mode. Scope is only available for ASGI apps.")

return self.transport.scope


class File(NamedTuple):
"""
Expand Down
26 changes: 26 additions & 0 deletions tests/test_request.py
Expand Up @@ -191,3 +191,29 @@ def test_bad_url_parse():
Mock(),
Mock(),
)


def test_request_scope_raises_exception_when_no_asgi():
app = Sanic("no_asgi")

@app.get("/")
async def get(request):
return request.scope

request, response = app.test_client.get("/")
assert response.status == 500
with pytest.raises(NotImplementedError):
_ = request.scope


@pytest.mark.asyncio
async def test_request_scope_is_not_none_when_running_in_asgi(app):
@app.get("/")
async def get(request):
return response.empty()

request, _ = await app.asgi_client.get("/")

assert request.scope is not None
assert request.scope["method"].lower() == "get"
assert request.scope["path"].lower() == "/"