Since #7249, parseCacheControl() is lenient: a known directive with a malformed value is dropped instead of throwing. That was the right call for untrusted header bytes, but it erased a distinction RFC 9111 cares about. parseCacheControl("max-age=abc") and parseCacheControl("") both return {}.
Those two inputs call for different cache behavior:
- Absent max-age: fall back to heuristic freshness (§4.2.2).
Malformed max-age: treat the response as stale (§4.2.1).
- The module docs point implementers at the §4.2.1 advice, but the API gives them no signal to act on. Today the only way to tell the cases apart is to re-scan the raw header string yourself.
Flagged by @bartlomieju in the #7249 review as a decision to settle before stabilizing @std/http/unstable-cache-control, not a blocker while the module is unstable.
Options I can see:
- Add an optional field to the result, e.g. invalid?: string[] with the directive names that failed to parse. Additive and cheap, but it puts parse metadata on a value type that otherwise round-trips through formatCacheControl().
- Keep the API as-is and document that callers who need the distinction must check the raw header. Zero cost, pushes the work onto exactly the callers §4.2.1 was written for.
- A strict option or separate strict entry point that restores throwing for trusted input.
I lean toward 1, with formatCacheControl() ignoring the field. Happy to PR whichever way this lands.
Since #7249, parseCacheControl() is lenient: a known directive with a malformed value is dropped instead of throwing. That was the right call for untrusted header bytes, but it erased a distinction RFC 9111 cares about. parseCacheControl("max-age=abc") and parseCacheControl("") both return {}.
Those two inputs call for different cache behavior:
Malformed max-age: treat the response as stale (§4.2.1).
Flagged by @bartlomieju in the #7249 review as a decision to settle before stabilizing @std/http/unstable-cache-control, not a blocker while the module is unstable.
Options I can see:
I lean toward 1, with formatCacheControl() ignoring the field. Happy to PR whichever way this lands.