Skip to content

fix(request): parse first entry of comma-list x-forwarded-proto header#1413

Merged
pi0 merged 5 commits into
h3js:mainfrom
LeSingh1:fix/x-forwarded-proto-comma-list
Jul 2, 2026
Merged

fix(request): parse first entry of comma-list x-forwarded-proto header#1413
pi0 merged 5 commits into
h3js:mainfrom
LeSingh1:fix/x-forwarded-proto-comma-list

Conversation

@LeSingh1

@LeSingh1 LeSingh1 commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Proxies can stack x-forwarded-proto as a comma-separated list, for example "https,http" where the leftmost entry is the scheme the original client used. getRequestProtocol compared the raw header value with strict equality, so any comma-list value fell through and the function returned the scheme from the underlying request URL instead of the client-facing protocol. toRequest had the same problem on the same header.

The fix applies the same split(",")[0].trim() pattern already used by getRequestHost and getRequestIP for their respective forwarded headers.

Two failing tests were added before the fix and confirmed broken: one in test/unit/request.test.ts that exercises getRequestProtocol directly with a fake event, and two in test/utils.test.ts under getRequestURL that test the comma-list and comma-with-space cases end-to-end through a live app handler. All 48 test files and 1159 tests pass after the fix. Lint and oxfmt are clean.

Summary by CodeRabbit

  • Bug Fixes
    • Improved protocol detection for proxied requests by correctly parsing x-forwarded-proto when it contains a comma-separated list (using the first value with whitespace trimmed), while respecting the option to ignore proxy headers.
  • Tests
    • Added unit and utility coverage for x-forwarded-proto parsing, including comma-separated values, whitespace handling, and the disable-proxy-header option.
  • Documentation
    • Updated request utility docs to clarify comma-separated x-forwarded-proto behavior and the xForwardedProto: false option.

Proxies can stack x-forwarded-proto as a comma-separated list
(e.g. "https,http"). getRequestProtocol compared the raw header
value with strict equality, so any comma-list value fell through
and the underlying request URL scheme was used instead of the
client-facing protocol. toRequest had the same issue.

Apply the same split(",")[0].trim() pattern already used by
getRequestHost and getRequestIP for their respective headers.
@LeSingh1
LeSingh1 requested a review from pi0 as a code owner June 12, 2026 06:50
@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 33540d8d-8c8f-4a8f-8ee7-ad1ad299b56b

📥 Commits

Reviewing files that changed from the base of the PR and between 7680538 and de855c6.

📒 Files selected for processing (1)
  • test/utils.test.ts

📝 Walkthrough

Walkthrough

The PR updates request protocol detection to parse comma-separated x-forwarded-proto values by taking the first trimmed entry in toRequest() and getRequestProtocol(), and adds tests plus documentation updates covering that behavior.

Changes

x-forwarded-proto comma-separated parsing

Layer / File(s) Summary
x-forwarded-proto parsing implementation
src/utils/request.ts, docs/2.utils/1.request.md
toRequest() and getRequestProtocol() now split x-forwarded-proto on commas, take the first trimmed value, and use it to determine scheme/protocol; the request utility docs were updated to describe the same behavior and the xForwardedProto disablement.
getRequestProtocol unit tests
test/unit/request.test.ts
Adds a makeEvent test helper and tests validating getRequestProtocol() for plain, comma-separated, and whitespace-padded x-forwarded-proto values, and the { xForwardedProto: false } option.
getRequestURL integration tests
test/utils.test.ts
Adds tests ensuring getRequestURL() uses the first comma-separated x-forwarded-proto entry and trims whitespace when constructing the URL.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Suggested reviewers: pi0x, pi0

Poem

I nibble headers in the night,
I split the commas, trim them right,
The first proto leads the way,
Through proxies, hop and sway,
Happy routes, in moonlit byte. 🐰

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main fix: parsing the first value from a comma-separated x-forwarded-proto header.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot 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.

🧹 Nitpick comments (1)
src/utils/request.ts (1)

377-388: ⚡ Quick win

Update JSDoc to document comma-separated header handling.

The JSDoc comment states "If x-forwarded-proto header is set to 'https'", but with the new implementation (lines 394-395), comma-separated values are now supported and the first entry is used. Consider updating the documentation to clarify this behavior for API consumers.

Example:

  * Get the request protocol.
  *
- * If `x-forwarded-proto` header is set to "https", it will return "https". You can disable this behavior by setting `xForwardedProto` to `false`.
+ * If the first entry of the `x-forwarded-proto` header (comma-separated list supported) is "https", it will return "https". You can disable this behavior by setting `xForwardedProto` to `false`.
  *
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/utils/request.ts` around lines 377 - 388, Update the JSDoc for
getRequestProtocol to document that the function supports comma-separated
x-forwarded-proto values: when the header contains multiple comma-separated
protocols the function will use the first entry (trimmed) and compare it to
"https"; also note that this behavior can be disabled via the xForwardedProto
parameter and that the fallback remains "http" when protocol cannot be
determined. Include a short example showing a comma-separated header and that
the first value is used.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/utils/request.ts`:
- Around line 377-388: Update the JSDoc for getRequestProtocol to document that
the function supports comma-separated x-forwarded-proto values: when the header
contains multiple comma-separated protocols the function will use the first
entry (trimmed) and compare it to "https"; also note that this behavior can be
disabled via the xForwardedProto parameter and that the fallback remains "http"
when protocol cannot be determined. Include a short example showing a
comma-separated header and that the first value is used.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4403885f-6b47-41a5-b678-206f6d063250

📥 Commits

Reviewing files that changed from the base of the PR and between 7eb018e and 400993d.

📒 Files selected for processing (3)
  • src/utils/request.ts
  • test/unit/request.test.ts
  • test/utils.test.ts

@pi0x pi0x left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Note: this review was performed by AI agents (Claude Code) on behalf of the maintainer, in two independent passes.

Pass 1 reviewed the diff for correctness, edge cases, and test coverage. Pass 2 (a fresh agent, adversarial by design) independently re-read the diff, checked for merge conflicts/CI status, and tried to find a reason to block approval before this review was posted. Both passes agree this change is correct, adequately tested, and safe to merge.

Caveat: this repo's real CI workflow (lint + build + vitest) requires maintainer approval to run on fork PRs and has not executed on this PR yet — only automated third-party checks (CodeRabbit, Socket Security) have run. Please trigger/approve the CI workflow before merging.

@pi0 pi0 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.

Thanks!

@pi0
pi0 merged commit 0c69d1e into h3js:main Jul 2, 2026
4 of 5 checks passed
@codecov

codecov Bot commented Jul 2, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

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.

3 participants