feat(products): hosted-image URL build/parse helpers (SD-0002 §6.3.1)
DB-free host-agnostic helpers: image_url() builds the canonical hosted Image Src for a fetched image; parse_image_id() recognizes one on re-import via path-parse so exports round-trip across localhost/PPE/rebrand (INV-12). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
"""Hosted-image URL helpers (SD-0002 §6.3.1, INV-12).
|
||||
|
||||
Build the canonical hosted Image Src for a fetched image, and recognize one on
|
||||
re-import. DB-free and host-agnostic: recognition is a path-parse, so an export
|
||||
round-trips across localhost / PPE / the #23 rebrand. The diff resolves a parsed
|
||||
id against the storefront-scoped catalog snapshot.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from urllib.parse import urlsplit
|
||||
|
||||
RENDITIONS = ("original", "thumb", "card", "detail")
|
||||
EXPORT_RENDITION = "detail"
|
||||
|
||||
_PATH = re.compile(r"^/api/products/images/(\d+)/(original|thumb|card|detail)$")
|
||||
|
||||
|
||||
def image_url(base_url: str, image_id: int, rendition: str = EXPORT_RENDITION) -> str:
|
||||
"""Absolute when base_url is set, else a root-relative path."""
|
||||
path = f"/api/products/images/{image_id}/{rendition}"
|
||||
return f"{base_url.rstrip('/')}{path}" if base_url else path
|
||||
|
||||
|
||||
def parse_image_id(url: str) -> int | None:
|
||||
"""The image id if url is one of our hosted-image URLs (any host), else None."""
|
||||
if not url:
|
||||
return None
|
||||
m = _PATH.match(urlsplit(url).path)
|
||||
return int(m.group(1)) if m else None
|
||||
@@ -0,0 +1,30 @@
|
||||
"""hosted-image URL helpers — round-trip recognition (SD-0002 §6.3.1, INV-12)."""
|
||||
from app.domains.products import hosted
|
||||
|
||||
|
||||
def test_build_relative_when_no_base():
|
||||
assert hosted.image_url("", 42, "detail") == "/api/products/images/42/detail"
|
||||
|
||||
|
||||
def test_build_absolute_with_base():
|
||||
url = hosted.image_url("https://ecomm-ppe.wiggleverse.org", 42, "detail")
|
||||
assert url == "https://ecomm-ppe.wiggleverse.org/api/products/images/42/detail"
|
||||
|
||||
|
||||
def test_parse_absolute_hosted_url():
|
||||
url = "https://market.wiggleverse.org/api/products/images/7/detail"
|
||||
assert hosted.parse_image_id(url) == 7
|
||||
|
||||
|
||||
def test_parse_relative_hosted_url():
|
||||
assert hosted.parse_image_id("/api/products/images/7/card") == 7
|
||||
|
||||
|
||||
def test_parse_ignores_query_and_trailing():
|
||||
assert hosted.parse_image_id("/api/products/images/7/detail?v=1") == 7
|
||||
|
||||
|
||||
def test_parse_non_hosted_returns_none():
|
||||
assert hosted.parse_image_id("https://cdn.example.com/a/b.png") is None
|
||||
assert hosted.parse_image_id("/api/products/images/abc/detail") is None
|
||||
assert hosted.parse_image_id("/api/products/images/7") is None
|
||||
Reference in New Issue
Block a user