# To be used with str.strip() and related methods.
HTTP_WHITESPACE = " \t"
+HTTP_TOKEN_RE = re.compile(r"^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$")
+
@lru_cache(1000)
def _normalize_header(name: str) -> str:
def add(self, name: str, value: str) -> None:
"""Adds a new value for the given key."""
+ if not HTTP_TOKEN_RE.match(name):
+ raise HTTPInputError("Invalid header name %r" % name)
norm_name = _normalize_header(name)
self._last_key = norm_name
if norm_name in self:
def format_timestamp(
- ts: Union[int, float, tuple, time.struct_time, datetime.datetime]
+ ts: Union[int, float, tuple, time.struct_time, datetime.datetime],
) -> str:
"""Formats a timestamp in the format used by HTTP.
headers2 = HTTPHeaders.parse(str(headers))
self.assertEqual(headers, headers2)
+ def test_invalid_header_names(self):
+ invalid_names = [
+ "",
+ "foo bar",
+ "foo\tbar",
+ "foo\nbar",
+ "foo\x00bar",
+ "foo ",
+ " foo",
+ "é",
+ ]
+ for name in invalid_names:
+ headers = HTTPHeaders()
+ with self.assertRaises(HTTPInputError):
+ headers.add(name, "bar")
+
class FormatTimestampTest(unittest.TestCase):
# Make sure that all the input types are supported.