From 50f96ff029ca426787497479b11708c0d21a9455 Mon Sep 17 00:00:00 2001 From: Adam Hopkins Date: Wed, 17 Feb 2021 16:54:25 +0200 Subject: [PATCH] Add raw header info to request object --- sanic/http.py | 6 ++++-- sanic/request.py | 22 +++++++++++++++++++++- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/sanic/http.py b/sanic/http.py index addebfd6b9..39e88c1687 100644 --- a/sanic/http.py +++ b/sanic/http.py @@ -148,7 +148,7 @@ async def http1_request_header(self): # Parse header content try: raw_headers = buf[:pos].decode(errors="surrogateescape") - reqline, *raw_headers = raw_headers.split("\r\n") + reqline, *split_headers = raw_headers.split("\r\n") method, self.url, protocol = reqline.split(" ") if protocol == "HTTP/1.1": @@ -162,7 +162,7 @@ async def http1_request_header(self): request_body = False headers = [] - for name, value in (h.split(":", 1) for h in raw_headers): + for name, value in (h.split(":", 1) for h in split_headers): name, value = h = name.lower(), value.lstrip() if name in ("content-length", "transfer-encoding"): @@ -181,6 +181,8 @@ async def http1_request_header(self): request = self.protocol.request_class( url_bytes=self.url.encode(), headers=headers_instance, + raw_headers=raw_headers, + request_line=reqline, version=protocol[5:], method=method, transport=self.protocol.transport, diff --git a/sanic/request.py b/sanic/request.py index 717f179cb5..5f754e4948 100644 --- a/sanic/request.py +++ b/sanic/request.py @@ -4,6 +4,7 @@ from collections import defaultdict, namedtuple from http.cookies import SimpleCookie from types import SimpleNamespace +from typing import Optional from urllib.parse import parse_qs, parse_qsl, unquote, urlunparse from httptools import parse_url # type: ignore @@ -56,6 +57,7 @@ class Request: "_ip", "_parsed_url", "_port", + "_raw_headers", "_remote_addr", "_socket", "_match_info", @@ -74,6 +76,7 @@ class Request: "parsed_json", "parsed_forwarded", "raw_url", + "request_line", "request_middleware_started", "stream", "transport", @@ -81,7 +84,17 @@ class Request: "version", ) - def __init__(self, url_bytes, headers, version, method, transport, app): + def __init__( + self, + url_bytes, + headers, + version, + method, + transport, + app, + raw_headers: Optional[str] = None, + request_line: Optional[str] = None, + ): self.raw_url = url_bytes # TODO: Content-Encoding detection self._parsed_url = parse_url(url_bytes) @@ -92,6 +105,8 @@ def __init__(self, url_bytes, headers, version, method, transport, app): self.version = version self.method = method self.transport = transport + self._raw_headers = raw_headers + self.request_line = request_line # Init but do not inhale self.body = b"" @@ -157,6 +172,11 @@ async def receive_body(self): if not self.body: self.body = b"".join([data async for data in self.stream]) + @property + def raw_headers(self): + _, headers = self._raw_headers.split("\r\n", 1) + return headers + @property def id(self): if not self._id: