-
-
Notifications
You must be signed in to change notification settings - Fork 948
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
Only stop receiving stream on body_stream
if body is empty
#1940
Conversation
Now I need to understand what's happening 🤣 |
starlette/middleware/base.py
Outdated
elif not message.get("more_body", False): | ||
break |
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.
Removing those two lines also solves the issue.
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.
I've removed them instead.
I don't know why we have the issue... It would be cool if we could find out the reason, but this change solves the issue and doesn't bring any regression. |
I don't see how this change can hurt, but I'd like to get some more input and maybe do a little post mortem on how we got here since quickly merging a "this can't hurt" PR last time is what hurt us in the end. BaseHTTMiddleware is a complex beast! |
@jhominal I would really appreciate your thoughts on this if you can take a look |
This is what I found originally ,, |
Some findings: this only happens with more than one sync dependency. That's it, no more findings. |
Ok, if we add a |
I know why we are able to see the logs after some more HTTP calls: it's because the garbage collector is acting there. |
Got it. The async def solve_generator(
*, call: Callable[..., Any], stack: AsyncExitStack, sub_values: Dict[str, Any]
) -> Any:
if is_gen_callable(call):
cm = contextmanager_in_threadpool(contextmanager(call)(**sub_values))
elif is_async_gen_callable(call):
cm = asynccontextmanager(call)(**sub_values)
return await stack.enter_async_context(cm) |
I'm tired. I'm going to write a report tomorrow morning, but the last messages show what is happening (maybe not in a clear way). |
This happens in FastAPI because they change the middleware order on the We are wrong here in breaking the receive stream. |
To test this, we can add a middleware wrapped by the I'll add this test tomorrow. (I think this makes sense... 👀) |
Thank you for digging @Kludex ! |
thanks @Kludex !! keep in mind. this behavior is not exposed in the TestClient. |
On my tests, I was going back in time to the PR that introduced, but once I used the latest Starlette I was not able to reproduce it... 👀 |
We even have a test for this behavior: starlette/tests/middleware/test_base.py Lines 266 to 325 in bf5d735
|
In any case, I'll write a report because there was a mistake. Some months ago, there was a PR (#1579) that tried to fix an issue reported in FastAPI (fastapi/fastapi#4050). I was able to reproduce that issue, but I concluded that the issue was not in the The PR introduced two changes:
I overstepped there, as the On the process of merging this PR, what we lacked on the author (me) side was to create a test for the behavior change to avoid regressions. Specifically, he needed to come up with a test case like what was created on #1715. As for the reviewers side, they thought the changes were fine based on the amount of changes, and considering that there was no drop of coverage, I think it made sense to have that consideration. What the reviewers could have done differently was to insist on a test case, maybe. We took a lot to notice this, and it's not even relevant right now because FastAPI pins each version of Starlette. Currently, latest FastAPI runs with Starlette 0.20.4, which contains the issue. The thing is, this behavior was fixed on #1715, which was released on Starlette 0.21.0. On the description of that PR, we can already see the intention of solving the case of the To conclude:
|
This is the solution for #1977. It looks like my report above is not quite precise. And it looks like we could benefit from another test case here... Ideas? |
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.
Given that we're not regressing any test cases, I think code removal without additional tests is okay.
I still want a test to cover this, but I'll merge this as is. |
This solves the issue reported by @MrSalman333 on #1609 (comment).
Test 1 (#1609 (comment))
Test 2 (#1579 (comment))