-
-
Notifications
You must be signed in to change notification settings - Fork 951
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
Document interaction of BaseHTTPMiddleware and contextvars #1525
Document interaction of BaseHTTPMiddleware and contextvars #1525
Conversation
Got into the same issue. |
Would you be able to share your concrete use case @peku33 ? As is right now this is a very "theoretical" issue, but it would help to get some actual use cases 😃 |
I am using one middleware to populate request context (contextvar) with some details and another middleware to provide logging based on that data. Data added to contextvar is only visible to "inner" middlewares, like if the context was cloned and frozen before running it. example:
the result is:
while I would rather expect it to be:
What is even funnier - it looks like the last middleware shares the context with the worker (with unicorn), because if the contextvar is set in the first (outermost) middleware - it is visible from inside of the worker. |
tests/middleware/test_base.py
Outdated
# on sync endpoints which suffers from the same problem of erasing changes | ||
# to the context |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What "same problem"? You mean the same as caused by the TaskGroup
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. Although I think this has been fixed in the meantime. Let me re-confirm.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep I think that should fix the issue. It doesn't change the rest of this PR, but we can just remove my comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah okay, no the issue is different: to_thread.run_sync()
now propagates the context _ forwards_ but not backwards:
from contextvars import ContextVar
import anyio
ctx = ContextVar[str]("ctx")
async def async_func() -> None:
assert ctx.set("bar")
def sync_func() -> None:
assert ctx.set("foo")
async def main() -> None:
await async_func()
assert ctx.get() == "bar"
await anyio.to_thread.run_sync(sync_func)
assert ctx.get() == "foo" # fails
anyio.run(main)
So there is still a subtle difference between a async and async endpoint. Side note: I think at some point before a 1.0 support for sync endpoints should be dropped, I think @tomchristie suggested this as well in the past via Gitter (Tom if you recall any of this conversation, or don't think it happened, please correct me if I am wrong).
I'm also happy to add a similar test in another PR documenting that edge case.
Co-authored-by: Marcelo Trylesinski <[email protected]>
…://github.com/adriangb/starlette into documente-basehttpmiddleware-context-behavior
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's go with this. It just adds a confirmation of the behavior we are aware.
Thanks @adriangb :) |
Using BaseHTTPMiddleware changes the behavior of the application because creating a TaskGroup erases changes to the context made within tasks spawned from the TaskGroup.
This PR is merely documenting the behavior, not necessarily proposing a fix or change.
As I understand it, the implications of this behavior were direct cause for a recent FastAPI minor version release with breaking changes (https://github.com/tiangolo/fastapi/releases/tag/0.74.0). I think it is important to at least document this behavior so that it is well understood going forward and so that we can know if it changes.
That said, one possible fix, if we decide we want to "fix" this, would be something along the lines of #1258