Skip to content
Next Next commit
fix for proper handling of absolute http URIs
  • Loading branch information
spinto committed Dec 9, 2025
commit e2629ea18bca8d8848490b1c1d53420956df8fdd
17 changes: 8 additions & 9 deletions pystac/asset.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,12 @@ def get_absolute_href(self) -> str | None:
str: The absolute HREF of this asset, or None if an absolute HREF could not
be determined.
"""
if utils.is_absolute_href(self.href):
item_self = self.owner.get_self_href() if self.owner is not None else None
if utils.is_absolute_href(self.href, item_self):
return self.href
else:
if self.owner is not None:
item_self = self.owner.get_self_href()
if item_self is not None:
return utils.make_absolute_href(self.href, item_self)
if item_self is not None:
return utils.make_absolute_href(self.href, item_self)
return None

def to_dict(self) -> dict[str, Any]:
Expand Down Expand Up @@ -341,7 +340,7 @@ def make_asset_hrefs_relative(self) -> Assets:
"""
self_href = self.get_self_href()
for asset in self.assets.values():
if is_absolute_href(asset.href):
if is_absolute_href(asset.href, self_href):
if self_href is None:
raise STACError(
"Cannot make asset HREFs relative if no self_href is set."
Expand All @@ -360,7 +359,7 @@ def make_asset_hrefs_absolute(self) -> Assets:
"""
self_href = self.get_self_href()
for asset in self.assets.values():
if not is_absolute_href(asset.href):
if not is_absolute_href(asset.href, self_href):
if self_href is None:
raise STACError(
"Cannot make relative asset HREFs absolute "
Expand All @@ -380,10 +379,10 @@ def get_self_href(self) -> str | None:


def _absolute_href(href: str, owner: Assets | None, action: str = "access") -> str:
if utils.is_absolute_href(href):
item_self = owner.get_self_href() if owner else None
if utils.is_absolute_href(href, item_self):
return href
else:
item_self = owner.get_self_href() if owner else None
if item_self is None:
raise ValueError(
f"Cannot {action} file if asset href ('{href}') is relative "
Expand Down
2 changes: 1 addition & 1 deletion pystac/item.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ def set_self_href(self, href: str | None) -> None:
# Make sure relative asset links remain valid.
for asset in self.assets.values():
asset_href = asset.href
if not is_absolute_href(asset_href):
if not is_absolute_href(asset_href, prev_href):
abs_href = make_absolute_href(asset_href, prev_href)
new_relative_href = make_relative_href(abs_href, new_href)
asset.href = new_relative_href
Expand Down
12 changes: 10 additions & 2 deletions pystac/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -378,19 +378,27 @@ def make_absolute_href(
return _make_absolute_href_path(parsed_source, parsed_start, start_is_dir)


def is_absolute_href(href: str) -> bool:
def is_absolute_href(href: str, start_href: str | None = None) -> bool:
"""Determines if an HREF is absolute or not.

May be used on either local file paths or URLs.

Args:
href : The HREF to consider.
start_href : The HREF that will be used as the basis for checking if
``source_href`` is a relative path. Defaults to the current
working directory.

Returns:
bool: ``True`` if the given HREF is absolute, ``False`` if it is relative.
"""
parsed = safe_urlparse(href)
return parsed.scheme not in ["", "file"] or os.path.isabs(parsed.path)
parsed_start_scheme = "" if start_href is None else safe_urlparse(start_href).scheme

if parsed_start_scheme in ["", "file"]:
return parsed.scheme not in ["", "file"] or os.path.isabs(parsed.path)
else:
return parsed.scheme not in ["", "file"]


def datetime_to_str(dt: datetime, timespec: str = "auto") -> str:
Expand Down
15 changes: 9 additions & 6 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,14 +197,17 @@ def test_make_absolute_href_windows(
def test_is_absolute_href() -> None:
# Test cases of (href, expected)
test_cases = [
("item.json", False),
("./item.json", False),
("../item.json", False),
("http://stacspec.org/item.json", True),
("item.json", False, None),
("./item.json", False, None),
("../item.json", False, None),
("http://stacspec.org/item.json", True, None),
("/item.json", True, None),
("/item.json", False, "http://stacspec.org/"),
("http://stacspec.org/item.json", True, "http://stacspec.org/"),
]

for href, expected in test_cases:
actual = is_absolute_href(href)
for href, expected, start_href in test_cases:
actual = is_absolute_href(href, start_href)
assert actual == expected


Expand Down
Loading