diff --git a/sanic/app.py b/sanic/app.py index 22435ef610..6b547eea9c 100644 --- a/sanic/app.py +++ b/sanic/app.py @@ -1209,10 +1209,15 @@ async def handle_exception( # Request Middleware # -------------------------------------------- # if run_middleware: - middleware = ( - request.route and request.route.extra.request_middleware - ) or self.request_middleware - response = await self._run_request_middleware(request, middleware) + try: + middleware = ( + request.route and request.route.extra.request_middleware + ) or self.request_middleware + response = await self._run_request_middleware( + request, middleware + ) + except Exception as e: + return await self.handle_exception(request, e, False) # No middleware results if not response: try: diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py index 7932eb6dfb..b945eadea0 100644 --- a/tests/test_exceptions.py +++ b/tests/test_exceptions.py @@ -1,5 +1,7 @@ import logging +from itertools import count + import pytest from bs4 import BeautifulSoup @@ -413,3 +415,21 @@ class CustomError(SanicException): assert CustomError().message == CustomError.message == str(CustomError()) assert SanicException().message != "" assert SanicException("").message == "" + + +def test_request_middleware_exception_on_404(app: Sanic): + """See https://github.com/sanic-org/sanic/issues/2950""" + counter = count() + + @app.on_request + def request_middleware(request): + value = next(counter) + raise Exception + + @app.route("/") + async def handler(request): ... + + _, response = app.test_client.get("/not-found") + + assert response.status == 500 + assert next(counter) == 1