This commit is contained in:
L. Kärkkäinen 2020-03-01 13:21:02 +02:00
parent f8298939c0
commit 5086076590
7 changed files with 42 additions and 25 deletions

View File

@ -968,7 +968,6 @@ class Sanic:
)
return response
async def handle_request(self, request):
"""Take a request from the HTTP Server and return a response object
to be sent back The HTTP Server only expects a response object, so
@ -1062,7 +1061,6 @@ class Sanic:
response = await self.handle_exception(request, e, name)
await request.respond(response).send(end_stream=True)
# -------------------------------------------------------------------- #
# Testing
# -------------------------------------------------------------------- #
@ -1092,7 +1090,7 @@ class Sanic:
stop_event: Any = None,
register_sys_signals: bool = True,
access_log: Optional[bool] = None,
**kwargs: Any
**kwargs: Any,
) -> None:
"""Run the HTTP Server and listen until keyboard interrupt or term
signal. On termination, drain connections before closing.

View File

@ -345,13 +345,17 @@ class ASGIApp:
await self.transport.send(self.response_start)
self.response_start = None
if self.response_body:
data = self.response_body + data if data else self.response_body
data = (
self.response_body + data if data else self.response_body
)
self.response_body = None
await self.transport.send({
await self.transport.send(
{
"type": "http.response.body",
"body": data.encode() if hasattr(data, "encode") else data,
"more_body": not end_stream,
})
}
)
async def __call__(self) -> None:
"""

View File

@ -28,6 +28,7 @@ class Stage(Enum):
HTTP_CONTINUE = b"HTTP/1.1 100 Continue\r\n\r\n"
class Http:
__slots__ = [
"_send",
@ -47,6 +48,7 @@ class Http:
"response_func",
"response_bytes_left",
]
def __init__(self, protocol):
self._send = protocol.send
self._receive_more = protocol.receive_more
@ -193,9 +195,9 @@ class Http:
data, size, end_stream = b"", 0, True
headers.pop("content-length", None)
headers.pop("transfer-encoding", None)
#raise ServerError(
# raise ServerError(
# f"A {status} response may only have headers, no body."
#)
# )
elif self.head_only and "content-length" in headers:
self.response_func = None
elif end_stream:
@ -344,13 +346,15 @@ class Http:
del buf[:size]
self.request_bytes_left -= size
self.protocol._total_request_size += size
if self.protocol._total_request_size > self.protocol.request_max_size:
if (
self.protocol._total_request_size
> self.protocol.request_max_size
):
self.keep_alive = False
raise PayloadTooLarge("Payload Too Large")
return data
return None
# Response methods
def respond(self, response):

View File

@ -17,8 +17,8 @@ from sanic.headers import (
parse_host,
parse_xforwarded,
)
from sanic.response import HTTPResponse
from sanic.log import error_logger, logger
from sanic.response import HTTPResponse
try:
@ -132,12 +132,14 @@ class Request:
Custom context is now stored in `request.custom_context.yourkey`"""
setattr(self.ctx, key, value)
def respond(self, status=200, headers=None, content_type=DEFAULT_HTTP_CONTENT_TYPE):
def respond(
self, status=200, headers=None, content_type=DEFAULT_HTTP_CONTENT_TYPE
):
return self.stream.respond(
status if isinstance(status, HTTPResponse) else HTTPResponse(
status=status,
headers=headers,
content_type=content_type,
status
if isinstance(status, HTTPResponse)
else HTTPResponse(
status=status, headers=headers, content_type=content_type,
)
)

View File

@ -71,13 +71,12 @@ class StreamingHTTPResponse(BaseHTTPResponse):
async def stream(self, request):
self.send = request.respond(
self.status,
self.headers,
self.content_type,
self.status, self.headers, self.content_type,
).send
await self.streaming_fn(self)
await self.send(end_stream=True)
class HTTPResponse(BaseHTTPResponse):
__slots__ = ("body", "status", "content_type", "headers", "_cookies")

View File

@ -183,7 +183,14 @@ class HttpProtocol(asyncio.Protocol):
):
self._http.exception = ServiceUnavailable("Response Timeout")
else:
interval = min(self.keep_alive_timeout, self.request_timeout, self.response_timeout) / 2
interval = (
min(
self.keep_alive_timeout,
self.request_timeout,
self.response_timeout,
)
/ 2
)
self.loop.call_later(max(0.1, interval), self.check_timeouts)
return
self._task.cancel()
@ -265,6 +272,7 @@ class HttpProtocol(asyncio.Protocol):
except:
logger.exception("protocol.data_received")
def trigger_events(events, loop):
"""Trigger event callbacks (functions or async)

View File

@ -41,7 +41,9 @@ class SanicTestClient:
url, verify=False, *args, **kwargs
)
except httpx.exceptions.ConnectionClosed:
logger.error(f"{method.upper()} {url} broken HTTP, response is None!")
logger.error(
f"{method.upper()} {url} broken HTTP, response is None!"
)
return None
except NameError:
raise Exception(response.status_code)