Monorepo for wisp.place. A static site hosting service built on top of the AT Protocol. wisp.place

redirects: Accept= follows the client's preference and skips missing targets #93

Merged nekomimi.pet
targeting main from feat/redirects-accept-negotiation
Merged opened by and assigned to nekomimi.pet
targeting main from feat/redirects-accept-negotiation

Follow-up to 9cc08b7, from dawn's review of how the condition should match.

  • An Accept= rule fires only when one of its media types is the client's top preference among the types it names (ties count). Wildcards are still ignored, so text/html, application/json;q=0.1 now stays HTML instead of rewriting to JSON.
  • An Accept= rewrite (200) whose target is not in the site is skipped and matching continues with the next rule or the page itself. With /* /:splat/index.md 200! Accept=text/markdown, pages without a markdown copy keep serving their HTML instead of a 404.
  • Doubled slashes in an internal rewrite target are collapsed, so the same splat rule maps /configuration/ to /configuration/index.md rather than /configuration//index.md.

Parameters and case were already ignored (application/ld+json; profile=... matches application/ld+json), Vary: Accept is set on both answers, and the Content-Type comes from the target file; tests now pin those down too. wispctl's matcher follows the preference and slash rules; its local serve passes no request headers, so the skip has no hook there.

Tests cover each change and fail with it removed. Root suite 2168 pass; tsc, biome and cargo clippy clean.

Commits 0