35 % speedup in HTTP/1.1 response formatting (not so much overall effect).

This commit is contained in:
L. Kärkkäinen 2020-03-09 14:35:06 +02:00
parent c86c29e239
commit a0e61ae5c6
3 changed files with 15 additions and 12 deletions

View File

@ -175,14 +175,17 @@ 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 = [
b"HTTP/1.1 %d %b\r\n" % (status, STATUS_CODES.get(status, b"UNKNOWN"))
for status in range(1000)
]
def format_http1_response( def format_http1_response(status: int, headers: HeaderBytesIterable) -> bytes:
status: int, headers: HeaderBytesIterable, body=b"" """Format a HTTP/1.1 response header."""
) -> bytes: # Note: benchmarks show that here bytes concat is faster than bytearray,
"""Format a full HTTP/1.1 response.""" # b"".join() or %-formatting. %timeit any changes you make.
return b"HTTP/1.1 %d %b\r\n%b\r\n%b" % ( ret = _HTTP1_STATUSLINES[status]
status, for h in headers:
STATUS_CODES.get(status, b"UNKNOWN"), ret += b"%b: %b\r\n" % h
b"".join(b"%b: %b\r\n" % h for h in headers), ret += b"\r\n"
body, return ret
)

View File

@ -222,7 +222,7 @@ class Http:
data = b"" data = b""
self.response_func = self.head_response_ignored self.response_func = self.head_response_ignored
headers["connection"] = "keep-alive" if self.keep_alive else "close" headers["connection"] = "keep-alive" if self.keep_alive else "close"
ret = format_http1_response(status, res.processed_headers, data) ret = format_http1_response(status, res.processed_headers) + data
# Send a 100-continue if expected and not Expectation Failed # Send a 100-continue if expected and not Expectation Failed
if self.expecting_continue: if self.expecting_continue:
self.expecting_continue = False self.expecting_continue = False

View File

@ -47,7 +47,7 @@ class BaseHTTPResponse:
headers += (b"content-type", self.content_type.encode()), headers += (b"content-type", self.content_type.encode()),
for name, value in self.headers.items(): for name, value in self.headers.items():
name = f"{name}".lower() name = f"{name}".lower()
if name.lower() == "set-cookie": if name == "set-cookie":
cookies[value.key] = value cookies[value.key] = value
else: else:
headers += (name.encode("ascii"), f"{value}".encode()), headers += (name.encode("ascii"), f"{value}".encode()),