Skip to content

fix(req.get): perform case-insensitive header lookup - #7395

Open
armanmikoyan wants to merge 1 commit into
expressjs:masterfrom
armanmikoyan:fix-req-get-case-insensitive-custom-headers
Open

fix(req.get): perform case-insensitive header lookup#7395
armanmikoyan wants to merge 1 commit into
expressjs:masterfrom
armanmikoyan:fix-req-get-case-insensitive-custom-headers

Conversation

@armanmikoyan

@armanmikoyan armanmikoyan commented Jul 25, 2026

Copy link
Copy Markdown

Fixes #5288

This updates req.get() / req.header() to perform a case-insensitive lookup when a header is present under a non-lowercase key.

Previously, custom headers added directly to req.headers with mixed-case names, such as X-filipe, could not be read with req.get('x-filipe'). This change preserves the fast direct lookup path, then falls back to scanning header keys case-insensitively.

req.headers['X-filipe'] = 'filipe'

req.get('x-filipe') // before: undefined

After this change, the same lookup returns the header value:

req.headers['X-filipe'] = 'filipe'

req.get('x-filipe') // after: 'filipe'

A regression test was added for custom mixed-case request headers.

@krzysdz

krzysdz commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

I won't close this yet, but in my opinion #5288 is the result of modifying Node.js API object in a way that violates requirements/assumptions stated in documentation and Express should not work around problems in code that uses it.

@bjohansebas

Copy link
Copy Markdown
Member

I'm adding it as an idea for Express 6. It doesn't mean it'll be included—it's just something for us to discuss.

@kilisamemarisaaa kilisamemarisaaa left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The fallback should only inspect own header properties. for...in also walks the prototype chain, so this change can return an inherited mixed-case property as if it were an HTTP header.

I reproduced the behavior represented by this head on Node 24.12.0:

const headers = Object.create({ 'X-Inherited': 'prototype-value' })

// Current direct lowercase lookup:
headers['x-inherited'] // undefined

// This PR's fallback:
getHeader(headers, 'x-inherited') // 'prototype-value'
Object.keys(headers) // []

A real Node request's req.headers also had Object.prototype as its prototype in that environment, rather than a null prototype. This means an enumerable inherited property (including one introduced by unrelated prototype mutation) becomes observable through req.get() only after this change.

Could the loop use Object.keys(headers) or guard with Object.prototype.hasOwnProperty.call(headers, key), with a regression case using Object.create({ 'X-Filipe': 'inherited' })? Mixed-case own properties would still work without treating prototype state as request metadata.

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Express 4 and 5 req.get doesnt return header if not set in lowercase

4 participants