This commit is contained in:
L. Kärkkäinen 2020-03-09 15:44:06 +02:00
parent a9d984e2f8
commit 9dc2ec966c
5 changed files with 14 additions and 20 deletions

View File

@ -6,11 +6,8 @@ from typing import (
Any, Any,
Awaitable, Awaitable,
Callable, Callable,
Dict,
List,
MutableMapping, MutableMapping,
Optional, Optional,
Tuple,
Union, Union,
) )
from urllib.parse import quote from urllib.parse import quote
@ -18,10 +15,8 @@ from urllib.parse import quote
import sanic.app # noqa import sanic.app # noqa
from sanic.compat import Header from sanic.compat import Header
from sanic.exceptions import InvalidUsage, ServerError from sanic.exceptions import InvalidUsage
from sanic.log import logger
from sanic.request import Request from sanic.request import Request
from sanic.response import StreamingHTTPResponse
from sanic.websocket import WebSocketConnection from sanic.websocket import WebSocketConnection
@ -278,11 +273,13 @@ class ASGIApp:
async def send(self, data, end_stream): async def send(self, data, end_stream):
if self.response: if self.response:
response, self.response = self.response, None response, self.response = self.response, None
await self.transport.send({ await self.transport.send(
"type": "http.response.start", {
"status": response.status, "type": "http.response.start",
"headers": response.processed_headers, "status": response.status,
}) "headers": response.processed_headers,
}
)
response_body = getattr(response, "body", None) response_body = getattr(response, "body", None)
if response_body: if response_body:
data = response_body + data if data else response_body data = response_body + data if data else response_body

View File

@ -175,11 +175,13 @@ def parse_host(host: str) -> Tuple[Optional[str], Optional[int]]:
host, port = m.groups() host, port = m.groups()
return host.lower(), int(port) if port is not None else None return host.lower(), int(port) if port is not None else None
_HTTP1_STATUSLINES = [ _HTTP1_STATUSLINES = [
b"HTTP/1.1 %d %b\r\n" % (status, STATUS_CODES.get(status, b"UNKNOWN")) b"HTTP/1.1 %d %b\r\n" % (status, STATUS_CODES.get(status, b"UNKNOWN"))
for status in range(1000) for status in range(1000)
] ]
def format_http1_response(status: int, headers: HeaderBytesIterable) -> bytes: def format_http1_response(status: int, headers: HeaderBytesIterable) -> bytes:
"""Format a HTTP/1.1 response header.""" """Format a HTTP/1.1 response header."""
# Note: benchmarks show that here bytes concat is faster than bytearray, # Note: benchmarks show that here bytes concat is faster than bytearray,

View File

@ -111,9 +111,7 @@ class Request:
# This logic of determining which response to use is subject to change # This logic of determining which response to use is subject to change
if response is None: if response is None:
response = self.stream.response or HTTPResponse( response = self.stream.response or HTTPResponse(
status=status, status=status, headers=headers, content_type=content_type,
headers=headers,
content_type=content_type,
) )
# Connect the response and return it # Connect the response and return it
return self.stream.respond(response) return self.stream.respond(response)

View File

@ -43,10 +43,7 @@ class BaseHTTPResponse:
self.headers.setdefault("content-type", self.content_type) self.headers.setdefault("content-type", self.content_type)
# Encode headers into bytes # Encode headers into bytes
return ( return (
( (name.encode("ascii"), f"{value}".encode(errors="surrogateescape"))
name.encode("ascii"),
f"{value}".encode("utf-8", errors="surrogateescape")
)
for name, value in self.headers.items() for name, value in self.headers.items()
) )
@ -64,6 +61,7 @@ class BaseHTTPResponse:
class StreamingHTTPResponse(BaseHTTPResponse): class StreamingHTTPResponse(BaseHTTPResponse):
"""Old style streaming response. Use `request.respond()` instead of this in """Old style streaming response. Use `request.respond()` instead of this in
new code to avoid the callback.""" new code to avoid the callback."""
__slots__ = ( __slots__ = (
"protocol", "protocol",
"streaming_fn", "streaming_fn",
@ -101,7 +99,6 @@ class StreamingHTTPResponse(BaseHTTPResponse):
await super().send(*args, **kwargs) await super().send(*args, **kwargs)
class HTTPResponse(BaseHTTPResponse): class HTTPResponse(BaseHTTPResponse):
__slots__ = ("body", "status", "content_type", "headers", "_cookies") __slots__ = ("body", "status", "content_type", "headers", "_cookies")

View File

@ -15,6 +15,7 @@ from aiofiles import os as async_os
from sanic.response import ( from sanic.response import (
HTTPResponse, HTTPResponse,
StreamingHTTPResponse, StreamingHTTPResponse,
empty,
file, file,
file_stream, file_stream,
json, json,
@ -22,7 +23,6 @@ from sanic.response import (
stream, stream,
text, text,
) )
from sanic.response import empty
from sanic.server import HttpProtocol from sanic.server import HttpProtocol
from sanic.testing import HOST, PORT from sanic.testing import HOST, PORT