refactor(assets-sync): move Content-Type into _headers, drop assets.toml#66
Draft
lwshang wants to merge 1 commit into
Draft
refactor(assets-sync): move Content-Type into _headers, drop assets.toml#66lwshang wants to merge 1 commit into
lwshang wants to merge 1 commit into
Conversation
`Content-Type` is now declared inside any `_headers` block: the parser routes it to a dedicated `HeaderRule.content_type` field (Mime-validated) and the sync pipeline feeds it into `CreateAssetArguments.content_type` instead of the appended response headers — so the canister still emits exactly one certified Content-Type per response. Removes the `assets.toml` config file introduced in 4788ef6. From a user's mental model Content-Type is just a header, and the only remaining justification for a second config file (sketched v2 fields `ignore` / `encodings` / `allow_raw_access`) is either covered by the build pipeline, satisfied by current defaults, or no longer in scope. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced May 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Removes the
assets.tomlconfig introduced in #64 and folds the only feature it carried — per-globContent-Typeoverrides — back into_headers. The plugin now recognisesContent-Type:inside any_headersblock, parses the value as a MIME, and routes it toCreateAssetArguments.content_typerather than the appended response headers — so the canister still emits exactly one certifiedContent-Typeper response.Net diff: −634 / +287 across 21 files. Drops a config format, a parser module, an e2e fixture, a top-level design doc, and the
tomlworkspace dep.Why Content-Type belongs in
_headers, not its own file#64 sat on the position that
Content-Typewas asset metadata, not a response header, and therefore deserved its own file. That framing was driven by the canister's wire shape (appends_headerswithout dedup, so aContent-Type:rule would produce two on the wire) — i.e. an implementation concern, not a user concern.Content-Typein_headers. To a user, it's just a header — splitting it across two files to satisfy our pipeline is the kind of design that makes them say "why is this weird."Content-Typefrom_headers, route tocontent_type, exclude from the appended list) keeps the canister's append-without-dedup invariant intact and gives the user the familiar one-file experience.assets.tomlfields didn't survive review.ignorebelongs in the build step (don't put the file indist/if it shouldn't deploy).encodingshas no driving use case — the currenttext/* + js/html → identity+gzip, everything else → identitypolicy covers real projects.allow_raw_accessis being dropped on the canister side (selective certification via the HTTP gateway spec covers what it was for). With no remaining fields, the config file has no reason to exist.The pivot rests on a principle: adding a config format later when a real need shows up is cheaper than carrying an unused format now.
Other design points
HeaderRulegainscontent_type: Option<Mime>. Parsing aContent-Type:line is case-insensitive, validates asMime, rejects empty values, and rejects duplicates within the same block. Other headers in the same block continue to flow throughheadersas usual (assets-sync/src/headers.rs).content_type_for(key, rules)walks rules in declaration order and returns the first matchingcontent_type— first-match-wins becauseContent-Typeis single-valued (accumulation semantics make no sense for it). Other matching rules still contribute their non-Content-Typeheaders (assets-sync/src/headers.rs).prepare_assetnow takes&[HeaderRule](instead of the deleted&AssetConfig) and appliescontent_type_forbeforeencoders_for— so a.diddeclared astext/plainstill picks up gzip and still triggers drift detection on re-deploy. Theheader_content_type_override_applies_to_prepare_assetunit test pins this end-to-end (assets-sync/src/sync.rs).sync()signature. Lost itsfiles: &[(String, String)]parameter — no consumer remains. The plugin entry no longer threadsinput.filesthrough; if a future feature needs inline files, it just reads them.assets-sync/src/asset_config.rs,ASSETS-TOML.md, thetomlworkspace dep, theassets-tomle2e fixture, and the assets-toml-only fields from the developer-docs cargo-cult example (the e2e fixture now demonstrates.didonly, the one extensionmime_guessgenuinely can't classify).Test plan
New coverage in
headers.rstests: Content-Type routes to dedicated field not headers, case-insensitive, coexists with other headers, block-with-only-Content-Type is valid, rejects duplicate / invalid / empty values;content_type_forreturns None / first-match-wins / skips rules without acontent_typedeclaration.🤖 Generated with Claude Code