在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来统一处理:
- 先安装依赖:
pip install starlette-context
- 编写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
相关产品推荐
相关产品推荐

