FastAPI (Starlette) + NGINX 代理:请求对象中的 URL 方案不正确?

问题描述 投票:0回答:1

我想了解以下内容

  • Starlette 如何在 Request 对象中设置“url”属性 - 特别是在 NGINX 代理后面操作时。
  • 如何在 NGINX 级别上操作
    request.url
    ——设置代理标头根本不会修改它?
  • 如何通过 Starlette 中间件操纵
    request.url
    ——不知何故我所做的没有任何效果?

设置是这样的:

我有一个 FastAPI 应用程序在 NGINX 代理后面运行。通过浏览器,我通过 HTTPS 向 NGINX 发送请求 (

https://www.example.com
),但无论我做什么,Starlette 这边的
request.url
始终是
http://www.example.com

我制作了一个小型 FastAPI 端点用于演示目的

@app.get("/test")
def some_test(request: Request):
    return {"request.url": request.url,
            "request['headers']": request["headers"],
            "request.client": request.client}

在下面的屏幕截图中,我展示了我得到的内容(域名是匿名的;设置为

xyz
): enter image description here

  1. 我在浏览器中调用
    https://www.example.com/test
  2. 在控制台中,我看到请求正确地发送给了
    https://www.example.com/test
  3. 但是当看Starlette的
    Request.url
    时,它说
    http://www.example.com/test

这种行为是应该的吗?在屏幕截图中,我还打印了

host
x-forwarded-proto
x-forwarded-schema
,我将 NGINX 配置设置为 HTTPS,但对象
Request
根本没有被修改。

如何在 NGINX 或 FastAPI/Starlette 级别纠正此问题?

  • 我已经尝试过设置各种命令,例如
    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;
    proxy_set_header X-Forwarded-Scheme $scheme;
    
    完全没有成功。
  • 我尝试编写一个自定义的 Starlette 中间件(我知道这很丑陋,但我想尝试一下以更好地理解发生了什么)
    from fastapi import Request
    from starlette.datastructures import URL
    
    @app.middleware("http")
    async def some_middlware(request: Request, call_next):
    
        if "/test" in str(request.url):
            print(f"before {request.url}")
            request._url = URL(str(request.url).replace("http", "https"))
            print(f"after {request.url}")
    
        response = await call_next(request)
        return response
    
    但这也不会修改响应中显示的
    request.url
nginx https fastapi reverse-proxy starlette
1个回答
2
投票

现在架构的代理可以工作了。

问题如下:

我的 Dockerfile 看起来像之前

ENTRYPOINT ["uvicorn", "main:app", "--proxy-headers", "--forwarded-allow-ips='*'", "--host", "0.0.0.0"]

--forwarded-allow-ips
参数中的引号不起作用。相反,入口点应为

ENTRYPOINT ["uvicorn", "main:app", "--proxy-headers", "--forwarded-allow-ips=*", "--host", "0.0.0.0"]

提示:为了更简洁,不应允许

*
作为 IP 地址,而应指定 IP 地址。

© www.soinside.com 2019 - 2024. All rights reserved.