Skip to content

abilian_cdn.client

The HTTP client the CLI drives. Useful on its own for a script that would rather not shell out.

abilian_cdn.client

The client side: talking to a CDN from a terminal or a CI job.

Separate from the server modules on purpose — nothing here imports the database or the object store, so cdn put works on a laptop that has neither.

ClientError

Bases: RuntimeError

The server refused, and this says what it said.

Credentials dataclass

Where to talk, and what to say who we are.

load classmethod

load(path: Path = CONFIG_PATH) -> Credentials

Read the environment first, then the config file.

The environment wins so a CI job can hold its token in a secret rather than in a file it would have to write first.

save

save(path: Path = CONFIG_PATH) -> None

Write the credential, readable only by its owner.

Client

The handful of calls the command line makes.

list_objects

list_objects(
    zone: str, prefix: str = ""
) -> Iterator[dict[str, Any]]

Every object under a prefix, following the server's paging.

A generator, so ls on a zone with a million objects prints the first page while the rest is still arriving.

put_file

put_file(
    zone: str, path: str, source: Path
) -> dict[str, Any]

Upload one file, streamed rather than read into memory.

sign

sign(
    zone: str, path: str, expires_in: int
) -> dict[str, Any]

Ask the service for a URL that serves this object without a token.

purge

purge(
    zone: str,
    paths: list[str] | None = None,
    prefix: str | None = None,
    everything: bool = False,
) -> dict[str, Any]

Drop cached copies so the next request fetches them again.

content_digest

content_digest(path: Path) -> str

The digest a single-part S3 upload reports as its ETag: MD5, hex.

Not a security claim — it is the only fingerprint both ends already have, which is what makes sync able to skip a file without downloading it.

parse_duration

parse_duration(text: str) -> int

Seconds, from 90, 30m, 2h or 7d.