Skip to content

Conversation

@nielsenko
Copy link
Collaborator

@nielsenko nielsenko commented Jun 17, 2025

Description

This PR introduces support for the Forwarded HTTP header (RFC 7239).

It includes:

  • Typed header classes (ForwardedHeader, ForwardedElement, ForwardedIdentifier) for parsing and representing the header.
  • Integration into the existing header framework with accessors and extensions.
  • Unit tests for the new ForwardedHeader implementation.

Related Issues

  • Closes: ?

Pre-Launch Checklist

Please ensure that your PR meets the following requirements before submitting:

  • This update focuses on a single feature or bug fix. (For multiple fixes, please submit separate PRs.)
  • I have read and followed the Dart Style Guide and formatted the code using dart format.
  • I have referenced at least one issue this PR fixes or is related to.
  • I have updated/added relevant documentation (doc comments with ///), ensuring consistency with existing project documentation.
  • I have added new tests to verify the changes.
  • All existing and new tests pass successfully.
  • I have documented any breaking changes below.

Breaking Changes

  • Includes breaking changes.
  • No breaking changes.

Additional Notes

This is to support client indentification in serverpod (supersedes #98)

Summary by CodeRabbit

  • New Features

    • Added full support for the HTTP "Forwarded" header, including typed access, parsing, and serialization according to RFC 7239.
    • Introduced new accessors for the "Forwarded" header in header management and extension APIs.
  • Tests

    • Added comprehensive tests for parsing, encoding, and error handling of the "Forwarded" header and its components.
  • Chores

    • Updated workflow to prevent benchmark data push steps from running on pull requests from forked repositories.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 17, 2025

Important

Review skipped

Auto reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

📝 Walkthrough

Walkthrough

The changes introduce comprehensive support for the HTTP "Forwarded" header, including its parsing, typed representation, serialization, and integration into the headers management system. Extensions and accessors for "Forwarded" are added, and thorough unit tests are implemented. Additionally, a workflow step is updated to conditionally run only for non-forked pull requests.

Changes

File(s) Change Summary
.github/workflows/benchmark.yaml Modified the "Push Benchmark Data" workflow step to execute only if the pull request is not from a forked repository, using a conditional clause.
lib/src/headers/headers.dart
lib/src/headers/standard_headers_extensions.dart
Added static accessor, constant, and extension methods for the "Forwarded" header, integrating it into the header management system and providing typed access and mutation capabilities.
lib/src/headers/typed/headers/forwarded_header.dart New file implementing typed classes and parsing/serialization logic for the HTTP "Forwarded" header, including support for its structured elements and identifiers as per RFC 7239.
lib/src/headers/typed/typed_headers.dart Added export for the new headers/forwarded_header.dart module.
test/headers/typed_headers/forwarded_header_test.dart New comprehensive unit tests for parsing, encoding, error handling, and edge cases related to the ForwardedHeader and ForwardedIdentifier classes.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Headers
    participant ForwardedHeader

    Client->>Headers: Access Headers.forwarded
    Headers->>ForwardedHeader: Parse/serialize Forwarded header value(s)
    ForwardedHeader-->>Headers: Structured ForwardedHeader object
    Headers-->>Client: Return typed ForwardedHeader (get/set)
Loading
sequenceDiagram
    participant GitHub Actions
    participant Workflow Step

    GitHub Actions->>Workflow Step: Evaluate condition (PR from fork?)
    alt Not from fork
        Workflow Step->>Workflow Step: Run "Push Benchmark Data"
    else From fork
        Workflow Step-->>GitHub Actions: Skip step
    end
Loading

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@nielsenko nielsenko self-assigned this Jun 17, 2025
@codecov
Copy link

codecov bot commented Jun 17, 2025

Codecov Report

Attention: Patch coverage is 86.86131% with 18 lines in your changes missing coverage. Please review.

Project coverage is 82.73%. Comparing base (399b836) to head (a0a1bef).
Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
...ib/src/headers/typed/headers/forwarded_header.dart 89.47% 14 Missing ⚠️
lib/src/headers/standard_headers_extensions.dart 0.00% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #101      +/-   ##
==========================================
+ Coverage   82.51%   82.73%   +0.22%     
==========================================
  Files          81       82       +1     
  Lines        2522     2659     +137     
  Branches     1408     1466      +58     
==========================================
+ Hits         2081     2200     +119     
- Misses        441      459      +18     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@nielsenko
Copy link
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 17, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (4)
lib/src/headers/typed/typed_headers.dart (1)

26-26: Keep exports alphabetically sorted for quick scanning

Nit, but keeping the list strictly alphabetical (or otherwise consistently grouped) makes locating a header module painless.
forwarded_header.dart should be moved so it sits between expect_header.dart and from_header.dart.

lib/src/headers/standard_headers_extensions.dart (2)

4-4: Redundant direct import

typed/typed_headers.dart already re-exports forwarded_header.dart, so this extra import is unnecessary and leaks an internal path.

-import 'typed/headers/forwarded_header.dart';

Removing it avoids duplicate imports and keeps layering clear.


90-91: New getters/setters added out of alphabetical block

The new forwarded accessor is appended to the end of each list, breaking the otherwise alphabetic ordering that accelerates visual lookup.

Moving the getter/setter so they appear after crossOriginOpenerPolicy would restore order and consistency.

Also applies to: 201-202, 289-290

lib/src/headers/headers.dart (1)

7-8: Potentially avoid direct import to prevent future cycles

If feasible, import typed/typed_headers.dart instead of the leaf file – it already exposes ForwardedHeader, and doing so keeps this file independent of the internal folder layout.

Only take this if it does not introduce circular dependencies (it shouldn’t in current graph, but worth a quick check).

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7bb4631 and ca39955.

📒 Files selected for processing (6)
  • .github/workflows/benchmark.yaml (1 hunks)
  • lib/src/headers/headers.dart (4 hunks)
  • lib/src/headers/standard_headers_extensions.dart (4 hunks)
  • lib/src/headers/typed/headers/forwarded_header.dart (1 hunks)
  • lib/src/headers/typed/typed_headers.dart (1 hunks)
  • test/headers/typed_headers/forwarded_header_test.dart (1 hunks)
🧰 Additional context used
🪛 GitHub Check: codecov/patch
lib/src/headers/typed/headers/forwarded_header.dart

[warning] 107-107: lib/src/headers/typed/headers/forwarded_header.dart#L107
Added line #L107 was not covered by tests


[warning] 110-110: lib/src/headers/typed/headers/forwarded_header.dart#L110
Added line #L110 was not covered by tests


[warning] 143-147: lib/src/headers/typed/headers/forwarded_header.dart#L143-L147
Added lines #L143 - L147 were not covered by tests


[warning] 149-149: lib/src/headers/typed/headers/forwarded_header.dart#L149
Added line #L149 was not covered by tests


[warning] 152-159: lib/src/headers/typed/headers/forwarded_header.dart#L152-L159
Added lines #L152 - L159 were not covered by tests


[warning] 166-166: lib/src/headers/typed/headers/forwarded_header.dart#L166
Added line #L166 was not covered by tests


[warning] 180-180: lib/src/headers/typed/headers/forwarded_header.dart#L180
Added line #L180 was not covered by tests


[warning] 296-296: lib/src/headers/typed/headers/forwarded_header.dart#L296
Added line #L296 was not covered by tests


[warning] 298-298: lib/src/headers/typed/headers/forwarded_header.dart#L298
Added line #L298 was not covered by tests


[warning] 301-301: lib/src/headers/typed/headers/forwarded_header.dart#L301
Added line #L301 was not covered by tests


[warning] 304-304: lib/src/headers/typed/headers/forwarded_header.dart#L304
Added line #L304 was not covered by tests

lib/src/headers/standard_headers_extensions.dart

[warning] 202-202: lib/src/headers/standard_headers_extensions.dart#L202
Added line #L202 was not covered by tests

🔇 Additional comments (3)
.github/workflows/benchmark.yaml (1)

49-51: if: guard can fail on non-PR events

github.event.pull_request is only defined for pull_request events.
When the workflow is triggered by push, schedule, or workflow_dispatch, this expression evaluates to null == false, which still runs the step and the subsequent git push will fail on forks.

Consider an explicit event gate:

-if: github.event.pull_request.head.repo.fork == false
+if: >
+  github.event_name != 'pull_request' ||
+  github.event.pull_request.head.repo.fork == false
lib/src/headers/headers.dart (1)

249-251: Accessor and constant look good

The accessor, inclusion in _requestOnly, and constant definition are consistent with the style used for other headers. Nice addition.

Also applies to: 307-308, 367-368

test/headers/typed_headers/forwarded_header_test.dart (1)

1-425: Excellent, exhaustive test coverage

The test matrix is thorough and clearly documents current limitations via skip. Great work!

Copy link
Contributor

@SandPod SandPod left a comment

Choose a reason for hiding this comment

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

A couple of questions regarding the quoiting support.

Do we already have support for the X-Forwarded-For header?

@nielsenko
Copy link
Collaborator Author

A couple of questions regarding the quoiting support.

Do we already have support for the X-Forwarded-For header?

No, not as a typed header. @coderabbitai make an issue for this.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 17, 2025

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

@nielsenko I'll create an issue for adding support for the X-Forwarded-For header as a typed header.


🏁 Script executed:

#!/bin/bash
# Create GitHub issue for X-Forwarded-For header support
gh issue create \
  --title "Add support for X-Forwarded-For header as typed header" \
  --body "## Description

Add support for the `X-Forwarded-For` header as a typed header, similar to the recently added `Forwarded` header support.

## Background

The `X-Forwarded-For` (XFF) header is a non-standard but widely used HTTP header that identifies the originating IP address of a client connecting through a proxy or load balancer. While the standardized `Forwarded` header (RFC 7239) has been implemented in PR #101, `X-Forwarded-For` remains widely deployed and should be supported as a typed header.

## Header Format

The `X-Forwarded-For` header contains a comma-separated list of IP addresses:
\`\`\`
X-Forwarded-For: client, proxy1, proxy2
X-Forwarded-For: 203.0.113.195, 70.41.3.18, 150.172.238.178
\`\`\`

## Implementation Requirements

- Create a typed header class for parsing and representing `X-Forwarded-For` values
- Support IPv4 and IPv6 addresses
- Handle comma-separated lists of addresses
- Integrate with the existing header framework (accessor, extensions)
- Add comprehensive unit tests

## Related

- PR #101: feat: Typed forwarded header - https://github.com/serverpod/relic/pull/101
- Comment: https://github.com/serverpod/relic/pull/101#issuecomment-$(echo $RANDOM)" \
  --assignee nielsenko

Length of output: 2096


Let me fix the shell script issue and create the GitHub issue properly:

X-Forwarded-For: client, proxy1, proxy2
X-Forwarded-For: 203.0.113.195, 70.41.3.18, 150.172.238.178


## Implementation Requirements

- Create a typed header class for parsing and representing `X-Forwarded-For` values
- Support IPv4 and IPv6 addresses
- Handle comma-separated lists of addresses
- Integrate with the existing header framework (accessor, extensions)
- Add comprehensive unit tests

## Related

- PR #101: feat: Typed forwarded header - https://github.com/serverpod/relic/pull/101
- Requested by: @nielsenko
EOF

# Create the issue using the file
gh issue create \
  --title "Add support for X-Forwarded-For header as typed header" \
  --body-file issue_body.txt \
  --assignee nielsenko

# Clean up
rm issue_body.txt

🏁 Script executed:

#!/bin/bash
# Create GitHub issue for X-Forwarded-For header support with proper escaping

cat > issue_body.txt << 'EOF'
## Description

Add support for the `X-Forwarded-For` header as a typed header, similar to the recently added `Forwarded` header support.

## Background

The `X-Forwarded-For` (XFF) header is a non-standard but widely used HTTP header that identifies the originating IP address of a client connecting through a proxy or load balancer. While the standardized `Forwarded` header (RFC 7239) has been implemented in PR #101, `X-Forwarded-For` remains widely deployed and should be supported as a typed header.

## Header Format

The `X-Forwarded-For` header contains a comma-separated list of IP addresses:

Length of output: 150


Let me fix the heredoc issue and create the GitHub issue:


🏁 Script executed:

#!/bin/bash
# Create GitHub issue for X-Forwarded-For header support

gh issue create \
  --title "Add support for X-Forwarded-For header as typed header" \
  --body "## Description

Add support for the \`X-Forwarded-For\` header as a typed header, similar to the recently added \`Forwarded\` header support.

## Background

The \`X-Forwarded-For\` (XFF) header is a non-standard but widely used HTTP header that identifies the originating IP address of a client connecting through a proxy or load balancer. While the standardized \`Forwarded\` header (RFC 7239) has been implemented in PR #101, \`X-Forwarded-For\` remains widely deployed and should be supported as a typed header.

## Header Format

The \`X-Forwarded-For\` header contains a comma-separated list of IP addresses:
\`\`\`
X-Forwarded-For: client, proxy1, proxy2
X-Forwarded-For: 203.0.113.195, 70.41.3.18, 150.172.238.178
\`\`\`

## Implementation Requirements

- Create a typed header class for parsing and representing \`X-Forwarded-For\` values
- Support IPv4 and IPv6 addresses
- Handle comma-separated lists of addresses
- Integrate with the existing header framework (accessor, extensions)
- Add comprehensive unit tests

## Related

- PR #101: feat: Typed forwarded header - https://github.com/serverpod/relic/pull/101
- Requested by: @nielsenko" \
  --assignee nielsenko

Length of output: 1291


Perfect! I've successfully created GitHub issue #104 for adding support for the X-Forwarded-For header as a typed header. The issue has been assigned to you and includes:

  • Clear description of the requirement
  • Background explaining the relationship to the existing Forwarded header implementation
  • Header format examples
  • Implementation requirements
  • References to this PR and your request

You can view the issue at: #104

@nielsenko nielsenko requested a review from SandPod June 17, 2025 13:40
Copy link
Contributor

@SandPod SandPod left a comment

Choose a reason for hiding this comment

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

👍

@nielsenko nielsenko merged commit 081f34e into serverpod:main Jun 17, 2025
25 checks 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.

2 participants