8000 fix: use Charset-based comparison for Accept-Charset negotiation by kawasima · Pull Request #107 · enkan/enkan · GitHub
[go: up one dir, main page]

Skip to content

fix: use Charset-based comparison for Accept-Charset negotiation - #107

Merged
kawasima merged 5 commits into
developfrom
feature/fix-accept-charset-comparison
Mar 28, 2026
Merged

kawasima merged 5 commits into
developfrom
feature/fix-accept-charset-comparison

Conversation

@kawasima
Copy link
Copy Markdown
Collaborator

Summary

  • Replace string equality (charset.equals("iso_8859_1")) with java.nio.charset.Charset-based comparison in AcceptHeaderNegotiator.bestAllowedCharset()
  • Handles all charset aliases (e.g. latin1, iso_8859_1, iso-8859-1) via JDK's canonical charset resolution
  • Correctly applies RFC 9110 §12.5.3 default quality of 1.0 for ISO-8859-1 when not explicitly listed in Accept-Charset

Closes #104

Test plan

  • acceptCharsetMatchesStandardName — iso-8859-1 in Accept-Charset matches iso-8859-1 in available set
  • acceptCharsetMatchesAlias — latin1 in Accept-Charset matches iso-8859-1 in available set
  • acceptCharsetDefaultsIso88591 — ISO-8859-1 gets default q=1.0 when not listed, beating utf-8;q=0.5
  • All 5 AcceptHeaderNegotiator tests pass

🤖 Generated with Claude Code

kawasima and others added 5 commits March 28, 2026 19:13
The charset comparison used string equality with "iso_8859_1"
(underscore), which never matched the standard "iso-8859-1" (hyphen)
that clients send. Replace with java.nio.charset.Charset-based
comparison to handle all aliases (latin1, iso_8859_1, iso-8859-1, etc.)
and correctly apply the RFC 9110 §12.5.3 default quality of 1.0 for
ISO-8859-1.

Closes #104

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Pre-resolve Accept-Charset entries to canonical Charset objects once
  outside the lambda, avoiding repeated Charset.forName() calls per
  available charset (O(available × accepts) → O(available + accepts))
- Deduplicate Charset.forName(charset) call — reuse resolved Charset
  for both alias matching and ISO-8859-1 default check
- Skip "*" wildcard in alias resolution loop to avoid unnecessary
  UnsupportedCharsetException
- Add test for Accept-Charset wildcard "*"

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Lowercase accept keys when building the accepts map so that
  Accept-Charset: UTF-8 matches available "utf-8" on the fast path
  (RFC 9110 charset comparison is case-insensitive)
- Add merge function to handle duplicate keys after lowercasing
- Add comment explaining the second wildcardQ check (reached when
  Charset.forName throws for unrecognized available charset names)
- Add case-sensitivity test

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace Double.parseDouble() with strict RFC 9110 §12.4.2 qvalue
  regex — rejects scientific notation (1e-1), >3 decimal places
  (0.1234), and out-of-range values (2.0). Remove unused clamp().
- Use sorted set string for cache keys instead of Set.toString() to
  avoid nondeterministic iteration order causing cache misses.
- Support escaped quotes in quoted-string parameter values per
  RFC 9110 §5.6.4: change "[^"]*" to "(?:[^"\\]|\\.)*"

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Wrap bestAllowedCharset body in charsetCache.computeIfAbsent() using
stableCacheKey, consistent with bestAllowedContentType and
bestAllowedLanguage. Avoids repeated Charset.forName() lookups for
the same Accept-Charset header and available set.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@kawasima
kawasima merged commit f3b01d9 into develop Mar 28, 2026
1 check passed
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

0