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