From a0e61ae5c6006970ea328e6bde595c54a398c1bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=2E=20K=C3=A4rkk=C3=A4inen?= Date: Mon, 9 Mar 2020 14:35:06 +0200 Subject: [PATCH] 35 % speedup in HTTP/1.1 response formatting (not so much overall effect). --- sanic/headers.py | 23 +++++++++++++---------- sanic/http.py | 2 +- sanic/response.py | 2 +- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/sanic/headers.py b/sanic/headers.py index 74a797ee..3dc729a9 100644 --- a/sanic/headers.py +++ b/sanic/headers.py @@ -175,14 +175,17 @@ def parse_host(host: str) -> Tuple[Optional[str], Optional[int]]: host, port = m.groups() 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( - status: int, headers: HeaderBytesIterable, body=b"" -) -> bytes: - """Format a full HTTP/1.1 response.""" - return b"HTTP/1.1 %d %b\r\n%b\r\n%b" % ( - status, - STATUS_CODES.get(status, b"UNKNOWN"), - b"".join(b"%b: %b\r\n" % h for h in headers), - body, - ) +def format_http1_response(status: int, headers: HeaderBytesIterable) -> bytes: + """Format a HTTP/1.1 response header.""" + # Note: benchmarks show that here bytes concat is faster than bytearray, + # b"".join() or %-formatting. %timeit any changes you make. + ret = _HTTP1_STATUSLINES[status] + for h in headers: + ret += b"%b: %b\r\n" % h + ret += b"\r\n" + return ret diff --git a/sanic/http.py b/sanic/http.py index 29821b07..5be70957 100644 --- a/sanic/http.py +++ b/sanic/http.py @@ -222,7 +222,7 @@ class Http: data = b"" self.response_func = self.head_response_ignored 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 if self.expecting_continue: self.expecting_continue = False diff --git a/sanic/response.py b/sanic/response.py index 47f04b39..c07f38d7 100644 --- a/sanic/response.py +++ b/sanic/response.py @@ -47,7 +47,7 @@ class BaseHTTPResponse: headers += (b"content-type", self.content_type.encode()), for name, value in self.headers.items(): name = f"{name}".lower() - if name.lower() == "set-cookie": + if name == "set-cookie": cookies[value.key] = value else: headers += (name.encode("ascii"), f"{value}".encode()),