Skip to content

Commit 5cec3bd

Browse files
authored
feat: support OAuth2 via HTTP client middleware instead of subclass (#252)
* feat: support OAuth2 via HTTP client middleware instead of subclass * docs: update CHANGELOG.md
1 parent beac73d commit 5cec3bd

File tree

4 files changed

+31
-22
lines changed

4 files changed

+31
-22
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66

77
## [Unreleased]
88

9+
### Changed
10+
11+
- Handle OAuth2 support via middleware of the HTTP client instead of a subclass ([252](https://github.com/stac-utils/stac-asset/pull/252))
12+
913
## [0.4.6] - 2024-11-05
1014

1115
### Added

pyproject.toml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@ requires-python = ">=3.10"
1919
dependencies = [
2020
"aiofiles>=23.1.0",
2121
"aiobotocore>=2.5.0",
22-
"aiohttp>=3.8.4",
22+
"aiohttp~=3.12",
2323
"pystac>=1.8.4",
2424
"python-dateutil>=2.7.0",
2525
"yarl>=1.9.2",
26-
"aiohttp-oauth2-client>=1.0.2",
26+
"aiohttp-oauth2-client~=2.0",
2727
"aiohttp-retry>=2.8.3",
2828
]
2929

@@ -77,7 +77,6 @@ ignore_missing_imports = true
7777

7878
[tool.pytest.ini_options]
7979
filterwarnings = [
80-
"ignore:inheritance class OAuth2Client from ClientSession is discouraged:DeprecationWarning", # https://github.com/VITObelgium/aiohttp-oauth2-client/issues/1
8180
"ignore:datetime.datetime.utcnow.*:DeprecationWarning:botocore", # https://github.com/boto/boto3/issues/3889
8281
]
8382
asyncio_default_fixture_loop_scope = "function"

src/stac_asset/http_client.py

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from typing import TypeVar
77

88
from aiohttp import ClientError, ClientSession, ClientTimeout
9-
from aiohttp_oauth2_client.client import OAuth2Client
9+
from aiohttp_oauth2_client.middleware import OAuth2Middleware
1010
from aiohttp_oauth2_client.models.grant import GrantType
1111
from aiohttp_retry import JitterRetry, RetryClient
1212
from aiohttp_retry.types import ClientType
@@ -64,6 +64,7 @@ async def from_config(cls: type[T], config: Config) -> T:
6464
""" # noqa: E501
6565
# TODO add basic auth
6666
timeout = ClientTimeout(total=config.http_client_timeout)
67+
middlewares = []
6768
if config.oauth2_grant is not None:
6869
if GrantType.DEVICE_CODE.endswith(config.oauth2_grant):
6970
from aiohttp_oauth2_client.grant.device_code import DeviceCodeGrant
@@ -112,15 +113,16 @@ async def from_config(cls: type[T], config: Config) -> T:
112113
)
113114
else:
114115
raise ValueError("Unknown grant type")
115-
session = OAuth2Client(grant, timeout=timeout, headers=config.http_headers)
116-
else:
117-
session = ClientSession(timeout=timeout, headers=config.http_headers)
118-
session = RetryClient(
119-
client_session=session,
120-
retry_options=JitterRetry(
121-
attempts=config.http_max_attempts, exceptions={ClientError}
122-
),
123-
)
116+
middlewares.append(OAuth2Middleware(grant))
117+
session = ClientSession(
118+
timeout=timeout, headers=config.http_headers, middlewares=middlewares
119+
)
120+
session = RetryClient(
121+
client_session=session,
122+
retry_options=JitterRetry(
123+
attempts=config.http_max_attempts, exceptions={ClientError}
124+
),
125+
)
124126
return cls(session, config.http_assert_content_type)
125127

126128
def __init__(

tests/test_http_client.py

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import pytest
2-
from aiohttp_oauth2_client.client import OAuth2Client
32
from aiohttp_oauth2_client.grant.authorization_code import AuthorizationCodeGrant
43
from aiohttp_oauth2_client.grant.client_credentials import ClientCredentialsGrant
54
from aiohttp_oauth2_client.grant.device_code import DeviceCodeGrant
65
from aiohttp_oauth2_client.grant.resource_owner_password_credentials import (
76
ResourceOwnerPasswordCredentialsGrant,
87
)
8+
from aiohttp_oauth2_client.middleware import OAuth2Middleware
99

1010
from stac_asset import Config, HttpClient
1111

@@ -33,8 +33,9 @@ async def test_oauth2_device_code_config() -> None:
3333
oauth2_client_id="public",
3434
)
3535
async with await HttpClient.from_config(config) as client:
36-
assert isinstance(client.session, OAuth2Client)
37-
assert isinstance(client.session.grant, DeviceCodeGrant)
36+
middlewares = client.session._client._middlewares
37+
assert isinstance(middlewares[0], OAuth2Middleware)
38+
assert isinstance(middlewares[0].grant, DeviceCodeGrant)
3839

3940

4041
async def test_oauth2_authorization_code_config() -> None:
@@ -46,8 +47,9 @@ async def test_oauth2_authorization_code_config() -> None:
4647
oauth2_pkce=False,
4748
)
4849
async with await HttpClient.from_config(config) as client:
49-
assert isinstance(client.session, OAuth2Client)
50-
assert isinstance(client.session.grant, AuthorizationCodeGrant)
50+
middlewares = client.session._client._middlewares
51+
assert isinstance(middlewares[0], OAuth2Middleware)
52+
assert isinstance(middlewares[0].grant, AuthorizationCodeGrant)
5153

5254

5355
async def test_oauth2_password_config() -> None:
@@ -59,8 +61,9 @@ async def test_oauth2_password_config() -> None:
5961
oauth2_password="secret",
6062
)
6163
async with await HttpClient.from_config(config) as client:
62-
assert isinstance(client.session, OAuth2Client)
63-
assert isinstance(client.session.grant, ResourceOwnerPasswordCredentialsGrant)
64+
middlewares = client.session._client._middlewares
65+
assert isinstance(middlewares[0], OAuth2Middleware)
66+
assert isinstance(middlewares[0].grant, ResourceOwnerPasswordCredentialsGrant)
6467

6568

6669
async def test_oauth2_client_credentials_config() -> None:
@@ -71,5 +74,6 @@ async def test_oauth2_client_credentials_config() -> None:
7174
oauth2_client_secret="secret",
7275
)
7376
async with await HttpClient.from_config(config) as client:
74-
assert isinstance(client.session, OAuth2Client)
75-
assert isinstance(client.session.grant, ClientCredentialsGrant)
77+
middlewares = client.session._client._middlewares
78+
assert isinstance(middlewares[0], OAuth2Middleware)
79+
assert isinstance(middlewares[0].grant, ClientCredentialsGrant)

0 commit comments

Comments
 (0)