Skip to content

Commit

Permalink
Rework check_header_validity for bytes/str subclasses
Browse files Browse the repository at this point in the history
  • Loading branch information
nateprewitt committed Jun 10, 2022
1 parent 9d3b79a commit 66fcc9c
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 17 deletions.
30 changes: 13 additions & 17 deletions requests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -1030,26 +1030,22 @@ def check_header_validity(header):
:param header: tuple, in the format (name, value).
"""
name, value = header

supported_types = tuple(HEADER_VALIDATORS.keys())
for part in header:
if not isinstance(part, supported_types):
for n, part in enumerate(header):
if isinstance(part, str):
validator = HEADER_VALIDATORS[str][n]
elif isinstance(part, bytes):
validator = HEADER_VALIDATORS[bytes][n]
else:
raise InvalidHeader(
f"Header part ({part!r}) from {{{name!r}: {value!r}}} must be "
f"of type str or bytes, not {type(part)}"
f"Header part ({part!r}) from {header} "
f"must be of type str or bytes, not {type(part)}"
)

_validate_header_part(name, "name", HEADER_VALIDATORS[type(name)][0])
_validate_header_part(value, "value", HEADER_VALIDATORS[type(value)][1])


def _validate_header_part(header_part, header_kind, validator):
if not validator.match(header_part):
raise InvalidHeader(
f"Invalid leading whitespace, reserved character(s), or return"
f"character(s) in header {header_kind}: {header_part!r}"
)
if not validator.match(part):
raise InvalidHeader(
f"Invalid leading whitespace, reserved character(s), "
f"or return character(s) in header: {part!r}"
)


def urldefragauth(url):
Expand Down
20 changes: 20 additions & 0 deletions tests/test_requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -1747,6 +1747,26 @@ def test_header_no_leading_space(self, httpbin, invalid_header):
with pytest.raises(InvalidHeader):
requests.get(httpbin("get"), headers=invalid_header)

def test_header_with_subclass_types(self, httpbin):
"""If the subclasses does not behave *exactly* like
the base bytes/str classes, this is not supported.
This test is for backwards compatibility.
"""

class MyString(str):
pass

class MyBytes(bytes):
pass

r_str = requests.get(httpbin("get"), headers={MyString("x-custom"): "myheader"})
assert r_str.request.headers["x-custom"] == "myheader"

r_bytes = requests.get(
httpbin("get"), headers={MyBytes(b"x-custom"): b"myheader"}
)
assert r_bytes.request.headers["x-custom"] == b"myheader"

@pytest.mark.parametrize("files", ("foo", b"foo", bytearray(b"foo")))
def test_can_send_objects_with_files(self, httpbin, files):
data = {"a": "this is a string"}
Expand Down

0 comments on commit 66fcc9c

Please sign in to comment.