Fix header lookup bug in _buildCanonicalHeaders for mixed-case keys (#11884)

* Initial plan

* fix: handle mixed-case header keys in _buildCanonicalHeaders

Create a lowercase-keyed map to properly lookup header values regardless of
the input key casing. This prevents undefined values when headers have
mixed-case keys like "Host" or "Content-Type".

Co-authored-by: DeJeune <67425183+DeJeune@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: DeJeune <67425183+DeJeune@users.noreply.github.com>
This commit is contained in:
Copilot 2025-12-12 23:22:16 +08:00 committed by GitHub
parent 908506c83f
commit 03c3eee9f3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 23 additions and 4 deletions

View File

@ -69,11 +69,15 @@ export function _buildCanonicalHeaders(headers: Record<string, string>): {
canonicalHeaders: string canonicalHeaders: string
signedHeaders: string signedHeaders: string
} { } {
const sortedKeys = Object.keys(headers) // Create a lowercase-keyed map to handle mixed-case input headers
.map((k) => k.toLowerCase()) const lowercaseHeaders: Record<string, string> = {}
.sort() for (const [key, value] of Object.entries(headers)) {
lowercaseHeaders[key.toLowerCase()] = value
}
const canonicalHeaders = sortedKeys.map((key) => `${key}:${headers[key]?.trim() || ''}`).join('\n') + '\n' const sortedKeys = Object.keys(lowercaseHeaders).sort()
const canonicalHeaders = sortedKeys.map((key) => `${key}:${lowercaseHeaders[key]?.trim() || ''}`).join('\n') + '\n'
const signedHeaders = sortedKeys.join(';') const signedHeaders = sortedKeys.join(';')

View File

@ -292,6 +292,21 @@ describe('VolcengineService', () => {
expect(result.canonicalHeaders).toBe('host:example.com\nx-custom:\n') expect(result.canonicalHeaders).toBe('host:example.com\nx-custom:\n')
}) })
it('should handle mixed-case header keys', () => {
const headers = {
'X-Date': '20240101T120000Z',
'Content-Type': 'application/json',
Host: 'example.com'
}
const result = _buildCanonicalHeaders(headers)
expect(result.canonicalHeaders).toBe(
'content-type:application/json\nhost:example.com\nx-date:20240101T120000Z\n'
)
expect(result.signedHeaders).toBe('content-type;host;x-date')
})
}) })
describe('deriveSigningKey', () => { describe('deriveSigningKey', () => {