We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
test_custom_middleware[trio] fails on 1-core-VM
### Checklist

<!-- Please make sure you check all these items before submitting your bug report. -->

- [X] The bug is reproducible against the latest release and/or `master`.
- [ ] There are no similar issues or pull requests to fix it yet.

### Describe the bug

While working on [reproducible builds](https://reproducible-builds.org/) for [openSUSE](https://en.opensuse.org/openSUSE:Reproducible_Builds), I found that our `python-starlette-0.16.0` package failed 1 test when running in a 1-core-VM (usually this happens due to differences in scheduling/timing)



### To reproduce

maybe run tests as `taskset 1 pytest`

or on Debian or openSUSE run
```
osc checkout openSUSE:Factory/python-starlette && cd $_
osc build --vm-type=kvm --noservice --clean -j1 standard
```

<!-- Provide a *minimal* example with steps to reproduce the bug locally.

NOTE: try to keep any external dependencies *at an absolute minimum*
(middleware, servers, proxies, certificates...).
In other words, remove anything that doesn't make the bug go away.
-->

### Expected behavior

<!-- A clear and concise description of what you expected to happen. -->
tests should pass

### Actual behavior

`test_custom_middleware[trio]` fails

<!-- A clear and concise description of what actually happens. -->

### Debugging material

```
 =================================== FAILURES ===================================
 _________________________ test_custom_middleware[trio] _________________________
 
 test_client_factory = functools.partial(<class 'starlette.testclient.TestClient'>, backend='trio', backend_options={})
 
     def test_custom_middleware(test_client_factory):
         client = test_client_factory(app)
         response = client.get("/")
         assert response.headers["Custom-Header"] == "Example"
     
         with pytest.raises(Exception):
 >           response = client.get("/exc")
 
 tests/middleware/test_base.py:56: 
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
 /usr/lib/python3.9/site-packages/requests/sessions.py:555: in get
     return self.request('GET', url, **kwargs)
 starlette/testclient.py:468: in request
     return super().request(
 /usr/lib/python3.9/site-packages/requests/sessions.py:542: in request
     resp = self.send(prep, **send_kwargs)
 /usr/lib/python3.9/site-packages/requests/sessions.py:655: in send
     r = adapter.send(request, **kwargs)
 starlette/testclient.py:266: in send
     raise exc
 starlette/testclient.py:263: in send
     portal.call(self.app, scope, receive, send)
 /usr/lib/python3.9/site-packages/anyio/from_thread.py:229: in call
     return self.start_task_soon(func, *args).result()
 /usr/lib64/python3.9/concurrent/futures/_base.py:445: in result
     return self.__get_result()
 /usr/lib64/python3.9/concurrent/futures/_base.py:390: in __get_result
     raise self._exception
 /usr/lib/python3.9/site-packages/anyio/from_thread.py:176: in _call_func
     retval = await retval
 starlette/applications.py:112: in __call__
     await self.middleware_stack(scope, receive, send)
 starlette/middleware/errors.py:159: in __call__
     await self.app(scope, receive, _send)
 starlette/middleware/base.py:57: in __call__
     task_group.cancel_scope.cancel()
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
 
 self = <anyio._backends._trio.TaskGroup object at 0x7f1d7c50a5b0>
 exc_type = <class 'RuntimeError'>
 exc_val = RuntimeError('No response returned.')
 exc_tb = <traceback object at 0x7f1d7c5294c0>
 
     async def __aexit__(self, exc_type: Optional[Type[BaseException]],
                         exc_val: Optional[BaseException],
                         exc_tb: Optional[TracebackType]) -> Optional[bool]:
         try:
             return await self._nursery_manager.__aexit__(exc_type, exc_val, exc_tb)
         except trio.MultiError as exc:
 >           raise ExceptionGroup(exc.exceptions) from None
 E           anyio._backends._trio.ExceptionGroup: 2 exceptions were raised in the task group:
 E           ----------------------------
 E           Traceback (most recent call last):
 E             File "/home/abuild/rpmbuild/BUILD/starlette-0.16.0/starlette/middleware/base.py", line 30, in coro
 E               await self.app(scope, request.receive, send_stream.send)
 E             File "/home/abuild/rpmbuild/BUILD/starlette-0.16.0/starlette/exceptions.py", line 82, in __call__
 E               raise exc
 E             File "/home/abuild/rpmbuild/BUILD/starlette-0.16.0/starlette/exceptions.py", line 71, in __call__
 E               await self.app(scope, receive, sender)
 E             File "/home/abuild/rpmbuild/BUILD/starlette-0.16.0/starlette/routing.py", line 656, in __call__
 E               await route.handle(scope, receive, send)
 E             File "/home/abuild/rpmbuild/BUILD/starlette-0.16.0/starlette/routing.py", line 259, in handle
 E               await self.app(scope, receive, send)
 E             File "/home/abuild/rpmbuild/BUILD/starlette-0.16.0/starlette/routing.py", line 63, in app
 E               response = await run_in_threadpool(func, request)
 E             File "/home/abuild/rpmbuild/BUILD/starlette-0.16.0/starlette/concurrency.py", line 39, in run_in_threadpool
 E               return await anyio.to_thread.run_sync(func, *args)
 E             File "/usr/lib/python3.9/site-packages/anyio/to_thread.py", line 28, in run_sync
 E               return await get_asynclib().run_sync_in_worker_thread(func, *args, cancellable=cancellable,
 E             File "/usr/lib/python3.9/site-packages/anyio/_backends/_trio.py", line 170, in run_sync_in_worker_thread
 E               return await run_sync(wrapper, cancellable=cancellable, limiter=limiter)
 E             File "/usr/lib/python3.9/site-packages/trio/_threads.py", line 205, in to_thread_run_sync
 E               return await trio.lowlevel.wait_task_rescheduled(abort)
 E             File "/usr/lib/python3.9/site-packages/trio/_core/_traps.py", line 166, in wait_task_rescheduled
 E               return (await _async_yield(WaitTaskRescheduled(abort_func))).unwrap()
 E             File "/usr/lib/python3.9/site-packages/outcome/_sync.py", line 111, in unwrap
 E               raise captured_error
 E             File "/usr/lib/python3.9/site-packages/trio/_threads.py", line 155, in do_release_then_return_result
 E               return result.unwrap()
 E             File "/usr/lib/python3.9/site-packages/outcome/_sync.py", line 111, in unwrap
 E               raise captured_error
 E             File "/usr/lib/python3.9/site-packages/trio/_threads.py", line 168, in worker_fn
 E               ret = sync_fn(*args)
 E             File "/usr/lib/python3.9/site-packages/anyio/_backends/_trio.py", line 168, in wrapper
 E               return func(*args)
 E             File "/home/abuild/rpmbuild/BUILD/starlette-0.16.0/tests/middleware/test_base.py", line 28, in exc
 E               raise Exception()
 E           Exception
 E           ----------------------------
 E           Traceback (most recent call last):
 E             File "/usr/lib/python3.9/site-packages/anyio/streams/memory.py", line 78, in receive
 E               return self.receive_nowait()
 E             File "/usr/lib/python3.9/site-packages/anyio/streams/memory.py", line 73, in receive_nowait
 E               raise WouldBlock
 E           anyio.WouldBlock
 E           
 E           During handling of the above exception, another exception occurred:
 E           
 E           Traceback (most recent call last):
 E             File "/home/abuild/rpmbuild/BUILD/starlette-0.16.0/starlette/middleware/base.py", line 35, in call_next
 E               message = await recv_stream.receive()
 E             File "/usr/lib/python3.9/site-packages/anyio/streams/memory.py", line 98, in receive
 E               raise EndOfStream
 E           anyio.EndOfStream
 E           
 E           During handling of the above exception, another exception occurred:
 E           
 E           Traceback (most recent call last):
 E             File "/home/abuild/rpmbuild/BUILD/starlette-0.16.0/starlette/middleware/base.py", line 55, in __call__
 E               response = await self.dispatch_func(request, call_next)
 E             File "/home/abuild/rpmbuild/BUILD/starlette-0.16.0/tests/middleware/test_base.py", line 12, in dispatch
 E               response = await call_next(request)
 E             File "/home/abuild/rpmbuild/BUILD/starlette-0.16.0/starlette/middleware/base.py", line 37, in call_next
 E               raise RuntimeError("No response returned.")
 E           RuntimeError: No response returned.
 
 /usr/lib/python3.9/site-packages/anyio/_backends/_trio.py:141: ExceptionGroup
 =========================== short test summary info ============================
 SKIPPED [3] tests/conftest.py:14: Trio not supported (yet!)
 =================== 1 failed, 464 passed, 3 skipped in 4.95s ===================
```

<!-- Any tracebacks, screenshots, etc. that can help understanding the problem.

NOTE:
- Please list tracebacks in full (don't truncate them).
- Consider using `<details>` to make tracebacks/logs collapsible if they're very large (see https://gist.github.com/ericclemmons/b146fe5da72ca1f706b2ef72a20ac39d).
-->

### Environment

- OS: Linux = openSUSE Tumbleweed 20210726 
- Python version: 3.9
- Starlette version: 0.16.0

### Additional context

This bug was found while working on [reproducible builds for openSUSE](https://en.opensuse.org/openSUSE:Reproducible_Builds).

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `starlette/middleware/base.py`
Content:
```
1 import typing
2 
3 import anyio
4 
5 from starlette.requests import Request
6 from starlette.responses import Response, StreamingResponse
7 from starlette.types import ASGIApp, Receive, Scope, Send
8 
9 RequestResponseEndpoint = typing.Callable[[Request], typing.Awaitable[Response]]
10 DispatchFunction = typing.Callable[
11     [Request, RequestResponseEndpoint], typing.Awaitable[Response]
12 ]
13 
14 
15 class BaseHTTPMiddleware:
16     def __init__(self, app: ASGIApp, dispatch: DispatchFunction = None) -> None:
17         self.app = app
18         self.dispatch_func = self.dispatch if dispatch is None else dispatch
19 
20     async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
21         if scope["type"] != "http":
22             await self.app(scope, receive, send)
23             return
24 
25         async def call_next(request: Request) -> Response:
26             send_stream, recv_stream = anyio.create_memory_object_stream()
27 
28             async def coro() -> None:
29                 async with send_stream:
30                     await self.app(scope, request.receive, send_stream.send)
31 
32             task_group.start_soon(coro)
33 
34             try:
35                 message = await recv_stream.receive()
36             except anyio.EndOfStream:
37                 raise RuntimeError("No response returned.")
38 
39             assert message["type"] == "http.response.start"
40 
41             async def body_stream() -> typing.AsyncGenerator[bytes, None]:
42                 async with recv_stream:
43                     async for message in recv_stream:
44                         assert message["type"] == "http.response.body"
45                         yield message.get("body", b"")
46 
47             response = StreamingResponse(
48                 status_code=message["status"], content=body_stream()
49             )
50             response.raw_headers = message["headers"]
51             return response
52 
53         async with anyio.create_task_group() as task_group:
54             request = Request(scope, receive=receive)
55             response = await self.dispatch_func(request, call_next)
56             await response(scope, receive, send)
57             task_group.cancel_scope.cancel()
58 
59     async def dispatch(
60         self, request: Request, call_next: RequestResponseEndpoint
61     ) -> Response:
62         raise NotImplementedError()  # pragma: no cover
63
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/starlette/middleware/base.py b/starlette/middleware/base.py
--- a/starlette/middleware/base.py
+++ b/starlette/middleware/base.py
@@ -23,17 +23,25 @@
             return
 
         async def call_next(request: Request) -> Response:
+            app_exc: typing.Optional[Exception] = None
             send_stream, recv_stream = anyio.create_memory_object_stream()
 
             async def coro() -> None:
+                nonlocal app_exc
+
                 async with send_stream:
-                    await self.app(scope, request.receive, send_stream.send)
+                    try:
+                        await self.app(scope, request.receive, send_stream.send)
+                    except Exception as exc:
+                        app_exc = exc
 
             task_group.start_soon(coro)
 
             try:
                 message = await recv_stream.receive()
             except anyio.EndOfStream:
+                if app_exc is not None:
+                    raise app_exc
                 raise RuntimeError("No response returned.")
 
             assert message["type"] == "http.response.start"

{"golden_diff": "diff --git a/starlette/middleware/base.py b/starlette/middleware/base.py\n--- a/starlette/middleware/base.py\n+++ b/starlette/middleware/base.py\n@@ -23,17 +23,25 @@\n             return\n \n         async def call_next(request: Request) -> Response:\n+            app_exc: typing.Optional[Exception] = None\n             send_stream, recv_stream = anyio.create_memory_object_stream()\n \n             async def coro() -> None:\n+                nonlocal app_exc\n+\n                 async with send_stream:\n-                    await self.app(scope, request.receive, send_stream.send)\n+                    try:\n+                        await self.app(scope, request.receive, send_stream.send)\n+                    except Exception as exc:\n+                        app_exc = exc\n \n             task_group.start_soon(coro)\n \n             try:\n                 message = await recv_stream.receive()\n             except anyio.EndOfStream:\n+                if app_exc is not None:\n+                    raise app_exc\n                 raise RuntimeError(\"No response returned.\")\n \n             assert message[\"type\"] == \"http.response.start\"\n", "issue": "test_custom_middleware[trio] fails on 1-core-VM\n### Checklist\r\n\r\n<!-- Please make sure you check all these items before submitting your bug report. -->\r\n\r\n- [X] The bug is reproducible against the latest release and/or `master`.\r\n- [ ] There are no similar issues or pull requests to fix it yet.\r\n\r\n### Describe the bug\r\n\r\nWhile working on [reproducible builds](https://reproducible-builds.org/) for [openSUSE](https://en.opensuse.org/openSUSE:Reproducible_Builds), I found that our `python-starlette-0.16.0` package failed 1 test when running in a 1-core-VM (usually this happens due to differences in scheduling/timing)\r\n\r\n\r\n\r\n### To reproduce\r\n\r\nmaybe run tests as `taskset 1 pytest`\r\n\r\nor on Debian or openSUSE run\r\n```\r\nosc checkout openSUSE:Factory/python-starlette && cd $_\r\nosc build --vm-type=kvm --noservice --clean -j1 standard\r\n```\r\n\r\n<!-- Provide a *minimal* example with steps to reproduce the bug locally.\r\n\r\nNOTE: try to keep any external dependencies *at an absolute minimum*\r\n(middleware, servers, proxies, certificates...).\r\nIn other words, remove anything that doesn't make the bug go away.\r\n-->\r\n\r\n### Expected behavior\r\n\r\n<!-- A clear and concise description of what you expected to happen. -->\r\ntests should pass\r\n\r\n### Actual behavior\r\n\r\n`test_custom_middleware[trio]` fails\r\n\r\n<!-- A clear and concise description of what actually happens. -->\r\n\r\n### Debugging material\r\n\r\n```\r\n =================================== FAILURES ===================================\r\n _________________________ test_custom_middleware[trio] _________________________\r\n \r\n test_client_factory = functools.partial(<class 'starlette.testclient.TestClient'>, backend='trio', backend_options={})\r\n \r\n     def test_custom_middleware(test_client_factory):\r\n         client = test_client_factory(app)\r\n         response = client.get(\"/\")\r\n         assert response.headers[\"Custom-Header\"] == \"Example\"\r\n     \r\n         with pytest.raises(Exception):\r\n >           response = client.get(\"/exc\")\r\n \r\n tests/middleware/test_base.py:56: \r\n _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \r\n /usr/lib/python3.9/site-packages/requests/sessions.py:555: in get\r\n     return self.request('GET', url, **kwargs)\r\n starlette/testclient.py:468: in request\r\n     return super().request(\r\n /usr/lib/python3.9/site-packages/requests/sessions.py:542: in request\r\n     resp = self.send(prep, **send_kwargs)\r\n /usr/lib/python3.9/site-packages/requests/sessions.py:655: in send\r\n     r = adapter.send(request, **kwargs)\r\n starlette/testclient.py:266: in send\r\n     raise exc\r\n starlette/testclient.py:263: in send\r\n     portal.call(self.app, scope, receive, send)\r\n /usr/lib/python3.9/site-packages/anyio/from_thread.py:229: in call\r\n     return self.start_task_soon(func, *args).result()\r\n /usr/lib64/python3.9/concurrent/futures/_base.py:445: in result\r\n     return self.__get_result()\r\n /usr/lib64/python3.9/concurrent/futures/_base.py:390: in __get_result\r\n     raise self._exception\r\n /usr/lib/python3.9/site-packages/anyio/from_thread.py:176: in _call_func\r\n     retval = await retval\r\n starlette/applications.py:112: in __call__\r\n     await self.middleware_stack(scope, receive, send)\r\n starlette/middleware/errors.py:159: in __call__\r\n     await self.app(scope, receive, _send)\r\n starlette/middleware/base.py:57: in __call__\r\n     task_group.cancel_scope.cancel()\r\n _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \r\n \r\n self = <anyio._backends._trio.TaskGroup object at 0x7f1d7c50a5b0>\r\n exc_type = <class 'RuntimeError'>\r\n exc_val = RuntimeError('No response returned.')\r\n exc_tb = <traceback object at 0x7f1d7c5294c0>\r\n \r\n     async def __aexit__(self, exc_type: Optional[Type[BaseException]],\r\n                         exc_val: Optional[BaseException],\r\n                         exc_tb: Optional[TracebackType]) -> Optional[bool]:\r\n         try:\r\n             return await self._nursery_manager.__aexit__(exc_type, exc_val, exc_tb)\r\n         except trio.MultiError as exc:\r\n >           raise ExceptionGroup(exc.exceptions) from None\r\n E           anyio._backends._trio.ExceptionGroup: 2 exceptions were raised in the task group:\r\n E           ----------------------------\r\n E           Traceback (most recent call last):\r\n E             File \"/home/abuild/rpmbuild/BUILD/starlette-0.16.0/starlette/middleware/base.py\", line 30, in coro\r\n E               await self.app(scope, request.receive, send_stream.send)\r\n E             File \"/home/abuild/rpmbuild/BUILD/starlette-0.16.0/starlette/exceptions.py\", line 82, in __call__\r\n E               raise exc\r\n E             File \"/home/abuild/rpmbuild/BUILD/starlette-0.16.0/starlette/exceptions.py\", line 71, in __call__\r\n E               await self.app(scope, receive, sender)\r\n E             File \"/home/abuild/rpmbuild/BUILD/starlette-0.16.0/starlette/routing.py\", line 656, in __call__\r\n E               await route.handle(scope, receive, send)\r\n E             File \"/home/abuild/rpmbuild/BUILD/starlette-0.16.0/starlette/routing.py\", line 259, in handle\r\n E               await self.app(scope, receive, send)\r\n E             File \"/home/abuild/rpmbuild/BUILD/starlette-0.16.0/starlette/routing.py\", line 63, in app\r\n E               response = await run_in_threadpool(func, request)\r\n E             File \"/home/abuild/rpmbuild/BUILD/starlette-0.16.0/starlette/concurrency.py\", line 39, in run_in_threadpool\r\n E               return await anyio.to_thread.run_sync(func, *args)\r\n E             File \"/usr/lib/python3.9/site-packages/anyio/to_thread.py\", line 28, in run_sync\r\n E               return await get_asynclib().run_sync_in_worker_thread(func, *args, cancellable=cancellable,\r\n E             File \"/usr/lib/python3.9/site-packages/anyio/_backends/_trio.py\", line 170, in run_sync_in_worker_thread\r\n E               return await run_sync(wrapper, cancellable=cancellable, limiter=limiter)\r\n E             File \"/usr/lib/python3.9/site-packages/trio/_threads.py\", line 205, in to_thread_run_sync\r\n E               return await trio.lowlevel.wait_task_rescheduled(abort)\r\n E             File \"/usr/lib/python3.9/site-packages/trio/_core/_traps.py\", line 166, in wait_task_rescheduled\r\n E               return (await _async_yield(WaitTaskRescheduled(abort_func))).unwrap()\r\n E             File \"/usr/lib/python3.9/site-packages/outcome/_sync.py\", line 111, in unwrap\r\n E               raise captured_error\r\n E             File \"/usr/lib/python3.9/site-packages/trio/_threads.py\", line 155, in do_release_then_return_result\r\n E               return result.unwrap()\r\n E             File \"/usr/lib/python3.9/site-packages/outcome/_sync.py\", line 111, in unwrap\r\n E               raise captured_error\r\n E             File \"/usr/lib/python3.9/site-packages/trio/_threads.py\", line 168, in worker_fn\r\n E               ret = sync_fn(*args)\r\n E             File \"/usr/lib/python3.9/site-packages/anyio/_backends/_trio.py\", line 168, in wrapper\r\n E               return func(*args)\r\n E             File \"/home/abuild/rpmbuild/BUILD/starlette-0.16.0/tests/middleware/test_base.py\", line 28, in exc\r\n E               raise Exception()\r\n E           Exception\r\n E           ----------------------------\r\n E           Traceback (most recent call last):\r\n E             File \"/usr/lib/python3.9/site-packages/anyio/streams/memory.py\", line 78, in receive\r\n E               return self.receive_nowait()\r\n E             File \"/usr/lib/python3.9/site-packages/anyio/streams/memory.py\", line 73, in receive_nowait\r\n E               raise WouldBlock\r\n E           anyio.WouldBlock\r\n E           \r\n E           During handling of the above exception, another exception occurred:\r\n E           \r\n E           Traceback (most recent call last):\r\n E             File \"/home/abuild/rpmbuild/BUILD/starlette-0.16.0/starlette/middleware/base.py\", line 35, in call_next\r\n E               message = await recv_stream.receive()\r\n E             File \"/usr/lib/python3.9/site-packages/anyio/streams/memory.py\", line 98, in receive\r\n E               raise EndOfStream\r\n E           anyio.EndOfStream\r\n E           \r\n E           During handling of the above exception, another exception occurred:\r\n E           \r\n E           Traceback (most recent call last):\r\n E             File \"/home/abuild/rpmbuild/BUILD/starlette-0.16.0/starlette/middleware/base.py\", line 55, in __call__\r\n E               response = await self.dispatch_func(request, call_next)\r\n E             File \"/home/abuild/rpmbuild/BUILD/starlette-0.16.0/tests/middleware/test_base.py\", line 12, in dispatch\r\n E               response = await call_next(request)\r\n E             File \"/home/abuild/rpmbuild/BUILD/starlette-0.16.0/starlette/middleware/base.py\", line 37, in call_next\r\n E               raise RuntimeError(\"No response returned.\")\r\n E           RuntimeError: No response returned.\r\n \r\n /usr/lib/python3.9/site-packages/anyio/_backends/_trio.py:141: ExceptionGroup\r\n =========================== short test summary info ============================\r\n SKIPPED [3] tests/conftest.py:14: Trio not supported (yet!)\r\n =================== 1 failed, 464 passed, 3 skipped in 4.95s ===================\r\n```\r\n\r\n<!-- Any tracebacks, screenshots, etc. that can help understanding the problem.\r\n\r\nNOTE:\r\n- Please list tracebacks in full (don't truncate them).\r\n- Consider using `<details>` to make tracebacks/logs collapsible if they're very large (see https://gist.github.com/ericclemmons/b146fe5da72ca1f706b2ef72a20ac39d).\r\n-->\r\n\r\n### Environment\r\n\r\n- OS: Linux = openSUSE Tumbleweed 20210726 \r\n- Python version: 3.9\r\n- Starlette version: 0.16.0\r\n\r\n### Additional context\r\n\r\nThis bug was found while working on [reproducible builds for openSUSE](https://en.opensuse.org/openSUSE:Reproducible_Builds).\n", "before_files": [{"content": "import typing\n\nimport anyio\n\nfrom starlette.requests import Request\nfrom starlette.responses import Response, StreamingResponse\nfrom starlette.types import ASGIApp, Receive, Scope, Send\n\nRequestResponseEndpoint = typing.Callable[[Request], typing.Awaitable[Response]]\nDispatchFunction = typing.Callable[\n    [Request, RequestResponseEndpoint], typing.Awaitable[Response]\n]\n\n\nclass BaseHTTPMiddleware:\n    def __init__(self, app: ASGIApp, dispatch: DispatchFunction = None) -> None:\n        self.app = app\n        self.dispatch_func = self.dispatch if dispatch is None else dispatch\n\n    async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:\n        if scope[\"type\"] != \"http\":\n            await self.app(scope, receive, send)\n            return\n\n        async def call_next(request: Request) -> Response:\n            send_stream, recv_stream = anyio.create_memory_object_stream()\n\n            async def coro() -> None:\n                async with send_stream:\n                    await self.app(scope, request.receive, send_stream.send)\n\n            task_group.start_soon(coro)\n\n            try:\n                message = await recv_stream.receive()\n            except anyio.EndOfStream:\n                raise RuntimeError(\"No response returned.\")\n\n            assert message[\"type\"] == \"http.response.start\"\n\n            async def body_stream() -> typing.AsyncGenerator[bytes, None]:\n                async with recv_stream:\n                    async for message in recv_stream:\n                        assert message[\"type\"] == \"http.response.body\"\n                        yield message.get(\"body\", b\"\")\n\n            response = StreamingResponse(\n                status_code=message[\"status\"], content=body_stream()\n            )\n            response.raw_headers = message[\"headers\"]\n            return response\n\n        async with anyio.create_task_group() as task_group:\n            request = Request(scope, receive=receive)\n            response = await self.dispatch_func(request, call_next)\n            await response(scope, receive, send)\n            task_group.cancel_scope.cancel()\n\n    async def dispatch(\n        self, request: Request, call_next: RequestResponseEndpoint\n    ) -> Response:\n        raise NotImplementedError()  # pragma: no cover\n", "path": "starlette/middleware/base.py"}], "after_files": [{"content": "import typing\n\nimport anyio\n\nfrom starlette.requests import Request\nfrom starlette.responses import Response, StreamingResponse\nfrom starlette.types import ASGIApp, Receive, Scope, Send\n\nRequestResponseEndpoint = typing.Callable[[Request], typing.Awaitable[Response]]\nDispatchFunction = typing.Callable[\n    [Request, RequestResponseEndpoint], typing.Awaitable[Response]\n]\n\n\nclass BaseHTTPMiddleware:\n    def __init__(self, app: ASGIApp, dispatch: DispatchFunction = None) -> None:\n        self.app = app\n        self.dispatch_func = self.dispatch if dispatch is None else dispatch\n\n    async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:\n        if scope[\"type\"] != \"http\":\n            await self.app(scope, receive, send)\n            return\n\n        async def call_next(request: Request) -> Response:\n            app_exc: typing.Optional[Exception] = None\n            send_stream, recv_stream = anyio.create_memory_object_stream()\n\n            async def coro() -> None:\n                nonlocal app_exc\n\n                async with send_stream:\n                    try:\n                        await self.app(scope, request.receive, send_stream.send)\n                    except Exception as exc:\n                        app_exc = exc\n\n            task_group.start_soon(coro)\n\n            try:\n                message = await recv_stream.receive()\n            except anyio.EndOfStream:\n                if app_exc is not None:\n                    raise app_exc\n                raise RuntimeError(\"No response returned.\")\n\n            assert message[\"type\"] == \"http.response.start\"\n\n            async def body_stream() -> typing.AsyncGenerator[bytes, None]:\n                async with recv_stream:\n                    async for message in recv_stream:\n                        assert message[\"type\"] == \"http.response.body\"\n                        yield message.get(\"body\", b\"\")\n\n            response = StreamingResponse(\n                status_code=message[\"status\"], content=body_stream()\n            )\n            response.raw_headers = message[\"headers\"]\n            return response\n\n        async with anyio.create_task_group() as task_group:\n            request = Request(scope, receive=receive)\n            response = await self.dispatch_func(request, call_next)\n            await response(scope, receive, send)\n            task_group.cancel_scope.cancel()\n\n    async def dispatch(\n        self, request: Request, call_next: RequestResponseEndpoint\n    ) -> Response:\n        raise NotImplementedError()  # pragma: no cover\n", "path": "starlette/middleware/base.py"}]}