Skip to content

fix(core): make Metadata keys consistently case-insensitive#1827

Open
anuq wants to merge 3 commits intoapache:mainfrom
anuq:fix/1588-metadata-case-insensitive
Open

fix(core): make Metadata keys consistently case-insensitive#1827
anuq wants to merge 3 commits intoapache:mainfrom
anuq:fix/1588-metadata-case-insensitive

Conversation

@anuq
Copy link

@anuq anuq commented Mar 15, 2026

Summary

Fixes #1588

HTTP headers are case-insensitive per RFC 2616, but Metadata had inconsistent behavior — getValues() and containsKey() did a case-insensitive fallback while write operations (addValue, setValue, setValues, addValues, remove) stored keys with their original casing.

Changes

  • Added a private normalizeKey(String key) helper that lowercases keys using Locale.ROOT
  • Applied it consistently across all read and write operations
  • Simplified getValues() and containsKey() — no more two-step fallback needed
  • Added testCaseInsensitiveKeys() test covering get, containsKey, addValue deduplication, and remove across mixed casings

Test

Tests run: 2, Failures: 0, Errors: 0, Skipped: 0

Normalize all keys to lowercase (Locale.ROOT) on every read and write
operation via a private normalizeKey() helper. Previously, getValues()
and containsKey() had a case-insensitive fallback but addValue(),
setValue(), setValues(), addValues(), and remove() stored keys with
their original casing, causing inconsistent behavior.

Fixes apache#1588

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@rzo1 rzo1 requested review from mvolikas and sigee March 15, 2026 18:18
@rzo1 rzo1 added this to the 3.5.2 milestone Mar 15, 2026
@rzo1
Copy link
Contributor

rzo1 commented Mar 15, 2026

Thanks for the PR @anuq - please verify the build output.

…sitive lookup After making all keys lowercase via normalizeKey(), keySet(prefix) was still doing a case-sensitive startsWith() match, causing lookups with uppercase prefixes (e.g. IMAGE., NEWS.) to return empty sets. Fixes SiteMapParserBoltTest failures for extension attribute assertions.
class MetadataTest {

@Test
void testCaseInsensitiveKeys() {
Copy link
Member

Choose a reason for hiding this comment

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

Good work! One thing I'd push back on slightly: testCaseInsensitiveKeys is doing a lot of work - it tests getFirstValue, containsKey, addValue, and remove all in one go. If this test fails, it can take some digging to identify which behavior broke.

Would you consider splitting it into separate test cases, each focused on a single method?

  • testGetFirstValueIsCaseInsensitive
  • testContainsKeyIsCaseInsensitive
  • testAddValueIsCaseInsensitive
  • testRemoveIsCaseInsensitive

This keeps tests easier to read, maintain, and debug. Let me know your thoughts!

Copy link
Author

Choose a reason for hiding this comment

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

makes sense, let me take another look at the test cases

…key lookup

- Replace testCaseInsensitiveKeys with four single-method tests:
  testGetFirstValueIsCaseInsensitive, testContainsKeyIsCaseInsensitive,
  testAddValueIsCaseInsensitive, testRemoveIsCaseInsensitive
- Fix testAddValueIsCaseInsensitive size assertion (1, not 2 — same normalized key)
- Fix checkListKeyFromOpensearch: look up "somekey" (lowercase) since
  normalizeKey() lowercases all keys before storing in OpenSearch

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@rzo1 rzo1 requested a review from sigee March 16, 2026 14:31
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.

[Improvement] The Metadata should handle all the case sensitivities

3 participants