...
```
+When redirecting users, the page you redirect them to will include URL they originally requested at the `next` query param:
+
+```python
+from starlette.authentication import requires
+from starlette.responses import RedirectResponse
+
+
+@requires('authenticated', redirect='login')
+async def admin(request):
+ ...
+
+
+async def login(request):
+ if request.method == "POST":
+ # Now that the user is authenticated,
+ # we can send them to their original request destination
+ if request.user.is_authenticated:
+ next_url = request.query_params.get("next")
+ if next_url:
+ return RedirectResponse(next_url)
+ return RedirectResponse("/")
+```
+
For class-based endpoints, you should wrap the decorator
around a method on the class.
import functools
import inspect
import typing
+from urllib.parse import urlencode
from starlette.exceptions import HTTPException
from starlette.requests import HTTPConnection, Request
if not has_required_scope(request, scopes_list):
if redirect is not None:
- return RedirectResponse(
- url=request.url_for(redirect), status_code=303
+ orig_request_qparam = urlencode({"next": str(request.url)})
+ next_url = "{redirect_path}?{orig_request}".format(
+ redirect_path=request.url_for(redirect),
+ orig_request=orig_request_qparam,
)
+ return RedirectResponse(url=next_url, status_code=303)
raise HTTPException(status_code=status_code)
return await func(*args, **kwargs)
if not has_required_scope(request, scopes_list):
if redirect is not None:
- return RedirectResponse(
- url=request.url_for(redirect), status_code=303
+ orig_request_qparam = urlencode({"next": str(request.url)})
+ next_url = "{redirect_path}?{orig_request}".format(
+ redirect_path=request.url_for(redirect),
+ orig_request=orig_request_qparam,
)
+ return RedirectResponse(url=next_url, status_code=303)
raise HTTPException(status_code=status_code)
return func(*args, **kwargs)
import base64
import binascii
+from urllib.parse import urlencode
import pytest
with test_client_factory(app) as client:
response = client.get("/admin")
assert response.status_code == 200
- assert response.url == "http://testserver/"
+ url = "{}?{}".format(
+ "http://testserver/", urlencode({"next": "http://testserver/admin"})
+ )
+ assert response.url == url
response = client.get("/admin", auth=("tomchristie", "example"))
assert response.status_code == 200
response = client.get("/admin/sync")
assert response.status_code == 200
- assert response.url == "http://testserver/"
+ url = "{}?{}".format(
+ "http://testserver/", urlencode({"next": "http://testserver/admin/sync"})
+ )
+ assert response.url == url
response = client.get("/admin/sync", auth=("tomchristie", "example"))
assert response.status_code == 200