Skip to content

feat(assets-sync): add assets.toml content-type overrides#64

Draft
lwshang wants to merge 2 commits into
lwshang/headers_globsfrom
lwshang/assets_toml
Draft

feat(assets-sync): add assets.toml content-type overrides#64
lwshang wants to merge 2 commits into
lwshang/headers_globsfrom
lwshang/assets_toml

Conversation

@lwshang
Copy link
Copy Markdown
Collaborator

@lwshang lwshang commented May 28, 2026

Superseded by #66. The dedicated assets.toml config was scrapped in favour of folding per-glob Content-Type overrides into _headers — same feature, single familiar file, no new format to learn. See #66 for the design rationale and the replacement implementation.

Summary (what this PR would have done)

Added an opt-in assets.toml config file (passed inline via the manifest's files: field) that let users override an asset's Content-Type by glob pattern. v1 scoped to this one field; broader [[asset]] knobs (ignore, encodings, allow_raw_access) were sketched in ASSETS-TOML.md for follow-ups.

Replaced by #66 which expresses the same overrides inside _headers (e.g. /*.did\n Content-Type: text/plain; charset=utf-8). The plugin extracts Content-Type from _headers and routes it into CreateAssetArguments.content_type so the canister still emits exactly one certified Content-Type per response.

🤖 Generated with Claude Code

lwshang and others added 2 commits May 28, 2026 16:31
New plugin-side config file (passed via `SyncExecInput.files`) lets
users override asset content-type by glob pattern:

    [[asset]]
    match = "/*.md"
    content_type = "text/markdown; charset=utf-8"

Resolution walks `[[asset]]` blocks in declaration order — first
matching `content_type` wins; falls back to `mime_guess::from_path`
otherwise. The override is applied in `prepare_asset` before
`encoders_for` runs, so a `.did` declared as `text/plain` also picks
up gzip compression and stores the right type for cert-tree drift
detection. Result feeds `CreateAssetArguments.content_type` so the
canister emits exactly one `Content-Type` in the certified response —
closes the duplicate-header pitfall of the legacy `.ic-assets.json5`
`headers.Content-Type` workaround.

Also lifts `HeaderPattern` from `headers.rs` into a shared
`KeyPattern` in `glob.rs` since both `_headers` rules and
`assets.toml` blocks match against asset keys with the same dialect.
Pure refactor; `_headers` semantics unchanged.

Strict v1 schema: `#[serde(deny_unknown_fields)]` on both the top
level and per-block — typo protection beats forward compat for an
unreleased plugin. The standard filename `assets.toml` is convention,
not enforced — the manifest's `files:` field is the authoritative
declaration of which file is the asset config.

Design rationale and parked open questions in `ASSETS-TOML.md`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two scenarios on a fixture that mirrors the developer-docs case:

1. `content_type_overrides_land_on_canister` — deploy with overrides
   for `/*.did`, `/*.sh`, `/llms.txt` and verify the HTTP gateway
   returns the configured `Content-Type` exactly (proves the override
   survived certification, since the gateway validates the
   `IC-Certificate` before responding).

2. `content_type_edit_propagates_on_redeploy` — flip an override and
   redeploy without changing the asset bytes; verify the new
   `Content-Type` reaches clients (proves drift detection triggers
   delete-then-recreate when content-type changes).

Also documents the feature in the top-level README under "Per-glob
content-type overrides" and refreshes the `_headers` paragraph to
mention the now-supported glob syntax (`/*.md`, mid-path wildcards).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant