Skip to content

abilian_cdn.delivery

The read path: resolving a zone, checking a signature, and answering with the bytes.

abilian_cdn.delivery

Serving objects: the read path.

Every byte a client receives passes through here, so the HTTP semantics that make a CDN useful — validators, conditional requests, ranges — are this module's whole job. The bytes themselves come off the local cache; a miss fills the cache from S3 first rather than streaming through.

RangeNotSatisfiableError

Bases: ClientException

A Range that names bytes the object does not have.

Description dataclass

What a response says about an object, whether or not it carries one.

One structure for both zone kinds, so a storage zone and a pull zone cannot drift into describing the same thing differently — and so a HEAD cannot drift from the GET it describes, which is a bug nobody notices until a download is truncated.

Delivery dataclass

A description and the bytes on disk that go with it.

parse_range

parse_range(
    header: str, size: int
) -> tuple[int, int] | None

The single byte range a request asks for, as inclusive (start, end).

None means "send the whole thing", which is the right answer for a syntactically odd header and for multi-range requests: RFC 9110 permits answering those with the full representation, and one body is worth more than the multipart machinery a second range would need.

stream_range async

stream_range(
    path: Path, start: int, end: int
) -> AsyncIterator[bytes]

Yield one inclusive byte range of a file.

check_access

check_access(
    request: Request, zone: Zone, path: str
) -> None

Whether this request may have this object at all.

Private first: a private zone's objects are served only through a URL this service signed, and no referrer rule loosens that.

cors_headers

cors_headers(
    request: Request, zone: Zone
) -> dict[str, str]

The CORS headers this zone grants, if any.

A private zone grants none by default: its objects are behind a signature precisely so that not everyone may have them.

response_headers

response_headers(
    about: Description, zone: Zone
) -> dict[str, str]

What every delivered response carries, hit or miss, body or not.

One place builds these so a HEAD cannot drift from the GET it describes.

split_content_type

split_content_type(value: str) -> tuple[str, str]

A content type split the way the framework wants it: type, then charset.

Litestar appends ; charset=<encoding> to any media type under text/ without looking at what the value already carries, so handing it text/html; charset=utf-8 — which is what an S3 client uploads HTML as — spells the charset twice. Split here and passed as two arguments, the header comes back exactly as it went in.

addressed async

addressed(
    session: AsyncSession, request: Request, target: str
) -> tuple[Zone, str]

The zone and the object path a delivery URL names.

Two spellings, and the order between them is §5.1's: a hostname belonging to a zone serves that zone at its root, so its objects have URLs with nobody else's name in them; everything else puts the zone's name in the first path segment.

One query for both, rather than a lookup by hostname in front of every request that does not use one — this is the hot path, and a zone is found by hostname or by slug in the same index scan.

serve_object async

serve_object(
    request: Request,
    object_path: FromPath[str],
    db_session: NamedDependency[AsyncSession],
    blobs: NamedDependency[Blobs],
    origin: NamedDependency[Origin],
) -> Response[Any]

Deliver one object.

describe_object async

describe_object(
    request: Request,
    object_path: FromPath[str],
    db_session: NamedDependency[AsyncSession],
    origin: NamedDependency[Origin],
) -> Response[None]

The headers a GET would send, without the body.

A storage zone answers from its index and fetches nothing: a HEAD that filled the cache would let anyone warm every object in a zone for free, and the index has every header a HEAD needs.

A pull zone has no index, so it resolves exactly as a GET would. Warming a pull zone costs a GET to the origin either way, and answering 404 for a path the origin has would be worse than a warmed cache.

preflight async

preflight(
    request: Request,
    object_path: FromPath[str],
    db_session: NamedDependency[AsyncSession],
) -> Response[None]

Answer a browser's CORS preflight for this zone.

Without it a scripted fetch never sends the real request, and the page's console says the object does not allow cross-origin reads — whatever the zone's settings say.

Deliberately answered from the zone alone: whether the object exists is the real request's business, and a preflight that 404s would tell any page which paths a private zone holds.