Skip to content

fix: do not let * select an explicitly listed value - #79

Open
lprnmns wants to merge 1 commit into
fastify:mainfrom
lprnmns:fix/wildcard-excludes-listed
Open

lprnmns wants to merge 1 commit into
fastify:mainfrom
lprnmns:fix/wildcard-excludes-listed

Conversation

@lprnmns

@lprnmns lprnmns commented Oct 23, 2026 •

Copy link
Copy Markdown

A * in the header is always mapped to the first supported value, even when the client has listed that value explicitly, e.g. with q=0:

const { negotiate } = require('@fastify/accept-negotiator')

negotiate('gzip;q=0, *', ['gzip', 'br'])     // 'gzip', expected 'br'
negotiate('*, gzip;q=0', ['gzip'])           // 'gzip', expected null
negotiate('br;q=0.5, *', ['br', 'gzip'])     // 'br' (q=0.5), expected 'gzip' (q=1 via *)

RFC 9110 §12.5.3 defines * in Accept-Encoding as matching "any available content coding not explicitly listed in the field value". negotiator (used by accepts/Express) agrees: it returns br, null and gzip for the three headers above. (@fastify/compress and @fastify/static replace * with gzip before calling negotiate(), so this change does not alter their behavior. It affects direct users of negotiate() / Negotiator.)

The fix records a * entry's quality instead of resolving it on the spot. Once the header has been read, * is applied to the highest-priority supported value that the header did not list, using the same comparison as the explicit entries. To keep the common case cheap, explicitly listed values are only collected when the header contains a *. parse() now reports the existing early exit (first supported value at q=1), so that case still returns right away.

Tests: four cases in test/testCases.js, all failing without the change. npm test (104 tests, 100% coverage, tstyche) and npm run lint pass. On benchmarks/negotiate.js, most cases are within run-to-run noise (about ±10% here), and a few are about 5–10% slower.

@gurgunday gurgunday left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

This branch has not been deployed

No deployments
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.

2 participants