Skip to content

Commit

Permalink
Ensure aiohttp headers matchable from both session and request (#158)
Browse files Browse the repository at this point in the history
* Prevent aiohttp request headers from overriding session headers in matcher

* Bump to 2.1.3

* Add test for unmatched headers

* Update date in changelog
  • Loading branch information
sarayourfriend authored Dec 16, 2024
1 parent 94dede1 commit 4d1083e
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 9 deletions.
5 changes: 5 additions & 0 deletions History.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
History
=======

v2.1.3 / 2024-12-16
-------------------------

* Ensure aiohttp headers can be matched from both the session and request in the same matcher

v2.1.2 / 2024-11-21
-------------------------

Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ readme = "README.rst"
license = "MIT"
authors = [
{ name = "Tomas Aparicio", email = "[email protected]" },
{ name = "Sara Marcondes", email = "[email protected]" },
]
classifiers = [
"Development Status :: 5 - Production/Stable",
Expand Down
2 changes: 1 addition & 1 deletion src/pook/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,4 @@
__license__ = "MIT"

# Current version
__version__ = "2.1.2"
__version__ = "2.1.3"
11 changes: 4 additions & 7 deletions src/pook/interceptors/aiohttp.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,18 +58,15 @@ def set_headers(self, req, headers) -> None:
# ``pook.request`` only allows a dict, so we need to map the iterable to the matchable interface
if headers:
if isinstance(headers, Mapping):
req.headers = headers
req.headers.update(**headers)
else:
req_headers: dict[str, str] = {}
# If it isn't a mapping, then its an Iterable[Tuple[Union[str, istr], str]]
for req_header, req_header_value in headers:
normalised_header = req_header.lower()
if normalised_header in req_headers:
req_headers[normalised_header] += f", {req_header_value}"
if normalised_header in req.headers:
req.headers[normalised_header] += f", {req_header_value}"
else:
req_headers[normalised_header] = req_header_value

req.headers = req_headers
req.headers[normalised_header] = req_header_value

async def _on_request(
self,
Expand Down
28 changes: 28 additions & 0 deletions tests/unit/interceptors/aiohttp_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,31 @@ async def test_client_headers(httpbin):
res = await session.get(httpbin + "/status/404")
assert res.status == 200
assert await res.read() == b"hello from pook"


@pytest.mark.asyncio
async def test_client_headers_merged(httpbin):
"""Headers set on the client should be matched even if request-specific headers are sent."""
pook.get(httpbin + "/status/404").header("x-pook", "hello").reply(200).body(
"hello from pook"
)
async with aiohttp.ClientSession(headers={"x-pook": "hello"}) as session:
res = await session.get(
httpbin + "/status/404", headers={"x-pook-secondary": "xyz"}
)
assert res.status == 200
assert await res.read() == b"hello from pook"


@pytest.mark.asyncio
async def test_client_headers_both_session_and_request(httpbin):
"""Headers should be matchable from both the session and request in the same matcher"""
pook.get(httpbin + "/status/404").header("x-pook-session", "hello").header(
"x-pook-request", "hey"
).reply(200).body("hello from pook")
async with aiohttp.ClientSession(headers={"x-pook-session": "hello"}) as session:
res = await session.get(
httpbin + "/status/404", headers={"x-pook-request": "hey"}
)
assert res.status == 200
assert await res.read() == b"hello from pook"
10 changes: 9 additions & 1 deletion tests/unit/interceptors/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ def test_header_sent(self, url_404):
assert body == b"hello from pook"

@pytest.mark.pook
def test_mocked_resposne_headers(self, url_404):
def test_mocked_response_headers(self, url_404):
"""Mocked response headers are appropriately returned."""
pook.get(url_404).reply(200).header("x-hello", "from pook")

Expand Down Expand Up @@ -238,3 +238,11 @@ def test_mutli_value_response_headers(self, url_404):

assert status == 200
assert headers["x-hello"] == "from pook, another time"

@pytest.mark.pook(allow_pending_mocks=True)
def test_unmatched_headers_none_sent(self, url_404):
"""Header matching will run, but not match, on requests that send no headers."""
pook.get(url_404).header("x-hello", "from pook").reply(200)

with pytest.raises(PookNoMatches):
self.make_request("GET", url_404)

0 comments on commit 4d1083e

Please sign in to comment.