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

request body get empty when using middleware to save request to contextvar #2669

Open
LoadingZhang opened this issue Aug 13, 2024 · 3 comments

Comments

@LoadingZhang
Copy link

LoadingZhang commented Aug 13, 2024

I want to save request to ContextVar so I can use it anywhere. Here is code sample:

from contextvars import ContextVar

import uvicorn
from fastapi import FastAPI
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.requests import Request

ctx: ContextVar[Request] = ContextVar("request")
app = FastAPI()


class RequestContextMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request: Request, call_next):
        token = ctx.set(request)
        try:
            response = await call_next(request)
        finally:
            ctx.reset(token)
        return response

app.add_middleware(RequestContextMiddleware)

async def root(request: Request, body: str):
    print(1, request._stream_consumed)
    print(2, request._body)
    ctx_request = ctx.get()
    print(3, ctx_request._body)


app.add_api_route("/", root, methods=["POST"])

if __name__ == '__main__':
    uvicorn.run(app)

Output:

1 True
2 "the request data"
...
    print(ctx_request._body)
          ^^^^^^^^^^^^^^^^^
AttributeError: '_CachedRequest' object has no attribute '_body'. Did you mean: 'body'?

so, my question is

  • Why middleware will read body?
  • Why the ctx_request._body get empty, but the request._body in param is worked
@adriangb
Copy link
Member

I'm not sure I understood your question / problem but _body is a private attribute that you should not be accessing or interacting with. Maybe try await request.body()?

@LoadingZhang LoadingZhang changed the title request._body get empty when using middleware to save request to contextvar request body get empty when using middleware to save request to contextvar Aug 13, 2024
@LoadingZhang
Copy link
Author

LoadingZhang commented Aug 13, 2024

I'm not sure I understood your question / problem but _body is a private attribute that you should not be accessing or interacting with. Maybe try await request.body()?

@adriangb I used await request.body() before, but it raised an error:

raise RuntimeError("Stream consumed")
RuntimeError: Stream consumed

After investigation, I found out that _body was missing and _stream_consumed is True after middleware processed.

@LoadingZhang
Copy link
Author

And I discovered similar topic in the discussion, which might be related.
#2556

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants