Ensure middleware executes once per request timeout (#2615)
This commit is contained in:
parent
f32437bf13
commit
d4041161c7
@ -16,6 +16,7 @@ from sanic.exceptions import (
|
|||||||
PayloadTooLarge,
|
PayloadTooLarge,
|
||||||
RequestCancelled,
|
RequestCancelled,
|
||||||
ServerError,
|
ServerError,
|
||||||
|
ServiceUnavailable,
|
||||||
)
|
)
|
||||||
from sanic.headers import format_http1_response
|
from sanic.headers import format_http1_response
|
||||||
from sanic.helpers import has_message_body
|
from sanic.helpers import has_message_body
|
||||||
@ -428,8 +429,11 @@ class Http(Stream, metaclass=TouchUpMeta):
|
|||||||
if self.request is None:
|
if self.request is None:
|
||||||
self.create_empty_request()
|
self.create_empty_request()
|
||||||
|
|
||||||
|
request_middleware = not isinstance(exception, ServiceUnavailable)
|
||||||
try:
|
try:
|
||||||
await app.handle_exception(self.request, exception)
|
await app.handle_exception(
|
||||||
|
self.request, exception, request_middleware
|
||||||
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
await app.handle_exception(self.request, e, False)
|
await app.handle_exception(self.request, e, False)
|
||||||
|
|
||||||
|
@ -104,6 +104,7 @@ class Request:
|
|||||||
"_protocol",
|
"_protocol",
|
||||||
"_remote_addr",
|
"_remote_addr",
|
||||||
"_request_middleware_started",
|
"_request_middleware_started",
|
||||||
|
"_response_middleware_started",
|
||||||
"_scheme",
|
"_scheme",
|
||||||
"_socket",
|
"_socket",
|
||||||
"_stream_id",
|
"_stream_id",
|
||||||
@ -179,6 +180,7 @@ class Request:
|
|||||||
Tuple[bool, bool, str, str], List[Tuple[str, str]]
|
Tuple[bool, bool, str, str], List[Tuple[str, str]]
|
||||||
] = defaultdict(list)
|
] = defaultdict(list)
|
||||||
self._request_middleware_started = False
|
self._request_middleware_started = False
|
||||||
|
self._response_middleware_started = False
|
||||||
self.responded: bool = False
|
self.responded: bool = False
|
||||||
self.route: Optional[Route] = None
|
self.route: Optional[Route] = None
|
||||||
self.stream: Optional[Stream] = None
|
self.stream: Optional[Stream] = None
|
||||||
@ -337,7 +339,8 @@ class Request:
|
|||||||
middleware = (
|
middleware = (
|
||||||
self.route and self.route.extra.response_middleware
|
self.route and self.route.extra.response_middleware
|
||||||
) or self.app.response_middleware
|
) or self.app.response_middleware
|
||||||
if middleware:
|
if middleware and not self._response_middleware_started:
|
||||||
|
self._response_middleware_started = True
|
||||||
response = await self.app._run_response_middleware(
|
response = await self.app._run_response_middleware(
|
||||||
self, response, middleware
|
self, response, middleware
|
||||||
)
|
)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
from asyncio import CancelledError
|
from asyncio import CancelledError, sleep
|
||||||
from itertools import count
|
from itertools import count
|
||||||
|
|
||||||
from sanic.exceptions import NotFound
|
from sanic.exceptions import NotFound
|
||||||
@ -318,6 +318,32 @@ def test_middleware_return_response(app):
|
|||||||
resp1 = await request.respond()
|
resp1 = await request.respond()
|
||||||
return resp1
|
return resp1
|
||||||
|
|
||||||
_, response = app.test_client.get("/")
|
app.test_client.get("/")
|
||||||
assert response_middleware_run_count == 1
|
assert response_middleware_run_count == 1
|
||||||
assert request_middleware_run_count == 1
|
assert request_middleware_run_count == 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_middleware_run_on_timeout(app):
|
||||||
|
app.config.RESPONSE_TIMEOUT = 0.1
|
||||||
|
response_middleware_run_count = 0
|
||||||
|
request_middleware_run_count = 0
|
||||||
|
|
||||||
|
@app.on_response
|
||||||
|
def response(_, response):
|
||||||
|
nonlocal response_middleware_run_count
|
||||||
|
response_middleware_run_count += 1
|
||||||
|
|
||||||
|
@app.on_request
|
||||||
|
def request(_):
|
||||||
|
nonlocal request_middleware_run_count
|
||||||
|
request_middleware_run_count += 1
|
||||||
|
|
||||||
|
@app.get("/")
|
||||||
|
async def handler(request):
|
||||||
|
resp1 = await request.respond()
|
||||||
|
await sleep(1)
|
||||||
|
return resp1
|
||||||
|
|
||||||
|
app.test_client.get("/")
|
||||||
|
assert request_middleware_run_count == 1
|
||||||
|
assert response_middleware_run_count == 1
|
||||||
|
Loading…
x
Reference in New Issue
Block a user