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

FastAPI(Starlette)搭配NGINX代理:Request对象URL协议异常问题

解决NGINX代理后Starlette/FastAPI的Request.url协议异常问题

核心原因

Starlette默认不会自动读取X-Forwarded-Proto这类代理头来重构请求URL,它直接使用与NGINX之间的通信协议(通常为HTTP)生成request.url,所以即便客户端用HTTPS请求NGINX,Starlette端仍会显示HTTP协议。


1. Starlette如何在NGINX代理场景下设置Request.url?

Starlette官方提供了ForwardedHeadersMiddleware专门处理代理场景的URL重构,无需手动修改私有属性。只需启用该中间件并配置信任的代理IP,Starlette就会自动读取NGINX传递的代理头,生成包含正确HTTPS协议的request.url。

2. NGINX层面如何配置才能让Starlette识别正确URL?

NGINX无法直接修改Starlette的request.url,但可以通过传递正确的代理头让Starlette自行重构。你的现有配置基本正确,但需确保X-Forwarded-Proto传递的是客户端实际使用的协议(HTTPS),同时配合Starlette的信任代理配置生效。

3. 为什么自定义中间件修改request.url无效?

Starlette的Request对象设计为不可变结构,直接修改私有属性_url不会被后续请求处理逻辑正确识别。必须通过修改请求的scope上下文或使用官方中间件来实现URL重构。


具体解决方案

方案1:使用Starlette官方ForwardedHeadersMiddleware(推荐)

在FastAPI应用中添加该中间件,指定信任的代理IP(比如NGINX所在服务器的IP):

from fastapi import FastAPI
from starlette.middleware.forwardedheaders import ForwardedHeadersMiddleware

app = FastAPI()

# 配置信任的代理IP,本地代理填["127.0.0.1"],生产环境填NGINX服务器的实际IP/子网
app.add_middleware(ForwardedHeadersMiddleware, trusted_hosts=["127.0.0.1", "::1"])

方案2:修正NGINX代理配置

确保NGINX正确传递代理头,特别是X-Forwarded-Proto:

location / {
    proxy_pass http://your-fastapi-service:8000; # 替换为你的FastAPI服务地址
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Host $http_host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme; # 传递客户端请求的协议(HTTPS)
    proxy_set_header X-Forwarded-Host $host;
}

方案3:自定义中间件的正确写法(不推荐,仅作参考)

如果一定要用自定义中间件,需要修改请求的scope上下文并重新生成URL:

from fastapi import Request
from starlette.datastructures import URL

@app.middleware("http")
async def fix_url_scheme(request: Request, call_next):
    # 修改scope中的scheme字段
    request.scope["scheme"] = "https"
    # 重新构建URL对象
    request._url = URL(
        scheme=request.scope["scheme"],
        netloc=f"{request.scope['server'][0]}:{request.scope['server'][1]}" if request.scope.get("server") else request.scope["host"],
        path=request.scope["path"],
        query_string=request.scope["query_string"]
    )
    response = await call_next(request)
    return response

验证

配置完成后重新启动NGINX和FastAPI服务,访问https://www.example.com/test,返回的request.url应显示为https://www.example.com/test,同时request['headers']中会包含x-forwarded-proto: https。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 10:48:20