Skip to content

mamut_routing_publish.server

Static site server for the published MAMUT-routing website.

Replaces the Julia HTTP.jl webapp on the serving side: the public website is fully static, so this serves exactly three things and nothing else:

  • the built dist/ tree (resolved first, like the Julia server did);
  • the repo artifact roots that payload links reference by repo-relative path (LICENSE, benchmarks, dist), with traversal containment;
  • /healthz (also mirrored at /api/healthz so existing smoke tests and monitoring keep working across the cutover).

Serving quality the Julia server lacked in rootless mode: real Cache-Control policy instead of a universal no-store, strong ETags with conditional 304s, Range support (via Starlette's FileResponse), and precompressed .gz/.br sidecar negotiation (see precompress.py).

One deliberate rule: files whose own name ends in .gz (the .atf.json.gz sidecars, the collection geo sidecars) are opaque application/gzip bytes with NO Content-Encoding header. The frontend fetches them raw and decompresses via DecompressionStream; transparent decompression by the browser would break that contract.

normalize_request_path

normalize_request_path(raw_path: str) -> str | None

Collapse a request path to /segment/... form; None rejects traversal.

Source code in src/mamut_routing_publish/server.py
def normalize_request_path(raw_path: str) -> str | None:
    """Collapse a request path to /segment/... form; None rejects traversal."""
    candidate = raw_path.replace("\\", "/")
    keep_trailing_slash = candidate.endswith("/")
    segments: list[str] = []
    for segment in candidate.split("/"):
        if not segment or segment == ".":
            continue
        if segment == ".." or "\x00" in segment:
            return None
        segments.append(segment)
    if not segments:
        return "/"
    return "/" + "/".join(segments) + ("/" if keep_trailing_slash else "")

resolve_public_file

resolve_public_file(
    repo_root: Path,
    request_path: str,
    site_root: Path | None = None,
) -> Path | None

Port of the Julia server's dual-root resolution.

The dist tree is tried first (with the extensionless -> index.html and trailing-slash -> index.html conventions the shells rely on), then the whitelisted repo artifact roots for repo-relative payload links.

Source code in src/mamut_routing_publish/server.py
def resolve_public_file(repo_root: Path, request_path: str, site_root: Path | None = None) -> Path | None:
    """Port of the Julia server's dual-root resolution.

    The ``dist`` tree is tried first (with the extensionless -> index.html
    and trailing-slash -> index.html conventions the shells rely on), then
    the whitelisted repo artifact roots for repo-relative payload links.
    """
    relative_candidates: list[str] = []
    if request_path == "/":
        relative_candidates.append("index.html")
    elif request_path.endswith("/"):
        relative_candidates.append(f"{request_path[1:-1]}/index.html")
    else:
        relative = request_path[1:]
        relative_candidates.append(relative)
        if "." not in relative.rsplit("/", 1)[-1]:
            relative_candidates.append(f"{relative}/index.html")

    site_root = repo_root / "dist" if site_root is None else site_root
    for relative_candidate in relative_candidates:
        site_candidate = site_root / relative_candidate
        if site_candidate.is_file() and _contained(site_candidate, site_root):
            return site_candidate
        first_segment = relative_candidate.split("/", 1)[0]
        if first_segment not in REPO_ARTIFACT_ROOT_ENTRIES:
            continue
        repo_candidate = repo_root / relative_candidate
        if repo_candidate.is_file() and _contained(repo_candidate, repo_root / first_segment):
            return repo_candidate
    return None

negotiate_variant

negotiate_variant(
    path: Path, accept_encoding: str
) -> tuple[Path, str | None]

Pick a precompressed sidecar when the client accepts its encoding.

Files that are themselves .gz/.br content are never negotiated: they are opaque bytes by contract.

Source code in src/mamut_routing_publish/server.py
def negotiate_variant(path: Path, accept_encoding: str) -> tuple[Path, str | None]:
    """Pick a precompressed sidecar when the client accepts its encoding.

    Files that are themselves ``.gz``/``.br`` content are never negotiated:
    they are opaque bytes by contract.
    """
    if path.name.endswith((".gz", ".br")):
        return path, None
    accepted = accepted_encodings(accept_encoding)
    for encoding, suffix in (("br", ".br"), ("gzip", ".gz")):
        if encoding in accepted:
            variant = path.with_name(path.name + suffix)
            if variant.is_file():
                return variant, encoding
    return path, None

create_app

create_app(
    repo_root: str | Path,
    site_dir: str | Path | None = None,
) -> Starlette

The static app: site_dir (default <repo_root>/dist) plus the repo artifact roots.

site_dir lets a staging build (site build --site-output-dir) be previewed without touching the live dist tree; repo-relative artifact links (benchmarks/, LICENSE, dist/ caches) still resolve against repo_root.

Source code in src/mamut_routing_publish/server.py
def create_app(repo_root: str | Path, site_dir: str | Path | None = None) -> Starlette:
    """The static app: ``site_dir`` (default ``<repo_root>/dist``) plus the repo artifact roots.

    ``site_dir`` lets a staging build (``site build --site-output-dir``) be
    previewed without touching the live ``dist`` tree; repo-relative artifact
    links (``benchmarks/``, ``LICENSE``, ``dist/`` caches) still resolve
    against ``repo_root``.
    """
    root = Path(repo_root).resolve()
    site_root = (root / "dist") if site_dir is None else Path(site_dir).resolve()
    if not site_root.is_dir():
        raise FileNotFoundError(f"No site tree at {site_root}. Run `site build` first.")
    app = Starlette(
        routes=[
            Route("/healthz", healthz, methods=["GET", "HEAD"]),
            Route("/api/healthz", healthz, methods=["GET", "HEAD"]),
            Route("/{path:path}", serve_site_file, methods=["GET", "HEAD"]),
        ]
    )
    app.state.repo_root = root
    app.state.site_root = site_root
    return app