2424SIGIL = ord (b":" )
2525INFORMATIONAL_START = ord (b"1" )
2626
27- HEADER_UNPERMITTED_CHARACTERS = frozenset ([
28- b"\r " ,
29- b"\n " ,
30- b"\x00 " ,
31- ])
32-
3327
3428# A set of headers that are hop-by-hop or connection-specific and thus
3529# forbidden in HTTP/2. This list comes from RFC 7540 § 8.1.2.2.
@@ -207,7 +201,7 @@ def validate_headers(headers: Iterable[Header], hdr_validation_flags: HeaderVali
207201 # For example, we avoid tuple unpacking in loops because it represents a
208202 # fixed cost that we don't want to spend, instead indexing into the header
209203 # tuples.
210- headers = _reject_unpermitted_characters (
204+ headers = _reject_illegal_characters (
211205 headers , hdr_validation_flags ,
212206 )
213207 headers = _reject_empty_header_names (
@@ -234,20 +228,35 @@ def validate_headers(headers: Iterable[Header], hdr_validation_flags: HeaderVali
234228 return _check_path_header (headers , hdr_validation_flags )
235229
236230
237- def _reject_unpermitted_characters (headers : Iterable [Header ],
238- hdr_validation_flags : HeaderValidationFlags ) -> Generator [Header , None , None ]:
231+ def _reject_illegal_characters (headers : Iterable [Header ],
232+ hdr_validation_flags : HeaderValidationFlags ) -> Generator [Header , None , None ]:
239233 """
240- Raises a ProtocolError if any header names or values contain unpermitted characters.
241- See RFC 7540 , section 10.3 and 8.1.2.6 .
234+ Raises a ProtocolError if any header names or values contain illegal characters.
235+ See RFC 9113 , section 8.2.1 .
242236 """
243237 for header in headers :
244- for c in HEADER_UNPERMITTED_CHARACTERS :
245- if c in header [0 ]:
246- msg = f"Unpermitted character '{ c } ' in header name: { header [0 ]!r} "
238+ # > A field name MUST NOT contain characters in the ranges 0x00-0x20, 0x41-0x5a,
239+ # > or 0x7f-0xff (all ranges inclusive).
240+ for c in header [0 ]:
241+ if c <= 0x20 or 0x41 <= c <= 0x5a or 0x7f <= c :
242+ msg = f"Illegal character '{ chr (c )} ' in header name: { header [0 ]!r} "
247243 raise ProtocolError (msg )
248- if c in header [1 ]:
249- msg = f"Unpermitted character '{ c } ' in header value: { header [1 ]!r} "
244+
245+ # > With the exception of pseudo-header fields (Section 8.3), which have a name
246+ # > that starts with a single colon, field names MUST NOT include a colon (ASCII
247+ # > COLON, 0x3a).
248+ if header [0 ].find (b":" , 1 ) != - 1 :
249+ msg = f"Illegal character ':' in header name: { header [0 ]!r} "
250+ raise ProtocolError (msg )
251+
252+ # > A field value MUST NOT contain the zero value (ASCII NUL, 0x00), line feed
253+ # > (ASCII LF, 0x0a), or carriage return (ASCII CR, 0x0d) at any position.
254+ for c in header [1 ]:
255+ if c == 0 or c == 0x0a or c == 0x0d :
256+ msg = f"Illegal character '{ chr (c )} ' in header value: { header [1 ]!r} "
250257 raise ProtocolError (msg )
258+
259+ # Surrounding whitespace is enforced in `_reject_surrounding_whitespace`.
251260 yield header
252261
253262
0 commit comments