Skip to content

Commit a6bc6d1

Browse files
00200200csernazs
authored andcommitted
Match header comparator names case-insensitively
1 parent c12273c commit a6bc6d1

2 files changed

Lines changed: 38 additions & 5 deletions

File tree

‎pytest_httpserver/httpserver.py‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,15 @@ def default_header_value_matcher(actual: str | None, expected: str) -> bool:
162162
return actual == expected
163163

164164
def __call__(self, header_name: str, actual: str | None, expected: str) -> bool:
165+
for name, matcher in self.matchers.items():
166+
if name.lower() == header_name.lower():
167+
return matcher(actual, expected)
168+
165169
try:
166-
matcher = self.matchers[header_name]
170+
if isinstance(self.matchers, defaultdict) and self.matchers.default_factory is not None:
171+
matcher = self.matchers.default_factory()
172+
else:
173+
matcher = self.matchers[header_name]
167174
except KeyError:
168175
raise NoMethodFoundForMatchingHeaderValueError(
169176
"No method found for matching header value: {}".format(header_name)

‎tests/test_headers.py‎

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,40 @@
11
import http.client
2+
from collections import defaultdict
23

4+
import pytest
35
import requests
46
from werkzeug.datastructures import Headers
57
from werkzeug.http import parse_dict_header
68

79
from pytest_httpserver import HTTPServer
810
from pytest_httpserver.httpserver import HeaderValueMatcher
11+
from pytest_httpserver.httpserver import NoMethodFoundForMatchingHeaderValueError
912

1013

11-
def test_custom_headers(httpserver: HTTPServer):
12-
headers_with_values_in_direct_order = {"Custom": 'Scheme key0="value0", key1="value1"'}
14+
def test_header_matcher_fallback_does_not_cache_header_names():
15+
matchers = defaultdict(lambda: HeaderValueMatcher.default_header_value_matcher)
16+
matcher = HeaderValueMatcher(matchers)
17+
18+
assert matcher("x-custom", "value", "value")
19+
assert not matcher("x-custom", "VALUE", "value")
20+
assert not matchers
21+
22+
matchers["X-Custom"] = lambda actual, expected: actual == expected.upper()
23+
assert matcher("x-custom", "VALUE", "value")
24+
25+
26+
def test_header_matcher_without_default():
27+
matcher = HeaderValueMatcher({"x-custom": HeaderValueMatcher.default_header_value_matcher})
28+
29+
assert matcher("X-CUSTOM", "value", "value")
30+
assert not matcher("X-CUSTOM", "VALUE", "value")
31+
with pytest.raises(NoMethodFoundForMatchingHeaderValueError, match="X-Missing"):
32+
matcher("X-Missing", "value", "value")
33+
34+
35+
@pytest.mark.parametrize("header_name", ["Custom", "custom", "CUSTOM"])
36+
def test_custom_headers(httpserver: HTTPServer, header_name: str):
37+
headers_with_values_in_direct_order = {header_name: 'Scheme key0="value0", key1="value1"'}
1338
httpserver.expect_request(uri="/", headers=headers_with_values_in_direct_order).respond_with_data("OK")
1439
response = requests.get(httpserver.url_for("/"), headers=headers_with_values_in_direct_order)
1540
assert response.status_code == 200
@@ -42,9 +67,10 @@ def custom_header_value_matcher(actual: str, expected: str) -> bool:
4267

4368

4469
# See https://en.wikipedia.org/wiki/Digest_access_authentication
45-
def test_authorization_headers(httpserver: HTTPServer):
70+
@pytest.mark.parametrize("header_name", ["Authorization", "authorization", "AUTHORIZATION", "aUtHoRiZaTiOn"])
71+
def test_authorization_headers(httpserver: HTTPServer, header_name: str):
4672
headers_with_values_in_direct_order = {
47-
"Authorization": (
73+
header_name: (
4874
'Digest username="Mufasa",'
4975
'realm="testrealm@host.com",'
5076
'nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",'

0 commit comments

Comments
 (0)