(self, scope: Scope, receive: Receive, send: Send)
| 99 | self.dispatch_func = self.dispatch if dispatch is None else dispatch |
| 100 | |
| 101 | async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: |
| 102 | if scope["type"] != "http": |
| 103 | await self.app(scope, receive, send) |
| 104 | return |
| 105 | |
| 106 | request = _CachedRequest(scope, receive) |
| 107 | wrapped_receive = request.wrapped_receive |
| 108 | response_sent = anyio.Event() |
| 109 | app_exc: Exception | None = None |
| 110 | exception_already_raised = False |
| 111 | |
| 112 | async def call_next(request: Request) -> Response: |
| 113 | async def receive_or_disconnect() -> Message: |
| 114 | if response_sent.is_set(): |
| 115 | return {"type": "http.disconnect"} |
| 116 | |
| 117 | async with anyio.create_task_group() as task_group: |
| 118 | |
| 119 | async def wrap(func: Callable[[], Awaitable[T]]) -> T: |
| 120 | result = await func() |
| 121 | task_group.cancel_scope.cancel() |
| 122 | return result |
| 123 | |
| 124 | task_group.start_soon(wrap, response_sent.wait) |
| 125 | message = await wrap(wrapped_receive) |
| 126 | |
| 127 | if response_sent.is_set(): |
| 128 | return {"type": "http.disconnect"} |
| 129 | |
| 130 | return message |
| 131 | |
| 132 | async def send_no_error(message: Message) -> None: |
| 133 | try: |
| 134 | await send_stream.send(message) |
| 135 | except anyio.BrokenResourceError: |
| 136 | # recv_stream has been closed, i.e. response_sent has been set. |
| 137 | return |
| 138 | |
| 139 | async def coro() -> None: |
| 140 | nonlocal app_exc |
| 141 | |
| 142 | with send_stream: |
| 143 | try: |
| 144 | await self.app(scope, receive_or_disconnect, send_no_error) |
| 145 | except Exception as exc: |
| 146 | app_exc = exc |
| 147 | |
| 148 | task_group.start_soon(coro) |
| 149 | |
| 150 | try: |
| 151 | message = await recv_stream.receive() |
| 152 | info = message.get("info", None) |
| 153 | if message["type"] == "http.response.debug" and info is not None: |
| 154 | message = await recv_stream.receive() |
| 155 | except anyio.EndOfStream: |
| 156 | if app_exc is not None: |
| 157 | nonlocal exception_already_raised |
| 158 | exception_already_raised = True |
nothing calls this directly
no test coverage detected