We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Response streaming produces [ERROR] Invalid response type None (need HTTPResponse)
### Is there an existing issue for this?

- [X] I have searched the existing issues

### Describe the bug

The "response streaming" [feature of Sanic](https://sanic.dev/en/guide/advanced/streaming.html#response-streaming) produces error messages when running from Uvicorn.

When accessing a page using the `await request.respond()` API, it produces error messages after each request.

```
[2024-01-31 19:37:14 +0000] [694830] [INFO] 
  ┌─────────────────────────────────────────────────────────────────────────────────┐
  │                                  Sanic v23.6.0                                  │
  │                                                                                 │
  ├───────────────────────┬─────────────────────────────────────────────────────────┤
  │                       │     mode: production, ASGI                              │
  │     ▄███ █████ ██     │   server: ASGI                                          │
  │    ██                 │   python: 3.11.6                                        │
  │     ▀███████ ███▄     │ platform: Linux-5.15.0-1048-aws-x86_64-with-glibc2.31   │
  │                 ██    │ packages: sanic-routing==23.12.0, sanic-testing==23.6.0 │
  │    ████ ████████▀     │                                                         │
  │                       │                                                         │
  │ Build Fast. Run Fast. │                                                         │
  └───────────────────────┴─────────────────────────────────────────────────────────┘

INFO:     Application startup complete.
INFO:     127.0.0.1:42186 - "GET / HTTP/1.1" 200 OK
[2024-01-31 19:38:19 +0000] [694830] [ERROR] Invalid response type None (need HTTPResponse)
Traceback (most recent call last):
  File "handle_request", line 144, in handle_request
    "_inspector",
            ^^^^^
sanic.exceptions.ServerError: Invalid response type None (need HTTPResponse)
[2024-01-31 19:38:19 +0000] [694830] [ERROR] The error response will not be sent to the client for the following exception:"Invalid response type None (need HTTPResponse)". A previous response has at least partially been sent.
```

### Code snippet

```python

from sanic import Sanic

app = Sanic("my-hello-world-app")


@app.route("/")
async def test(request):
    response = await request.respond(content_type="text/plain")
    await response.send("hello world")
    await response.eof()


if __name__ == "__main__":
    app.run()
```

### Expected Behavior

Sanic should not produce error messages when using the response streaming API.

### How do you run Sanic?

ASGI

### Operating System

Linux

### Sanic Version

23.6.0

### Additional context

Possibly related to #2572, but it seems like a different issue. I can reproduce this without using WebSockets or SSE.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `sanic/asgi.py`
Content:
```
1 from __future__ import annotations
2 
3 import warnings
4 
5 from typing import TYPE_CHECKING, Optional
6 
7 from sanic.compat import Header
8 from sanic.exceptions import BadRequest, ServerError
9 from sanic.helpers import Default
10 from sanic.http import Stage
11 from sanic.log import error_logger, logger
12 from sanic.models.asgi import ASGIReceive, ASGIScope, ASGISend, MockTransport
13 from sanic.request import Request
14 from sanic.response import BaseHTTPResponse
15 from sanic.server import ConnInfo
16 from sanic.server.websockets.connection import WebSocketConnection
17 
18 
19 if TYPE_CHECKING:
20     from sanic import Sanic
21 
22 
23 class Lifespan:
24     def __init__(
25         self, sanic_app, scope: ASGIScope, receive: ASGIReceive, send: ASGISend
26     ) -> None:
27         self.sanic_app = sanic_app
28         self.scope = scope
29         self.receive = receive
30         self.send = send
31 
32         if "server.init.before" in self.sanic_app.signal_router.name_index:
33             logger.debug(
34                 'You have set a listener for "before_server_start" '
35                 "in ASGI mode. "
36                 "It will be executed as early as possible, but not before "
37                 "the ASGI server is started.",
38                 extra={"verbosity": 1},
39             )
40         if "server.shutdown.after" in self.sanic_app.signal_router.name_index:
41             logger.debug(
42                 'You have set a listener for "after_server_stop" '
43                 "in ASGI mode. "
44                 "It will be executed as late as possible, but not after "
45                 "the ASGI server is stopped.",
46                 extra={"verbosity": 1},
47             )
48 
49     async def startup(self) -> None:
50         """
51         Gather the listeners to fire on server start.
52         Because we are using a third-party server and not Sanic server, we do
53         not have access to fire anything BEFORE the server starts.
54         Therefore, we fire before_server_start and after_server_start
55         in sequence since the ASGI lifespan protocol only supports a single
56         startup event.
57         """
58         await self.sanic_app._startup()
59         await self.sanic_app._server_event("init", "before")
60         await self.sanic_app._server_event("init", "after")
61 
62         if not isinstance(self.sanic_app.config.USE_UVLOOP, Default):
63             warnings.warn(
64                 "You have set the USE_UVLOOP configuration option, but Sanic "
65                 "cannot control the event loop when running in ASGI mode."
66                 "This option will be ignored."
67             )
68 
69     async def shutdown(self) -> None:
70         """
71         Gather the listeners to fire on server stop.
72         Because we are using a third-party server and not Sanic server, we do
73         not have access to fire anything AFTER the server stops.
74         Therefore, we fire before_server_stop and after_server_stop
75         in sequence since the ASGI lifespan protocol only supports a single
76         shutdown event.
77         """
78         await self.sanic_app._server_event("shutdown", "before")
79         await self.sanic_app._server_event("shutdown", "after")
80 
81     async def __call__(self) -> None:
82         while True:
83             message = await self.receive()
84             if message["type"] == "lifespan.startup":
85                 try:
86                     await self.startup()
87                 except Exception as e:
88                     error_logger.exception(e)
89                     await self.send(
90                         {"type": "lifespan.startup.failed", "message": str(e)}
91                     )
92                 else:
93                     await self.send({"type": "lifespan.startup.complete"})
94             elif message["type"] == "lifespan.shutdown":
95                 try:
96                     await self.shutdown()
97                 except Exception as e:
98                     error_logger.exception(e)
99                     await self.send(
100                         {"type": "lifespan.shutdown.failed", "message": str(e)}
101                     )
102                 else:
103                     await self.send({"type": "lifespan.shutdown.complete"})
104                 return
105 
106 
107 class ASGIApp:
108     sanic_app: Sanic
109     request: Request
110     transport: MockTransport
111     lifespan: Lifespan
112     ws: Optional[WebSocketConnection]
113     stage: Stage
114     response: Optional[BaseHTTPResponse]
115 
116     @classmethod
117     async def create(
118         cls,
119         sanic_app: Sanic,
120         scope: ASGIScope,
121         receive: ASGIReceive,
122         send: ASGISend,
123     ) -> ASGIApp:
124         instance = cls()
125         instance.ws = None
126         instance.sanic_app = sanic_app
127         instance.transport = MockTransport(scope, receive, send)
128         instance.transport.loop = sanic_app.loop
129         instance.stage = Stage.IDLE
130         instance.response = None
131         instance.sanic_app.state.is_started = True
132         setattr(instance.transport, "add_task", sanic_app.loop.create_task)
133 
134         try:
135             headers = Header(
136                 [
137                     (
138                         key.decode("ASCII"),
139                         value.decode(errors="surrogateescape"),
140                     )
141                     for key, value in scope.get("headers", [])
142                 ]
143             )
144         except UnicodeDecodeError:
145             raise BadRequest(
146                 "Header names can only contain US-ASCII characters"
147             )
148 
149         if scope["type"] == "http":
150             version = scope["http_version"]
151             method = scope["method"]
152         elif scope["type"] == "websocket":
153             version = "1.1"
154             method = "GET"
155 
156             instance.ws = instance.transport.create_websocket_connection(
157                 send, receive
158             )
159         else:
160             raise ServerError("Received unknown ASGI scope")
161 
162         url_bytes, query = scope["raw_path"], scope["query_string"]
163         if query:
164             # httpx ASGI client sends query string as part of raw_path
165             url_bytes = url_bytes.split(b"?", 1)[0]
166             # All servers send them separately
167             url_bytes = b"%b?%b" % (url_bytes, query)
168 
169         request_class = sanic_app.request_class or Request  # type: ignore
170         instance.request = request_class(
171             url_bytes,
172             headers,
173             version,
174             method,
175             instance.transport,
176             sanic_app,
177         )
178         request_class._current.set(instance.request)
179         instance.request.stream = instance  # type: ignore
180         instance.request_body = True
181         instance.request.conn_info = ConnInfo(instance.transport)
182 
183         await instance.sanic_app.dispatch(
184             "http.lifecycle.request",
185             inline=True,
186             context={"request": instance.request},
187             fail_not_found=False,
188         )
189 
190         return instance
191 
192     async def read(self) -> Optional[bytes]:
193         """
194         Read and stream the body in chunks from an incoming ASGI message.
195         """
196         if self.stage is Stage.IDLE:
197             self.stage = Stage.REQUEST
198         message = await self.transport.receive()
199         body = message.get("body", b"")
200         if not message.get("more_body", False):
201             self.request_body = False
202             if not body:
203                 return None
204         return body
205 
206     async def __aiter__(self):
207         while self.request_body:
208             data = await self.read()
209             if data:
210                 yield data
211 
212     def respond(self, response: BaseHTTPResponse):
213         if self.stage is not Stage.HANDLER:
214             self.stage = Stage.FAILED
215             raise RuntimeError("Response already started")
216         if self.response is not None:
217             self.response.stream = None
218         response.stream, self.response = self, response
219         return response
220 
221     async def send(self, data, end_stream):
222         self.stage = Stage.IDLE if end_stream else Stage.RESPONSE
223         if self.response:
224             response, self.response = self.response, None
225             await self.transport.send(
226                 {
227                     "type": "http.response.start",
228                     "status": response.status,
229                     "headers": response.processed_headers,
230                 }
231             )
232             response_body = getattr(response, "body", None)
233             if response_body:
234                 data = response_body + data if data else response_body
235         await self.transport.send(
236             {
237                 "type": "http.response.body",
238                 "body": data.encode() if hasattr(data, "encode") else data,
239                 "more_body": not end_stream,
240             }
241         )
242 
243     _asgi_single_callable = True  # We conform to ASGI 3.0 single-callable
244 
245     async def __call__(self) -> None:
246         """
247         Handle the incoming request.
248         """
249         try:
250             self.stage = Stage.HANDLER
251             await self.sanic_app.handle_request(self.request)
252         except Exception as e:
253             try:
254                 await self.sanic_app.handle_exception(self.request, e)
255             except Exception as exc:
256                 await self.sanic_app.handle_exception(self.request, exc, False)
257
```
--- 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/sanic/asgi.py b/sanic/asgi.py
--- a/sanic/asgi.py
+++ b/sanic/asgi.py
@@ -219,19 +219,26 @@
         return response
 
     async def send(self, data, end_stream):
-        self.stage = Stage.IDLE if end_stream else Stage.RESPONSE
-        if self.response:
-            response, self.response = self.response, None
+        if self.stage is Stage.IDLE:
+            if not end_stream or data:
+                raise RuntimeError(
+                    "There is no request to respond to, either the "
+                    "response has already been sent or the "
+                    "request has not been received yet."
+                )
+            return
+        if self.response and self.stage is Stage.HANDLER:
             await self.transport.send(
                 {
                     "type": "http.response.start",
-                    "status": response.status,
-                    "headers": response.processed_headers,
+                    "status": self.response.status,
+                    "headers": self.response.processed_headers,
                 }
             )
-            response_body = getattr(response, "body", None)
+            response_body = getattr(self.response, "body", None)
             if response_body:
                 data = response_body + data if data else response_body
+        self.stage = Stage.IDLE if end_stream else Stage.RESPONSE
         await self.transport.send(
             {
                 "type": "http.response.body",

{"golden_diff": "diff --git a/sanic/asgi.py b/sanic/asgi.py\n--- a/sanic/asgi.py\n+++ b/sanic/asgi.py\n@@ -219,19 +219,26 @@\n         return response\n \n     async def send(self, data, end_stream):\n-        self.stage = Stage.IDLE if end_stream else Stage.RESPONSE\n-        if self.response:\n-            response, self.response = self.response, None\n+        if self.stage is Stage.IDLE:\n+            if not end_stream or data:\n+                raise RuntimeError(\n+                    \"There is no request to respond to, either the \"\n+                    \"response has already been sent or the \"\n+                    \"request has not been received yet.\"\n+                )\n+            return\n+        if self.response and self.stage is Stage.HANDLER:\n             await self.transport.send(\n                 {\n                     \"type\": \"http.response.start\",\n-                    \"status\": response.status,\n-                    \"headers\": response.processed_headers,\n+                    \"status\": self.response.status,\n+                    \"headers\": self.response.processed_headers,\n                 }\n             )\n-            response_body = getattr(response, \"body\", None)\n+            response_body = getattr(self.response, \"body\", None)\n             if response_body:\n                 data = response_body + data if data else response_body\n+        self.stage = Stage.IDLE if end_stream else Stage.RESPONSE\n         await self.transport.send(\n             {\n                 \"type\": \"http.response.body\",\n", "issue": "Response streaming produces [ERROR] Invalid response type None (need HTTPResponse)\n### Is there an existing issue for this?\r\n\r\n- [X] I have searched the existing issues\r\n\r\n### Describe the bug\r\n\r\nThe \"response streaming\" [feature of Sanic](https://sanic.dev/en/guide/advanced/streaming.html#response-streaming) produces error messages when running from Uvicorn.\r\n\r\nWhen accessing a page using the `await request.respond()` API, it produces error messages after each request.\r\n\r\n```\r\n[2024-01-31 19:37:14 +0000] [694830] [INFO] \r\n  \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\r\n  \u2502                                  Sanic v23.6.0                                  \u2502\r\n  \u2502                                                                                 \u2502\r\n  \u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\r\n  \u2502                       \u2502     mode: production, ASGI                              \u2502\r\n  \u2502     \u2584\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588     \u2502   server: ASGI                                          \u2502\r\n  \u2502    \u2588\u2588                 \u2502   python: 3.11.6                                        \u2502\r\n  \u2502     \u2580\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2584     \u2502 platform: Linux-5.15.0-1048-aws-x86_64-with-glibc2.31   \u2502\r\n  \u2502                 \u2588\u2588    \u2502 packages: sanic-routing==23.12.0, sanic-testing==23.6.0 \u2502\r\n  \u2502    \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2580     \u2502                                                         \u2502\r\n  \u2502                       \u2502                                                         \u2502\r\n  \u2502 Build Fast. Run Fast. \u2502                                                         \u2502\r\n  \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\r\n\r\nINFO:     Application startup complete.\r\nINFO:     127.0.0.1:42186 - \"GET / HTTP/1.1\" 200 OK\r\n[2024-01-31 19:38:19 +0000] [694830] [ERROR] Invalid response type None (need HTTPResponse)\r\nTraceback (most recent call last):\r\n  File \"handle_request\", line 144, in handle_request\r\n    \"_inspector\",\r\n            ^^^^^\r\nsanic.exceptions.ServerError: Invalid response type None (need HTTPResponse)\r\n[2024-01-31 19:38:19 +0000] [694830] [ERROR] The error response will not be sent to the client for the following exception:\"Invalid response type None (need HTTPResponse)\". A previous response has at least partially been sent.\r\n```\r\n\r\n### Code snippet\r\n\r\n```python\r\n\r\nfrom sanic import Sanic\r\n\r\napp = Sanic(\"my-hello-world-app\")\r\n\r\n\r\n@app.route(\"/\")\r\nasync def test(request):\r\n    response = await request.respond(content_type=\"text/plain\")\r\n    await response.send(\"hello world\")\r\n    await response.eof()\r\n\r\n\r\nif __name__ == \"__main__\":\r\n    app.run()\r\n```\r\n\r\n### Expected Behavior\r\n\r\nSanic should not produce error messages when using the response streaming API.\r\n\r\n### How do you run Sanic?\r\n\r\nASGI\r\n\r\n### Operating System\r\n\r\nLinux\r\n\r\n### Sanic Version\r\n\r\n23.6.0\r\n\r\n### Additional context\r\n\r\nPossibly related to #2572, but it seems like a different issue. I can reproduce this without using WebSockets or SSE.\n", "before_files": [{"content": "from __future__ import annotations\n\nimport warnings\n\nfrom typing import TYPE_CHECKING, Optional\n\nfrom sanic.compat import Header\nfrom sanic.exceptions import BadRequest, ServerError\nfrom sanic.helpers import Default\nfrom sanic.http import Stage\nfrom sanic.log import error_logger, logger\nfrom sanic.models.asgi import ASGIReceive, ASGIScope, ASGISend, MockTransport\nfrom sanic.request import Request\nfrom sanic.response import BaseHTTPResponse\nfrom sanic.server import ConnInfo\nfrom sanic.server.websockets.connection import WebSocketConnection\n\n\nif TYPE_CHECKING:\n    from sanic import Sanic\n\n\nclass Lifespan:\n    def __init__(\n        self, sanic_app, scope: ASGIScope, receive: ASGIReceive, send: ASGISend\n    ) -> None:\n        self.sanic_app = sanic_app\n        self.scope = scope\n        self.receive = receive\n        self.send = send\n\n        if \"server.init.before\" in self.sanic_app.signal_router.name_index:\n            logger.debug(\n                'You have set a listener for \"before_server_start\" '\n                \"in ASGI mode. \"\n                \"It will be executed as early as possible, but not before \"\n                \"the ASGI server is started.\",\n                extra={\"verbosity\": 1},\n            )\n        if \"server.shutdown.after\" in self.sanic_app.signal_router.name_index:\n            logger.debug(\n                'You have set a listener for \"after_server_stop\" '\n                \"in ASGI mode. \"\n                \"It will be executed as late as possible, but not after \"\n                \"the ASGI server is stopped.\",\n                extra={\"verbosity\": 1},\n            )\n\n    async def startup(self) -> None:\n        \"\"\"\n        Gather the listeners to fire on server start.\n        Because we are using a third-party server and not Sanic server, we do\n        not have access to fire anything BEFORE the server starts.\n        Therefore, we fire before_server_start and after_server_start\n        in sequence since the ASGI lifespan protocol only supports a single\n        startup event.\n        \"\"\"\n        await self.sanic_app._startup()\n        await self.sanic_app._server_event(\"init\", \"before\")\n        await self.sanic_app._server_event(\"init\", \"after\")\n\n        if not isinstance(self.sanic_app.config.USE_UVLOOP, Default):\n            warnings.warn(\n                \"You have set the USE_UVLOOP configuration option, but Sanic \"\n                \"cannot control the event loop when running in ASGI mode.\"\n                \"This option will be ignored.\"\n            )\n\n    async def shutdown(self) -> None:\n        \"\"\"\n        Gather the listeners to fire on server stop.\n        Because we are using a third-party server and not Sanic server, we do\n        not have access to fire anything AFTER the server stops.\n        Therefore, we fire before_server_stop and after_server_stop\n        in sequence since the ASGI lifespan protocol only supports a single\n        shutdown event.\n        \"\"\"\n        await self.sanic_app._server_event(\"shutdown\", \"before\")\n        await self.sanic_app._server_event(\"shutdown\", \"after\")\n\n    async def __call__(self) -> None:\n        while True:\n            message = await self.receive()\n            if message[\"type\"] == \"lifespan.startup\":\n                try:\n                    await self.startup()\n                except Exception as e:\n                    error_logger.exception(e)\n                    await self.send(\n                        {\"type\": \"lifespan.startup.failed\", \"message\": str(e)}\n                    )\n                else:\n                    await self.send({\"type\": \"lifespan.startup.complete\"})\n            elif message[\"type\"] == \"lifespan.shutdown\":\n                try:\n                    await self.shutdown()\n                except Exception as e:\n                    error_logger.exception(e)\n                    await self.send(\n                        {\"type\": \"lifespan.shutdown.failed\", \"message\": str(e)}\n                    )\n                else:\n                    await self.send({\"type\": \"lifespan.shutdown.complete\"})\n                return\n\n\nclass ASGIApp:\n    sanic_app: Sanic\n    request: Request\n    transport: MockTransport\n    lifespan: Lifespan\n    ws: Optional[WebSocketConnection]\n    stage: Stage\n    response: Optional[BaseHTTPResponse]\n\n    @classmethod\n    async def create(\n        cls,\n        sanic_app: Sanic,\n        scope: ASGIScope,\n        receive: ASGIReceive,\n        send: ASGISend,\n    ) -> ASGIApp:\n        instance = cls()\n        instance.ws = None\n        instance.sanic_app = sanic_app\n        instance.transport = MockTransport(scope, receive, send)\n        instance.transport.loop = sanic_app.loop\n        instance.stage = Stage.IDLE\n        instance.response = None\n        instance.sanic_app.state.is_started = True\n        setattr(instance.transport, \"add_task\", sanic_app.loop.create_task)\n\n        try:\n            headers = Header(\n                [\n                    (\n                        key.decode(\"ASCII\"),\n                        value.decode(errors=\"surrogateescape\"),\n                    )\n                    for key, value in scope.get(\"headers\", [])\n                ]\n            )\n        except UnicodeDecodeError:\n            raise BadRequest(\n                \"Header names can only contain US-ASCII characters\"\n            )\n\n        if scope[\"type\"] == \"http\":\n            version = scope[\"http_version\"]\n            method = scope[\"method\"]\n        elif scope[\"type\"] == \"websocket\":\n            version = \"1.1\"\n            method = \"GET\"\n\n            instance.ws = instance.transport.create_websocket_connection(\n                send, receive\n            )\n        else:\n            raise ServerError(\"Received unknown ASGI scope\")\n\n        url_bytes, query = scope[\"raw_path\"], scope[\"query_string\"]\n        if query:\n            # httpx ASGI client sends query string as part of raw_path\n            url_bytes = url_bytes.split(b\"?\", 1)[0]\n            # All servers send them separately\n            url_bytes = b\"%b?%b\" % (url_bytes, query)\n\n        request_class = sanic_app.request_class or Request  # type: ignore\n        instance.request = request_class(\n            url_bytes,\n            headers,\n            version,\n            method,\n            instance.transport,\n            sanic_app,\n        )\n        request_class._current.set(instance.request)\n        instance.request.stream = instance  # type: ignore\n        instance.request_body = True\n        instance.request.conn_info = ConnInfo(instance.transport)\n\n        await instance.sanic_app.dispatch(\n            \"http.lifecycle.request\",\n            inline=True,\n            context={\"request\": instance.request},\n            fail_not_found=False,\n        )\n\n        return instance\n\n    async def read(self) -> Optional[bytes]:\n        \"\"\"\n        Read and stream the body in chunks from an incoming ASGI message.\n        \"\"\"\n        if self.stage is Stage.IDLE:\n            self.stage = Stage.REQUEST\n        message = await self.transport.receive()\n        body = message.get(\"body\", b\"\")\n        if not message.get(\"more_body\", False):\n            self.request_body = False\n            if not body:\n                return None\n        return body\n\n    async def __aiter__(self):\n        while self.request_body:\n            data = await self.read()\n            if data:\n                yield data\n\n    def respond(self, response: BaseHTTPResponse):\n        if self.stage is not Stage.HANDLER:\n            self.stage = Stage.FAILED\n            raise RuntimeError(\"Response already started\")\n        if self.response is not None:\n            self.response.stream = None\n        response.stream, self.response = self, response\n        return response\n\n    async def send(self, data, end_stream):\n        self.stage = Stage.IDLE if end_stream else Stage.RESPONSE\n        if self.response:\n            response, self.response = self.response, None\n            await self.transport.send(\n                {\n                    \"type\": \"http.response.start\",\n                    \"status\": response.status,\n                    \"headers\": response.processed_headers,\n                }\n            )\n            response_body = getattr(response, \"body\", None)\n            if response_body:\n                data = response_body + data if data else response_body\n        await self.transport.send(\n            {\n                \"type\": \"http.response.body\",\n                \"body\": data.encode() if hasattr(data, \"encode\") else data,\n                \"more_body\": not end_stream,\n            }\n        )\n\n    _asgi_single_callable = True  # We conform to ASGI 3.0 single-callable\n\n    async def __call__(self) -> None:\n        \"\"\"\n        Handle the incoming request.\n        \"\"\"\n        try:\n            self.stage = Stage.HANDLER\n            await self.sanic_app.handle_request(self.request)\n        except Exception as e:\n            try:\n                await self.sanic_app.handle_exception(self.request, e)\n            except Exception as exc:\n                await self.sanic_app.handle_exception(self.request, exc, False)\n", "path": "sanic/asgi.py"}], "after_files": [{"content": "from __future__ import annotations\n\nimport warnings\n\nfrom typing import TYPE_CHECKING, Optional\n\nfrom sanic.compat import Header\nfrom sanic.exceptions import BadRequest, ServerError\nfrom sanic.helpers import Default\nfrom sanic.http import Stage\nfrom sanic.log import error_logger, logger\nfrom sanic.models.asgi import ASGIReceive, ASGIScope, ASGISend, MockTransport\nfrom sanic.request import Request\nfrom sanic.response import BaseHTTPResponse\nfrom sanic.server import ConnInfo\nfrom sanic.server.websockets.connection import WebSocketConnection\n\n\nif TYPE_CHECKING:\n    from sanic import Sanic\n\n\nclass Lifespan:\n    def __init__(\n        self, sanic_app, scope: ASGIScope, receive: ASGIReceive, send: ASGISend\n    ) -> None:\n        self.sanic_app = sanic_app\n        self.scope = scope\n        self.receive = receive\n        self.send = send\n\n        if \"server.init.before\" in self.sanic_app.signal_router.name_index:\n            logger.debug(\n                'You have set a listener for \"before_server_start\" '\n                \"in ASGI mode. \"\n                \"It will be executed as early as possible, but not before \"\n                \"the ASGI server is started.\",\n                extra={\"verbosity\": 1},\n            )\n        if \"server.shutdown.after\" in self.sanic_app.signal_router.name_index:\n            logger.debug(\n                'You have set a listener for \"after_server_stop\" '\n                \"in ASGI mode. \"\n                \"It will be executed as late as possible, but not after \"\n                \"the ASGI server is stopped.\",\n                extra={\"verbosity\": 1},\n            )\n\n    async def startup(self) -> None:\n        \"\"\"\n        Gather the listeners to fire on server start.\n        Because we are using a third-party server and not Sanic server, we do\n        not have access to fire anything BEFORE the server starts.\n        Therefore, we fire before_server_start and after_server_start\n        in sequence since the ASGI lifespan protocol only supports a single\n        startup event.\n        \"\"\"\n        await self.sanic_app._startup()\n        await self.sanic_app._server_event(\"init\", \"before\")\n        await self.sanic_app._server_event(\"init\", \"after\")\n\n        if not isinstance(self.sanic_app.config.USE_UVLOOP, Default):\n            warnings.warn(\n                \"You have set the USE_UVLOOP configuration option, but Sanic \"\n                \"cannot control the event loop when running in ASGI mode.\"\n                \"This option will be ignored.\"\n            )\n\n    async def shutdown(self) -> None:\n        \"\"\"\n        Gather the listeners to fire on server stop.\n        Because we are using a third-party server and not Sanic server, we do\n        not have access to fire anything AFTER the server stops.\n        Therefore, we fire before_server_stop and after_server_stop\n        in sequence since the ASGI lifespan protocol only supports a single\n        shutdown event.\n        \"\"\"\n        await self.sanic_app._server_event(\"shutdown\", \"before\")\n        await self.sanic_app._server_event(\"shutdown\", \"after\")\n\n    async def __call__(self) -> None:\n        while True:\n            message = await self.receive()\n            if message[\"type\"] == \"lifespan.startup\":\n                try:\n                    await self.startup()\n                except Exception as e:\n                    error_logger.exception(e)\n                    await self.send(\n                        {\"type\": \"lifespan.startup.failed\", \"message\": str(e)}\n                    )\n                else:\n                    await self.send({\"type\": \"lifespan.startup.complete\"})\n            elif message[\"type\"] == \"lifespan.shutdown\":\n                try:\n                    await self.shutdown()\n                except Exception as e:\n                    error_logger.exception(e)\n                    await self.send(\n                        {\"type\": \"lifespan.shutdown.failed\", \"message\": str(e)}\n                    )\n                else:\n                    await self.send({\"type\": \"lifespan.shutdown.complete\"})\n                return\n\n\nclass ASGIApp:\n    sanic_app: Sanic\n    request: Request\n    transport: MockTransport\n    lifespan: Lifespan\n    ws: Optional[WebSocketConnection]\n    stage: Stage\n    response: Optional[BaseHTTPResponse]\n\n    @classmethod\n    async def create(\n        cls,\n        sanic_app: Sanic,\n        scope: ASGIScope,\n        receive: ASGIReceive,\n        send: ASGISend,\n    ) -> ASGIApp:\n        instance = cls()\n        instance.ws = None\n        instance.sanic_app = sanic_app\n        instance.transport = MockTransport(scope, receive, send)\n        instance.transport.loop = sanic_app.loop\n        instance.stage = Stage.IDLE\n        instance.response = None\n        instance.sanic_app.state.is_started = True\n        setattr(instance.transport, \"add_task\", sanic_app.loop.create_task)\n\n        try:\n            headers = Header(\n                [\n                    (\n                        key.decode(\"ASCII\"),\n                        value.decode(errors=\"surrogateescape\"),\n                    )\n                    for key, value in scope.get(\"headers\", [])\n                ]\n            )\n        except UnicodeDecodeError:\n            raise BadRequest(\n                \"Header names can only contain US-ASCII characters\"\n            )\n\n        if scope[\"type\"] == \"http\":\n            version = scope[\"http_version\"]\n            method = scope[\"method\"]\n        elif scope[\"type\"] == \"websocket\":\n            version = \"1.1\"\n            method = \"GET\"\n\n            instance.ws = instance.transport.create_websocket_connection(\n                send, receive\n            )\n        else:\n            raise ServerError(\"Received unknown ASGI scope\")\n\n        url_bytes, query = scope[\"raw_path\"], scope[\"query_string\"]\n        if query:\n            # httpx ASGI client sends query string as part of raw_path\n            url_bytes = url_bytes.split(b\"?\", 1)[0]\n            # All servers send them separately\n            url_bytes = b\"%b?%b\" % (url_bytes, query)\n\n        request_class = sanic_app.request_class or Request  # type: ignore\n        instance.request = request_class(\n            url_bytes,\n            headers,\n            version,\n            method,\n            instance.transport,\n            sanic_app,\n        )\n        request_class._current.set(instance.request)\n        instance.request.stream = instance  # type: ignore\n        instance.request_body = True\n        instance.request.conn_info = ConnInfo(instance.transport)\n\n        await instance.sanic_app.dispatch(\n            \"http.lifecycle.request\",\n            inline=True,\n            context={\"request\": instance.request},\n            fail_not_found=False,\n        )\n\n        return instance\n\n    async def read(self) -> Optional[bytes]:\n        \"\"\"\n        Read and stream the body in chunks from an incoming ASGI message.\n        \"\"\"\n        if self.stage is Stage.IDLE:\n            self.stage = Stage.REQUEST\n        message = await self.transport.receive()\n        body = message.get(\"body\", b\"\")\n        if not message.get(\"more_body\", False):\n            self.request_body = False\n            if not body:\n                return None\n        return body\n\n    async def __aiter__(self):\n        while self.request_body:\n            data = await self.read()\n            if data:\n                yield data\n\n    def respond(self, response: BaseHTTPResponse):\n        if self.stage is not Stage.HANDLER:\n            self.stage = Stage.FAILED\n            raise RuntimeError(\"Response already started\")\n        if self.response is not None:\n            self.response.stream = None\n        response.stream, self.response = self, response\n        return response\n\n    async def send(self, data, end_stream):\n        if self.stage is Stage.IDLE:\n            if not end_stream or data:\n                raise RuntimeError(\n                    \"There is no request to respond to, either the \"\n                    \"response has already been sent or the \"\n                    \"request has not been received yet.\"\n                )\n            return\n        if self.response and self.stage is Stage.HANDLER:\n            await self.transport.send(\n                {\n                    \"type\": \"http.response.start\",\n                    \"status\": self.response.status,\n                    \"headers\": self.response.processed_headers,\n                }\n            )\n            response_body = getattr(self.response, \"body\", None)\n            if response_body:\n                data = response_body + data if data else response_body\n        self.stage = Stage.IDLE if end_stream else Stage.RESPONSE\n        await self.transport.send(\n            {\n                \"type\": \"http.response.body\",\n                \"body\": data.encode() if hasattr(data, \"encode\") else data,\n                \"more_body\": not end_stream,\n            }\n        )\n\n    _asgi_single_callable = True  # We conform to ASGI 3.0 single-callable\n\n    async def __call__(self) -> None:\n        \"\"\"\n        Handle the incoming request.\n        \"\"\"\n        try:\n            self.stage = Stage.HANDLER\n            await self.sanic_app.handle_request(self.request)\n        except Exception as e:\n            try:\n                await self.sanic_app.handle_exception(self.request, e)\n            except Exception as exc:\n                await self.sanic_app.handle_exception(self.request, exc, False)\n", "path": "sanic/asgi.py"}]}