You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Nginx搭配FastAPI环境中如何获取用户真实IP?

在Nginx+Docker部署的FastAPI中获取用户真实IP的解决方法

问题根源

部署在Docker环境下时,request.client.host返回的是Nginx容器的IP而非用户真实IP,这是因为FastAPI直接接收来自Nginx容器的请求,而非用户的原始请求。要解决这个问题,需要让Nginx把用户真实IP通过HTTP头传递给FastAPI,再在FastAPI中正确读取这些头信息。

第一步:修正Nginx配置

确保Nginx的反向代理配置中添加了传递真实IP的Header,否则FastAPI无法拿到正确的IP。在你的Nginx location 块中添加以下配置:

location / {
    proxy_pass http://your-fastapi-container-name:8000;  # 替换为你的FastAPI容器名称/IP+端口
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;  # 直接传递用户真实IP
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  # 传递完整的IP链(用户IP在前)
    proxy_set_header X-Forwarded-Proto $scheme;
}

修改后重启Nginx服务生效。

第二步:FastAPI中读取真实IP的两种有效方法

方法一:直接读取HTTP Header(无需额外依赖)

这是最轻量化的方案,直接读取Nginx传递的X-Real-IP或X-Forwarded-For头:

from fastapi import FastAPI, Header, Request

app = FastAPI()

@app.get("/get-ip")
def get_user_real_ip(
    request: Request,
    x_real_ip: str = Header(None),
    x_forwarded_for: str = Header(None)
):
    # 优先使用X-Real-IP,若不存在则从X-Forwarded-For取第一个IP,最后 fallback 到request.client.host
    real_ip = x_real_ip 
    if not real_ip and x_forwarded_for:
        real_ip = x_forwarded_for.split(',')[0].strip()
    if not real_ip:
        real_ip = request.client.host
    return {"user_real_ip": real_ip}

你之前的代码部署后无效,大概率是因为Nginx没配置proxy_set_header X-Real-IP $remote_addr;,补全配置后即可生效。

方法二:使用starlette_context插件(更优雅的多场景支持)

如果你需要在多个接口中复用IP获取逻辑,可以用starlette_context来统一处理:

  1. 先安装依赖:
pip install starlette-context
  1. 编写FastAPI代码:
from fastapi import FastAPI
from starlette_context import middleware, plugins
from starlette_context import context

app = FastAPI()

# 添加上下文中间件,同时支持X-Real-IP和X-Forwarded-For
app.add_middleware(
    middleware.ContextMiddleware,
    plugins=(
        plugins.RealIPPlugin(),       # 处理X-Real-IP头
        plugins.ForwardedForPlugin(), # 处理X-Forwarded-For头
    ),
)

@app.get("/")
def get_ip():
    real_ip = context.data.get("X-Real-IP")
    forwarded_for = context.data.get("X-Forwarded-For")
    
    user_ip = real_ip or (forwarded_for.split(',')[0].strip() if forwarded_for else None)
    return {"hello": "world", "user_real_ip": user_ip}

额外注意事项

  • 确保Nginx容器和FastAPI容器处于同一个Docker网络中,避免跨网络导致Header传递异常。
  • 不要直接将FastAPI容器的端口暴露到公网,必须通过Nginx反向代理,否则无法获取用户真实IP。

内容的提问来源于stack exchange,提问作者Ch1irxo 17

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 09:21:14