Only stop receiving stream on body_stream if body is empty#1940
Only stop receiving stream on body_stream if body is empty#1940
body_stream if body is empty#1940Conversation
|
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.
Removing those two lines also solves the issue.
|
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: |
|
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? |
lovelydinosaur
left a comment
There was a problem hiding this comment.
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))