This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
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
How to set request headers before path operation is executed #2727
Comments
In Starlette But fortunately we can monkey-patch everything in Python. You can create your own router like this, also you can do the same thing with a middleware, but i like this approach more. from fastapi import APIRouter, FastAPI, Request, Response
from fastapi.routing import APIRoute
from typing import Callable, Tuple
from uuid import uuid4
class ContextIncludedRoute(APIRoute):
def get_route_handler(self) -> Callable:
original_route_handler = super().get_route_handler()
async def custom_route_handler(request: Request) -> Response:
id_header: Tuple[bytes] = "x-request-id".encode(), str(uuid4()).encode()
request.headers.__dict__["_list"].append(id_header)
response: Response = await original_route_handler(request)
return response
return custom_route_handler
app = FastAPI()
router = APIRouter(route_class=ContextIncludedRoute)
@router.post("/dummy")
async def dummy(request: Request):
return request.headers["x-request-id"]
app.include_router(router) |
Very nice @ycd This is shown in the docs here: https://fastapi.tiangolo.com/advanced/custom-request-and-route/ |
Thanks @ycd. Like this approach. Is there a way where we can use a similar approach with a middleware |
from fastapi import FastAPI
app = FastAPI()
class Middleware:
def __init__(self, app):
self.app = app
async def __call__(self, scope, receive, send):
assert scope["type"] == "http"
headers = dict(scope["headers"])
headers[b"x-request-id"] = b'1' # generate the way you want
scope["headers"] = [(k, v) for k, v in headers.items()]
await self.app(scope, receive, send)
app.add_middleware(Middleware)
@app.get("/")
def home():
return "Hello World!" Check also: https://pypi.org/project/starlette-context/ |
Thanks @Kludex . This is also an awesome solution. Was trying to the do the same but was missing |
Another way is to set headers using the https://fastapi.tiangolo.com/tutorial/middleware/ @app.middleware("http")
async def create_auth_header(
request: Request,
call_next,
):
"""
Check if there are cookies set for authorization. If so, construct the
Authorization header and modify the request (unless the header already
exists!)
"""
if (
"Authorization" not in request.headers
and "access_token_payload" in request.cookies
and "access_token_signature" in request.cookies
):
access_token_payload = request.cookies["access_token_payload"]
access_token_signature = request.cookies["access_token_signature"]
access_token = f"{access_token_payload}.{access_token_signature}"
request.headers.__dict__["_list"].append(
(
"authorization".encode(),
f"Bearer {access_token}".encode(),
)
)
response = await call_next(request)
return response Edit: It's really important for the header key to be lower case when encoding like above (so use |
I cannot say for all suggestions but I am pretty sure that at least some approaches are
Suggestion: # REPLACE:
# request.headers.__dict__["_list"].append(
# (
# "authorization".encode(),
# f"Bearer {access_token}".encode(),
# )
# )
new_headers = request.headers.mutablecopy()
new_headers.append(
"authorization".encode(),
f"Bearer {access_token}".encode()
)
request._headers = new_headers # solves first point
request.scope.update(headers=request.headers.raw) # solves second point
I am pretty sure that the proposals of @mnahinkhan and @ycd are missing both points. |
This isn't working @Magnati. I recommend #3027 (comment) |
Thanks for the help here everyone! ☕ If that solves your use case, you can close the issue @satishdash 🍰 |
Solved! |
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
First check
Example
Description
Tried implementing call in a class whose init method takes scope, receive and send params
tried mutating scope ['headers'] adding additional key, value pairs utf8 encoded but the request object in the path operation still doesn't have those headers.
Invoking api through test client invokes the middleware but the headers that are mutated still isn't visible in the request object received by the path operation.
@tiangolo suggested in one of the issues to create a new request object but have no idea how to do it.
Environment
To know the FastAPI version use:
python -c "import fastapi; print(fastapi.__version__)"
To know the Python version use:
Additional comments
Can anybody please suggest or recommend it's important.
The text was updated successfully, but these errors were encountered: