fix(cache): deduplicate Cache-Control directives case-insensitively by nyxst4ck · Pull Request #5025 · honojs/hono · GitHub
Skip to content

fix(cache): deduplicate Cache-Control directives case-insensitively#5025

Open
nyxst4ck wants to merge 1 commit into
honojs:mainfrom
nyxst4ck:fix/cache-control-case-insensitive-dedup
Open

fix(cache): deduplicate Cache-Control directives case-insensitively#5025
nyxst4ck wants to merge 1 commit into
honojs:mainfrom
nyxst4ck:fix/cache-control-case-insensitive-dedup

Conversation

@nyxst4ck

Copy link
Copy Markdown

What

The cache middleware composes its configured cacheControl directives onto an
existing Cache-Control header, de-duplicating by directive name. But it
extracts the existing directive names without lower-casing them
(src/middleware/cache/index.ts), while lower-casing its own name before the
membership check:

const existingDirectives = c.res.headers.get('Cache-Control')
  ?.split(',').map((d) => d.trim().split('=', 1)[0]) ?? []   // not lowercased
for (const directive of cacheControlDirectives) {
  let [name, value] = directive.trim().split('=', 2)
  name = name.toLowerCase()                                   // lowercased
  if (!existingDirectives.includes(name)) { ... }             // case-sensitive miss
}

Cache-Control directive names are case-insensitive (RFC 7234 §5.2). So when a
route handler sets e.g. Cache-Control: Max-Age=3600 and the middleware is
configured with cacheControl: 'max-age=10', the duplicate isn't detected and a
contradictory directive is appended:

Cache-Control: Max-Age=3600, max-age=10

The existing /wait2/ de-dup test only passes because both directives there are
written lower-case by the middleware itself; the handler-set path was the gap.

Fix

Lower-case the extracted existing directive names so the case-insensitive de-dup
check matches handler-set names like Max-Age.

Test

Added a Cache Middleware case (/wait5/) where the handler sets
Cache-Control: Max-Age=3600 against a middleware max-age=10. It fails on
main (Max-Age=3600, max-age=10) and passes with the fix (Max-Age=3600).
All cache middleware tests pass (139). Prettier + ESLint clean.

The cache middleware extracted existing Cache-Control directive names without
lower-casing them, then compared against its own lower-cased directive names.
Cache-Control directive names are case-insensitive (RFC 7234), so a handler-set
`Max-Age=3600` was not recognised as a duplicate of a configured `max-age=10`
and a contradictory directive was appended.

Lower-case the extracted names so the de-dup check matches regardless of case.
@codecov

codecov Bot commented Jun 17, 2026

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant