Skip to content

get_ipaddr reads wrong header key ("X_FORWARDED_FOR") and doesn't parse X-Forwarded-For list #255

@idlefella

Description

@idlefella

Describe the bug
The function get_ipaddr in slowapi/util.py checks for the header "X_FORWARDED_FOR" (underscores). In practice the header is "X-Forwarded-For" (hyphens) and ASGI/Starlette expose headers case-insensitively (commonly accessible via lowercased keys). Because of this the header lookup fails and the function falls back to request.client.host or "127.0.0.1".

slowapi/slowapi/util.py

Lines 4 to 17 in 5e2b9c1

def get_ipaddr(request: Request) -> str:
"""
Returns the ip address for the current request (or 127.0.0.1 if none found)
based on the X-Forwarded-For headers.
Note that a more robust method for determining IP address of the client is
provided by uvicorn's ProxyHeadersMiddleware.
"""
if "X_FORWARDED_FOR" in request.headers:
return request.headers["X_FORWARDED_FOR"]
else:
if not request.client or not request.client.host:
return "127.0.0.1"
return request.client.host

To Reproduce
Run a fastapi application behind a reverse proxy like nginx.

Expected behavior
The rate limit should be by the original client IP address (from the X-Forwarded-For header), not by the proxy's IP or the fallback 127.0.0.1. When a reverse proxy sets the X-Forwarded-For header, get_ipaddr should correctly extract and return the client's real IP address for rate limiting purposes.

Screenshots
No screenshots.

Your app (please complete the following information):

  • fastapi or starlette? fastapi
  • Version? [e.g., fastapi 0.115+]
  • slowapi version (have you tried with the latest version)? 0.1.9

Additional context

None

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions