The previous keyForURL stripped default ports (:443 for https, :80
for http) and omitted the scheme, so:
http://example.com/x.html ──┐
https://example.com/x.html ──┴──→ same cache entry (collision)
https://example.com/x.html ──┐
https://example.com:443/x.html ──┴──→ same cache entry
This was a defensible HTTP convention but a real correctness issue
on reverse-proxy stacks where http and https legitimately serve
different bytes for the same path, or where two upstreams share a
host but answer on different default ports.
New layout: <scheme>/<host>[:<port>]/<path>. Full origin tuple in
the key, no port stripping, scheme segregation. Examples:
https/zddc.varasys.io/releases/archive_stable.html
https/example.com:8443/x.html
http/example.com/y.html (distinct from https/example.com/y.html)
Operators retain the "ls _app/ to inspect what's cached" affordance
they relied on; they just see one extra directory layer (scheme
first, then host).
Tests:
* Updated TestKeyForURL to assert the new layout for every
previously-covered case
* New TestKeyForURL_NoCollisions explicitly asserts that the
dimensions previously collapsed (default-port↔bare, http↔https,
different non-default ports) now produce distinct keys
Doc references to the cache layout under <ZDDC_ROOT>/_app/ updated
in zddc/README.md (3 mentions).
NOTE: existing _app/ caches under the old layout will be ignored
on first request after upgrade — entries will be re-fetched and
written to the new path. Operators can `rm -rf <ZDDC_ROOT>/_app`
during the upgrade window if they prefer not to have orphans.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>