brazier/static

Types

Why a client bundle could not be loaded.

pub type AssetError {
  AssetNotFound
  AssetReadFailed(reason: String)
}

Constructors

  • AssetNotFound

    No regular file exists at the path.

  • AssetReadFailed(reason: String)

    The file exists but could not be read.

A client bundle prepared for serving: the raw bytes, their gzip encoding and a strong ETag. Built once per file version and cached.

pub type ClientAsset {
  ClientAsset(raw: BitArray, gzip: BitArray, etag: String)
}

Constructors

  • ClientAsset(raw: BitArray, gzip: BitArray, etag: String)

Configuration for static file serving.

pub type StaticConfig {
  StaticConfig(directory: String, prefix: String, max_age: Int)
}

Constructors

  • StaticConfig(directory: String, prefix: String, max_age: Int)

    Arguments

    directory

    Directory to serve files from (e.g., “priv/static”).

    prefix

    URL path prefix (e.g., “/static”). Must start with /, must not end with /, and must not be / itself (see validate_config).

    max_age

    Cache-Control max-age in seconds (0 = revalidate every time).

Values

pub fn accepts_gzip(accept_encoding: String) -> Bool

RFC 9110 §12.5.3: true when the Accept-Encoding header value accepts gzip with a non-zero quality (explicitly, or via * when gzip is not listed). “” (no header) means no content coding is requested.

pub fn cache_control(max_age: Int) -> String

The Cache-Control value for a max-age: 0 means “store but revalidate”.

pub fn cached_client_asset_paths() -> List(String)

Paths currently held by the client asset cache (at most 4).

pub fn contains_traversal(path: String) -> Bool

Check if a path contains directory traversal sequences. Catches: “..”, backslash, null bytes, and encoded traversal (%2e, %2f, %5c). A percent-escape is ASCII, so the path is lowercased in ASCII only.

The path is searched as bytes, the way the file system reads it, not as grapheme clusters: .. followed by a combining mark (U+0301) is one . and one .́ to string.contains, but holds the bytes .., and %2f + U+0301 still decodes to a / byte.

pub fn default_config() -> StaticConfig

Default static config.

pub fn etag_for(contents: BitArray) -> String

A strong entity tag derived from the content (SHA-256, 128 bits shown). A served static file carries the tag of its contents.

pub fn etag_matches(if_none_match: String, etag: String) -> Bool

RFC 9110 §13.1.2: If-None-Match uses the weak comparison, so W/"x" matches "x". * matches any current representation. The header may carry a comma-separated list; “” means the header was absent.

pub fn fingerprint(path: String, contents: BitArray) -> String

Generate a fingerprinted filename for cache busting from the content hash: “app.js” → “app-<16 hex>.js”, “LICENSE” → “LICENSE-<16 hex>”.

pub fn immutable_cache_control() -> String

The Cache-Control value for content-addressed assets.

pub const immutable_max_age: Int

Seconds a fingerprinted (content-addressed) asset may be cached.

pub fn is_client_bundle_name(name: String) -> Bool

True for a client bundle file name produced by brazier/build: brazier_client_<8..64 hex digits>.js, nothing else. This is the only shape the transport will read from the client assets directory.

pub fn load_client_asset(
  path: String,
) -> Result(ClientAsset, AssetError)

Load a client bundle through the asset cache. The file is stat-ed on every call and re-read and re-compressed when its size, mtime, ctime, inode or device changed, or when the cached entry was recorded within two seconds of the file’s last change (git’s racy-clean rule, as for the static digest cache), so a rebuilt bundle is never served stale and is picked up without a restart.

pub fn matches_prefix(config: StaticConfig, path: String) -> Bool

True when path is inside the static prefix: equal to it or below it on a / boundary. /staticfoo does not match the prefix /static.

pub fn mime_type(path: String) -> String

Determine MIME type from file extension.

pub fn route_pattern(config: StaticConfig) -> String

The route pattern a served static file reports to telemetry: <prefix>/*, never the file path.

pub fn serve(
  config: StaticConfig,
  path: String,
) -> Result(response.Response(server.ResponseBody), Nil)

Try to serve a static file for the given path. Returns Ok(Response) if a file was found and served (or the path was refused), Error(Nil) if the path is outside the static prefix or no such file exists.

pub fn serve_immutable(
  config: StaticConfig,
  path: String,
) -> Result(response.Response(server.ResponseBody), Nil)

Serve static files with an immutable cache (for fingerprinted assets). Fingerprinted assets can be cached forever since the URL changes on content change.

pub fn serve_with_etag_check(
  config: StaticConfig,
  path: String,
  if_none_match: String,
) -> Result(response.Response(server.ResponseBody), Nil)

Serve a static file with ETag/If-None-Match support. if_none_match is the raw header value (“” when absent); a matching entity tag (or *) yields 304 Not Modified.

pub fn validate_config(
  config: StaticConfig,
) -> Result(Nil, String)

Reject configurations that would shadow every route or produce invalid cache headers. Called by the transport at startup.

✨ Search Document