希望你能帮助我,这是我遇到的问题:
我的前端和后端服务器都运行在同一个 AWS EC2 实例上。因此,我创建了一个像这样的 NGINX 配置:
server {
server_name NAME;
listen 80 default_server;
location / {
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_http_version 1.1;
}
location /api/ {
proxy_pass http://127.0.0.1:8000;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_http_version 1.1;
}
}
因此,任何对 “http://public_ip/api/” 的请求都会路由到 FastAPI 后端服务器,而对另一个端点的所有其他请求都会路由到前端 SPA。
这在大多数情况下都很好用。但是,如果我尝试访问 FastAPI "/api/docs" 或 "/api/redoc" 路由,则会出现问题。例如,当我调用 "/api/docs" 端点时,有一个对 "http://public_ip/openapi.json" 地址的请求。这显然不是以 "/api" 开头的端点。所以 NGINX 阻止了它并提出了一个错误的请求。
https://fastapi.tiangolo.com/advanced/behind-a-proxy/#about-proxies-with-a-stripped-path-prefix
我找到了本指南,但似乎与我的问题完全无关。至少我是这样理解的。
任何帮助表示赞赏。提前致谢。
将 'openapi_url' 参数传递给 FastAPI() 似乎是一个很好的解决方案。通过 openapi_url= '/api/openapi.json' 并且它对文档和 redoc 都是固定的。感谢任何其他/更好的解决方案来处理可能发生的所有重定向。
api = FastAPI(title="API_NAME",
description="API_DESC",
version="0.2.0",
docs_url='/api/docs',
redoc_url='/api/redoc',
openapi_url='/api/openapi.json')
对我来说,它的工作方式如下:
我的docker容器的入口点脚本:
echo "Running the FastAPI server"
uvicorn server:app --host 0.0.0.0 --port 8000 --app-dir dashboard/api/ --root-path /api/ --forwarded-allow-ips "*" --reload &
FastAPI 应用程序:
import uvicorn
from typing import Union
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI() # root_path="/api/"
origins = ['*']
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.get("/")
async def read_root():
return {"message": "Hello from FastAPI"}
@app.get("/test")
def read_main(request: Request):
return {"message": "Hello World", "root_path": request.scope.get("root_path")}
# if __name__ == "__main__":
# uvicorn.run(app, host='0.0.0.0', port=8000)
NGINX 配置:
upstream dashboard {
server localhost:8081;
}
upstream apiserver {
server localhost:8000;
}
server {
listen 8080 default_server;
listen [::]:8080 default_server;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
}
location /dashboard/ {
proxy_pass http://dashboard;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-Proto $scheme;
}
location /api/ {
rewrite ^/api/(.*) /$1 break;
proxy_set_header Host $http_host;
proxy_pass http://apiserver;
}
}
现在在 docker 容器之外一切正常:
curl http://0.0.0.0:28080/api/
curl http://0.0.0.0:28080/api/test
curl http://0.0.0.0:28080/api/openapi.json
curl http://0.0.0.0:28080/api/docs
在 docker 容器内它也可以工作:
curl http://0.0.0.0:8000/
curl http://0.0.0.0:8000/test
curl http://0.0.0.0:8000/openapi.json
curl http://0.0.0.0:8000/docs