我想了解以下内容
request.url
——设置代理标头根本不会修改它?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
):
https://www.example.com/test
https://www.example.com/test
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;
完全没有成功。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
。现在架构的代理可以工作了。
问题如下:
我的 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 地址。