Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure aiohttp headers matchable from both session and request #158

Merged
merged 4 commits into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
Loading