Skip to content

feat: Configurable fallback behavior for the asset canister (custom 404 support) #4497

@marc0olo

Description

@marc0olo

Problem

The asset canister serves /index.html with status 200 for all unmatched routes. This is correct for SPAs but wrong for static sites, docs sites, and multi-page apps where unmatched routes should return 404. It also hurts SEO — search engines index non-existent pages as real content.

The fallback file and status code are hardcoded:

  • FALLBACK_FILE = "/index.html" in ic-certified-assets/src/asset_certification/types/http.rs
  • Always served with status 200

There is no custom 404.html support despite it being standard on other hosting platforms (Netlify, Vercel, GitHub Pages, Cloudflare Pages).

Proposal

Make the fallback configurable via .ic-assets.json5:

// SPA (current default — no change needed)
{ "fallback": { "file": "/index.html", "status_code": 200 } }

// Static site with custom 404
{ "fallback": { "file": "/404.html", "status_code": 404 } }

// No fallback (strict mode)
{ "fallback": false }

Default remains { file: "/index.html", status_code: 200 } for full backward compatibility.

Implementation notes

Areas to change:

  1. Config parsing (ic-asset): extend .ic-assets.json5 schema with top-level fallback property
  2. State machine (ic-certified-assets/src/state_machine/mod.rs): replace hardcoded FALLBACK_FILE with configurable value and status code
  3. Certification (ic-certified-assets/src/asset_certification/mod.rs): the certification tree and witness generation must be updated to certify the configured fallback file and status code (currently hardcoded for 200 + index.html)
  4. Stable storage: persist fallback config across upgrades

The certification changes are the most involved — the Merkle proof must cover the actual status code and body being returned for unmatched paths.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions