Response middleware ran by async request.respond().
This commit is contained in:
parent
2b63d2bed4
commit
2adcc72e06
29
sanic/app.py
29
sanic/app.py
|
@ -938,7 +938,7 @@ class Sanic:
|
|||
"""
|
||||
pass
|
||||
|
||||
async def handle_exception(self, request, exception, name=""):
|
||||
async def handle_exception(self, request, exception):
|
||||
try:
|
||||
response = self.error_handler.response(request, exception)
|
||||
if isawaitable(response):
|
||||
|
@ -959,7 +959,7 @@ class Sanic:
|
|||
if response is not None:
|
||||
try:
|
||||
response = await self._run_response_middleware(
|
||||
request, response, request_name=name
|
||||
request, response, request_name=request.name
|
||||
)
|
||||
except CancelledError:
|
||||
# FIXME: Ensure exiting in a clean manner instead of this
|
||||
|
@ -992,6 +992,7 @@ class Sanic:
|
|||
try:
|
||||
# Fetch handler from router
|
||||
handler, args, kwargs, uri, name = self.router.get(request)
|
||||
request.name = name
|
||||
|
||||
if request.stream.request_body:
|
||||
if self.router.is_stream_handler(request):
|
||||
|
@ -1036,22 +1037,11 @@ class Sanic:
|
|||
response = handler(request, *args, **kwargs)
|
||||
if isawaitable(response):
|
||||
response = await response
|
||||
# Run response middleware
|
||||
if response is not None:
|
||||
try:
|
||||
response = await self._run_response_middleware(
|
||||
request, response, request_name=name
|
||||
)
|
||||
except CancelledError:
|
||||
raise
|
||||
except Exception:
|
||||
error_logger.exception(
|
||||
"Exception occurred in one of response "
|
||||
"middleware handlers"
|
||||
)
|
||||
if response:
|
||||
response = await request.respond(response)
|
||||
# Make sure that response is finished / run StreamingHTTP callback
|
||||
if isinstance(response, BaseHTTPResponse):
|
||||
await request.respond(response).send(end_stream=True)
|
||||
await response.send(end_stream=True)
|
||||
else:
|
||||
raise ServerError(
|
||||
f"Invalid response type {response!r} (need HTTPResponse)"
|
||||
|
@ -1063,8 +1053,9 @@ class Sanic:
|
|||
# -------------------------------------------- #
|
||||
# Response Generation Failed
|
||||
# -------------------------------------------- #
|
||||
response = await self.handle_exception(request, e, name)
|
||||
await request.respond(response).send(end_stream=True)
|
||||
response = await self.handle_exception(request, e)
|
||||
response = await request.respond(response)
|
||||
await response.send(end_stream=True)
|
||||
|
||||
# -------------------------------------------------------------------- #
|
||||
# Testing
|
||||
|
@ -1345,6 +1336,8 @@ class Sanic:
|
|||
_response = await _response
|
||||
if _response:
|
||||
response = _response
|
||||
if isinstance(response, BaseHTTPResponse):
|
||||
response = request.stream.respond(response)
|
||||
break
|
||||
return response
|
||||
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
from sys import argv
|
||||
|
||||
from multidict import CIMultiDict # type: ignore
|
||||
from asyncio import CancelledError
|
||||
|
||||
try:
|
||||
from trio import Cancelled
|
||||
CancelledErrors = CancelledError, Cancelled
|
||||
except ImportError:
|
||||
CancelledErrors = CancelledError,
|
||||
|
||||
class Header(CIMultiDict):
|
||||
def get_all(self, key):
|
||||
|
|
|
@ -9,6 +9,7 @@ from urllib.parse import parse_qs, parse_qsl, unquote, urlunparse
|
|||
from httptools import parse_url # type: ignore
|
||||
|
||||
from sanic.exceptions import InvalidUsage
|
||||
from sanic.compat import CancelledErrors
|
||||
from sanic.headers import (
|
||||
parse_content_header,
|
||||
parse_forwarded,
|
||||
|
@ -16,7 +17,7 @@ from sanic.headers import (
|
|||
parse_xforwarded,
|
||||
)
|
||||
from sanic.log import error_logger, logger
|
||||
from sanic.response import HTTPResponse
|
||||
from sanic.response import HTTPResponse, BaseHTTPResponse
|
||||
|
||||
|
||||
try:
|
||||
|
@ -62,6 +63,7 @@ class Request:
|
|||
"endpoint",
|
||||
"headers",
|
||||
"method",
|
||||
"name",
|
||||
"parsed_args",
|
||||
"parsed_not_grouped_args",
|
||||
"parsed_files",
|
||||
|
@ -89,6 +91,7 @@ class Request:
|
|||
# Init but do not inhale
|
||||
self.body = b""
|
||||
self.ctx = SimpleNamespace()
|
||||
self.name = None
|
||||
self.parsed_forwarded = None
|
||||
self.parsed_json = None
|
||||
self.parsed_form = None
|
||||
|
@ -105,7 +108,7 @@ class Request:
|
|||
self.__class__.__name__, self.method, self.path
|
||||
)
|
||||
|
||||
def respond(
|
||||
async def respond(
|
||||
self, response=None, *, status=200, headers=None, content_type=None
|
||||
):
|
||||
# This logic of determining which response to use is subject to change
|
||||
|
@ -113,8 +116,22 @@ class Request:
|
|||
response = self.stream.response or HTTPResponse(
|
||||
status=status, headers=headers, content_type=content_type,
|
||||
)
|
||||
# Connect the response and return it
|
||||
return self.stream.respond(response)
|
||||
# Connect the response
|
||||
if isinstance(response, BaseHTTPResponse):
|
||||
response = self.stream.respond(response)
|
||||
# Run response middleware
|
||||
try:
|
||||
response = await self.app._run_response_middleware(
|
||||
self, response, request_name=self.name
|
||||
)
|
||||
except CancelledErrors:
|
||||
raise
|
||||
except Exception:
|
||||
error_logger.exception(
|
||||
"Exception occurred in one of response "
|
||||
"middleware handlers"
|
||||
)
|
||||
return response
|
||||
|
||||
async def receive_body(self):
|
||||
self.body = b"".join([data async for data in self.stream])
|
||||
|
|
Loading…
Reference in New Issue
Block a user