diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 01ab6ec..3e512e3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -39,8 +39,13 @@ Before creating an issue please make sure that it was not already reported. #### Code 1) Create a new branch based on `develop` branch. + * Optional: create and enable virtualenv: + ``` + python3 -m venv myenv + source myenv/bin/activate + ``` 2) Fetch all dev dependencies. - * Install required python modules using `pip`: **python -m pip install .[testing]** + * Install required python modules using `pip`: **python -m pip install ".[testing]"** 3) Ensure tests are ok by running them using [`pytest`](http://doc.pytest.org/en/latest/index.html). 4) Add your changes. 5) Follow [Black](https://black.readthedocs.io/en/stable/) code formatting. diff --git a/httpx_auth/__init__.py b/httpx_auth/__init__.py index b948ba1..2b2d41d 100644 --- a/httpx_auth/__init__.py +++ b/httpx_auth/__init__.py @@ -1,5 +1,6 @@ from httpx_auth._authentication import ( Basic, + BearerToken, HeaderApiKey, QueryApiKey, SupportMultiAuth, @@ -46,6 +47,7 @@ __all__ = [ "Basic", + "BearerToken", "HeaderApiKey", "QueryApiKey", "OAuth2", diff --git a/httpx_auth/_authentication.py b/httpx_auth/_authentication.py index f251bff..0526752 100644 --- a/httpx_auth/_authentication.py +++ b/httpx_auth/_authentication.py @@ -61,6 +61,18 @@ def auth_flow( yield request +class BearerToken(HeaderApiKey): + """Describes a Bearer Token requests authentication.""" + + def __init__(self, token: str): + """ + :param token: The Bearer token that will be sent. + """ + if not token: + raise Exception("Token is mandatory.") + super().__init__(f"Bearer {token}", "Authorization") + + class QueryApiKey(httpx.Auth, SupportMultiAuth): """Describes an API Key requests authentication.""" diff --git a/pyproject.toml b/pyproject.toml index 9f68ced..6f240c1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,6 +43,7 @@ issues = "https://github.com/Colin-b/httpx_auth/issues" [project.optional-dependencies] testing = [ + "pytest==8.3.4", # Used to generate test tokens "pyjwt==2.*", # Used to mock httpx @@ -55,6 +56,11 @@ testing = [ "pytest-asyncio==0.25.*", ] +[tool.setuptools] +py-modules = [ + "httpx_auth" +] + [tool.setuptools.dynamic] version = {attr = "httpx_auth.version.__version__"} @@ -62,5 +68,3 @@ version = {attr = "httpx_auth.version.__version__"} filterwarnings = [ "error", ] -# Silence deprecation warnings about option "asyncio_default_fixture_loop_scope" -asyncio_default_fixture_loop_scope = "function" diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000..54462f5 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,3 @@ +[pytest] +asyncio_mode = auto +asyncio_default_fixture_loop_scope = "function" diff --git a/tests/bearer/__init__.py b/tests/bearer/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/bearer/test_bearer.py b/tests/bearer/test_bearer.py new file mode 100644 index 0000000..2c5db3e --- /dev/null +++ b/tests/bearer/test_bearer.py @@ -0,0 +1,23 @@ +from pytest_httpx import HTTPXMock +import httpx +import pytest + +import httpx_auth + + +def test_bearer_requires_atoken(): + with pytest.raises(Exception) as exception_info: + httpx_auth.BearerToken(None) + assert str(exception_info.value) == "Token is mandatory." + +def test_bearer_token_is_sent(httpx_mock: HTTPXMock): + auth = httpx_auth.BearerToken("my_token") + + httpx_mock.add_response( + url="https://authorized_only", + method="GET", + match_headers={"Authorization": "Bearer my_token"}, + ) + + with httpx.Client() as client: + client.get("https://authorized_only", auth=auth)