import http.client import requests from werkzeug.datastructures import Headers from werkzeug.http import parse_dict_header from pytest_httpserver import HTTPServer from pytest_httpserver.httpserver import HeaderValueMatcher def test_custom_headers(httpserver: HTTPServer): headers_with_values_in_direct_order = {"Custom": 'Scheme key0="value0", key1="value1"'} httpserver.expect_request(uri="/", headers=headers_with_values_in_direct_order).respond_with_data("OK") response = requests.get(httpserver.url_for("/"), headers=headers_with_values_in_direct_order) assert response.status_code == 200 assert response.text == "OK" # By default different order of items in header value dicts means different header values headers_with_values_in_modified_order = {"Custom": 'Scheme key1="value1", key0="value0"'} response = requests.get(httpserver.url_for("/"), headers=headers_with_values_in_modified_order) assert response.status_code == 500 # Define header_value_matcher that ignores the order of items in header value dict def custom_header_value_matcher(actual: str, expected: str) -> bool: actual_scheme, _, actual_dict_str = actual.partition(" ") expected_scheme, _, expected_dict_str = expected.partition(" ") actual_dict = parse_dict_header(actual_dict_str) expected_dict = parse_dict_header(expected_dict_str) return actual_scheme == expected_scheme and actual_dict == expected_dict matchers = HeaderValueMatcher.DEFAULT_MATCHERS.copy() # type: ignore matchers["Custom"] = custom_header_value_matcher header_value_matcher = HeaderValueMatcher(matchers) httpserver.handlers.clear() httpserver.expect_request( uri="/", headers=headers_with_values_in_direct_order, header_value_matcher=header_value_matcher ).respond_with_data("OK") response = requests.get(httpserver.url_for("/"), headers=headers_with_values_in_modified_order) assert response.status_code == 200 assert response.text == "OK" # See https://en.wikipedia.org/wiki/Digest_access_authentication def test_authorization_headers(httpserver: HTTPServer): headers_with_values_in_direct_order = { "Authorization": ( 'Digest username="Mufasa",' 'realm="testrealm@host.com",' 'nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",' 'uri="/dir/index.html",' "qop=auth," "nc=00000001," 'cnonce="0a4f113b",' 'response="6629fae49393a05397450978507c4ef1",' 'opaque="5ccc069c403ebaf9f0171e9517f40e41"' ) } httpserver.expect_request(uri="/", headers=headers_with_values_in_direct_order).respond_with_data("OK") response = requests.get(httpserver.url_for("/"), headers=headers_with_values_in_direct_order) assert response.status_code == 200 assert response.text == "OK" headers_with_values_in_modified_order = { "Authorization": ( "Digest qop=auth," 'username="Mufasa",' 'nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",' 'uri="/dir/index.html",' "nc=00000001," 'realm="testrealm@host.com",' 'response="6629fae49393a05397450978507c4ef1",' 'cnonce="0a4f113b",' 'opaque="5ccc069c403ebaf9f0171e9517f40e41"' ) } response = requests.get(httpserver.url_for("/"), headers=headers_with_values_in_modified_order) assert response.status_code == 200 assert response.text == "OK" def test_header_one_key_multiple_values(httpserver: HTTPServer): httpserver.expect_request(uri="/t1").respond_with_data(headers=[("X-Foo", "123"), ("X-Foo", "456")]) httpserver.expect_request(uri="/t2").respond_with_data(headers={"X-Foo": ["123", "456"]}) headers = Headers() headers.add("X-Foo", "123") headers.add("X-Foo", "456") httpserver.expect_request(uri="/t3").respond_with_data(headers=headers) for uri in ("/t1", "/t2", "/t3"): conn = http.client.HTTPConnection("localhost:{}".format(httpserver.port)) conn.request("GET", uri) response = conn.getresponse() conn.close() assert response.status == 200 assert response.headers.get_all("X-Foo") == ["123", "456"]