Repository: sanic-org/sanic

Issue:
Malfunction of middleware when the request aborted.
### Is there an existing issue for this?

- [X] I have searched the existing issues

### Describe the bug

When the client aborts the request while processing the request on the server, on_request is called again after on_response.

### Code snippet

```py
import asyncio

from sanic import Sanic, text

app = Sanic(__name__)


@app.on_request
async def on_request(request):
    print("on_request", request.id)


@app.on_response
async def on_response(request, response):
    print("on_response", request.id)


@app.get("/")
async def test(request):
    print("test handler")

    try:
        await asyncio.sleep(10)
    except asyncio.CancelledError as e:
        print("test handler cancelled")
        raise e

    return text("test")


if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8000)
```

Output
```sh
on_request 592d1e27-b05b-4f2f-a138-f81d5c44c58c
test handler
---- I aborted the request here ----
test handler cancelled
on_response 592d1e27-b05b-4f2f-a138-f81d5c44c58c
on_request 592d1e27-b05b-4f2f-a138-f81d5c44c58c <<<< strange thing
```

### Expected Behavior

`on_request` should be called once before call `RouterHandler`, not again after `on_response`

### How do you run Sanic?

As a script (`app.run` or `Sanic.serve`)

### Operating System

Windows-10-10.0.19044-SP0 

### Sanic Version

sanic==22.12.0, sanic-routing==22.8.0, sanic-ext==22.12.0


Discussion:
Yeah I am experiencing something similar as well. I have a search component in my React frontend that does search-as-you-type so there are lots of requests sent to the server and sometimes the frontend will explicitly cancel the pending request if the user started typing something else.

Currently I have an error because while the request was cancelled, sanic was still in the process of running some middleware for the request and they error out because the request context is no longer available. There seems to be something odd with processing `CancelledError`. I wish there was more documentation about this so I can implement a fix that does not involve wrapper each-and-every middleware of method in a try/catch.

For info I am running Python 3.11, Latest sanic.
This appears to be a bug that we need to get sorted out. Hopefully for the upcoming 23.3. release.

The internals of error and cancellation handling & middlewares are really complicated and not really documented beyond some source code comments.

I have an overhaul branch that I wanted to get in but will wiat until next release. I'll get a patch for this in.

Resolving patch:
diff --git a/sanic/http/http1.py b/sanic/http/http1.py
--- a/sanic/http/http1.py
+++ b/sanic/http/http1.py
@@ -428,7 +428,9 @@ async def error_response(self, exception: Exception) -> None:
             if self.request is None:
                 self.create_empty_request()
 
-            request_middleware = not isinstance(exception, ServiceUnavailable)
+            request_middleware = not isinstance(
+                exception, (ServiceUnavailable, RequestCancelled)
+            )
             try:
                 await app.handle_exception(
                     self.request, exception, request_middleware


Test patch: