Skip to content

Conversation

@jnschaeffer
Copy link

What kind of change does this PR introduce?

This PR updates performRateLimiting to treat the rate limit header value as a comma-separated list and enforce rate limiting based on the first value in that list.

What is the current behavior?

Certain HTTP headers, such as X-Forwarded-For and other headers that are combined according to RFC 7230, can be represented as a comma-separated list of values. Intermediate proxies may add their own values to these headers, modifying the resulting value. For example, an end user with a single IP address proxied through a fleet of load balancers using the X-Forwarded-For header may be associated with multiple X-Forwarded-For header values, e.g., 2.2.2.2,100.100.100.100 and 2.2.2.2,300.300.300.300. The current implementation of performRateLimiting treats each of these as separate rate limiting keys.

What is the new behavior?

This PR splits the rate limit header by commas and takes the first value (with whitespace removed) to use as the rate limiting key.

Note that this logic is superficially similar to the utilities.GetIPAddress function with two key differences. In performRateLimiting, there is no set format for a given rate limiting key, nor is there a fallback value after the first value in the list that the API should use.

This commit changes the conditional logic in performRateLimiting to
prefer returning early rather than nesting if/else statements.

This is largely preparation for changing the behavior of
performRateLimiting to accept comma-separated lists of header values,
which will incur some additional conditional logic.
This commit updates performRateLimiting to treat the rate limit header
value as a comma-separated list and enforce rate limiting based on the
first value in that list.

Certain HTTP headers, such as X-Forwarded-For and other headers that
are combined according to RFC 7230, can be represented as a
comma-separated list of values. Intermediate proxies may add their own
values to these headers, modifying the resulting value. For example,
an end user with a single IP address proxied through a fleet of load
balancers using the X-Forwarded-For header may be associated with
multiple X-Forwarded-For header values, e.g.,
"2.2.2.2,100.100.100.100" and "2.2.2.2,300.300.300.300". The current
implementation of performRateLimiting treats each of these as separate
rate limiting keys.

To address this issue, this commit splits the rate limit header by
commas and takes the first value (with whitespace removed) to use as
the rate limiting key.

Note that this logic is superficially similar to the
utilities.GetIPAddress function with two key differences. In
performRateLimiting, there is no set format for a given rate limiting
key, nor is there a fallback value after the first value in the list
that the API should use.
@jnschaeffer jnschaeffer requested a review from a team as a code owner December 5, 2025 18:10
@coveralls
Copy link

Pull Request Test Coverage Report for Build 19971839037

Details

  • 24 of 26 (92.31%) changed or added relevant lines in 1 file are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.01%) to 68.449%

Changes Missing Coverage Covered Lines Changed/Added Lines %
internal/api/middleware.go 24 26 92.31%
Totals Coverage Status
Change from base Build 19871602451: 0.01%
Covered Lines: 14655
Relevant Lines: 21410

💛 - Coveralls

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