Skip to content

Commit

Permalink
Fix query header clobbering. (#50)
Browse files Browse the repository at this point in the history
Fixes #48

Co-authored-by: Frank Greguska <[email protected]>
  • Loading branch information
chuckwondo and frankinspace authored May 13, 2024
1 parent 18a3536 commit f4aab17
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 10 deletions.
10 changes: 9 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Fixed

- [issues/48](https://github.com/nasa/python_cmr/issues/48) When a query's
`Authorization` header is set via the `bearer_token` or `token` method, other
existing headers are no longer clobbered. However, if multiple calls are made
to `bearer_token` and/or `token`, later calls overwrite the `Authorization`
setting of prior calls (i.e., the last call wins).

## [0.11.0]

Expand Down Expand Up @@ -116,7 +123,8 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
- Prior releases of this software originated from
<https://github.com/jddeal/python-cmr/releases>

[Unreleased]: https://github.com/nasa/python_cmr/compare/v0.10.0...HEAD
[Unreleased]: https://github.com/nasa/python_cmr/compare/v0.11.0...HEAD
[0.11.0]: https://github.com/nasa/python_cmr/compare/v0.10.0...v0.11.0
[0.10.0]: https://github.com/nasa/python_cmr/compare/v0.9.0...v0.10.0
[0.9.0]: https://github.com/nasa/python_cmr/compare/v0.8.0...v0.9.0
[0.8.0]: https://github.com/nasa/python_cmr/compare/v0.7.0...v0.8.0
Expand Down
24 changes: 22 additions & 2 deletions cmr/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@
from .queries import GranuleQuery, CollectionQuery, ToolQuery, ServiceQuery, VariableQuery, CMR_OPS, CMR_UAT, CMR_SIT
from .queries import (
CMR_OPS,
CMR_SIT,
CMR_UAT,
CollectionQuery,
GranuleQuery,
Query,
ServiceQuery,
ToolQuery,
VariableQuery,
)

__all__ = ["GranuleQuery", "CollectionQuery", "ToolQuery", "ServiceQuery", "VariableQuery", "CMR_OPS", "CMR_UAT", "CMR_SIT"]
__all__ = [
"CMR_OPS",
"CMR_SIT",
"CMR_UAT",
"CollectionQuery",
"GranuleQuery",
"Query",
"ServiceQuery",
"ToolQuery",
"VariableQuery",
]
13 changes: 6 additions & 7 deletions cmr/queries.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,11 @@
CMR_SIT = "https://cmr.sit.earthdata.nasa.gov/search/"

DateLike: TypeAlias = Union[str, date, datetime]
DayNightFlag: TypeAlias = Union[
Literal["day"], Literal["night"], Literal["unspecified"]
]
DayNightFlag: TypeAlias = Literal["day", "night", "unspecified"]
FloatLike: TypeAlias = Union[str, SupportsFloat]
PointLike: TypeAlias = Tuple[FloatLike, FloatLike]


class Query:
"""
Base class for all CMR queries.
Expand Down Expand Up @@ -285,7 +284,7 @@ def mode(self, mode: str = CMR_OPS) -> Self:

def token(self, token: str) -> Self:
"""
Add token into authorization headers.
Set the value of this query's `Authorization` header to the given token.
:param token: Token from EDL Echo-Token or NASA Launchpad token.
:returns: self
Expand All @@ -294,13 +293,13 @@ def token(self, token: str) -> Self:
if not token:
return self

self.headers = {'Authorization': token}
self.headers.update({"Authorization": token})

return self

def bearer_token(self, bearer_token: str) -> Self:
"""
Add token into authorization headers.
Set the value of this query's `Authorization` header to the given bearer token.
:param token: Token from EDL token.
:returns: self
Expand All @@ -309,7 +308,7 @@ def bearer_token(self, bearer_token: str) -> Self:
if not bearer_token:
return self

self.headers = {'Authorization': f'Bearer {bearer_token}'}
self.headers.update({"Authorization": f"Bearer {bearer_token}"})

return self

Expand Down
57 changes: 57 additions & 0 deletions tests/test_queries.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
from cmr import Query


class MockQuery(Query):
def _valid_state(self) -> bool:
return True


def test_query_headers_initially_empty():
query = MockQuery("/foo")
assert query.headers == {}


def test_bearer_token_adds_header():
query = MockQuery("/foo")
query.headers["foo"] = "bar"
query.bearer_token("bearertoken")

assert query.headers["foo"] == "bar"


def test_bearer_token_does_not_clobber_other_headers():
query = MockQuery("/foo")
query.bearer_token("bearertoken")

assert query.headers["Authorization"] == "Bearer bearertoken"


def test_bearer_token_replaces_existing_auth_header():
query = MockQuery("/foo")
query.token("token")
query.bearer_token("bearertoken")

assert query.headers["Authorization"] == "Bearer bearertoken"


def test_token_adds_header():
query = MockQuery("/foo")
query.token("token")

assert query.headers["Authorization"] == "token"


def test_token_does_not_clobber_other_headers():
query = MockQuery("/foo")
query.headers["foo"] = "bar"
query.token("token")

assert query.headers["foo"] == "bar"


def test_token_replaces_existing_auth_header():
query = MockQuery("/foo")
query.bearer_token("bearertoken")
query.token("token")

assert query.headers["Authorization"] == "token"

0 comments on commit f4aab17

Please sign in to comment.