fix: Nginx 重定向 + 自定义 404 — 隐藏 FastAPI 后端信息
nginx_https.conf 新增注释化重定向规则,将裸页面路径 301 到 /app/ 前缀; main.py 添加 StarletteHTTPExceptionHandler,404 返回空白 HTML 而非 JSON, 避免泄露后端框架标识。 Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -93,6 +93,12 @@ server {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# ── Redirect bare page paths to /app/ (for reverse-proxy deployments) ──
|
||||
# If you use proxy_pass instead of root+try_files, uncomment this block:
|
||||
# location ~ ^/(login|index|servers|files|push|scripts|script-executions|credentials|schedules|retries|commands|alerts|audit|settings|install|terminal|assets)\.html$ {
|
||||
# return 301 /app/$1.html;
|
||||
# }
|
||||
|
||||
# ── Static HTML pages (no SPA — each page is standalone) ──
|
||||
location / {
|
||||
try_files $uri $uri/ =404;
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# 2026-05-30 Nginx 静态文件路径重定向 + 部署文档更新
|
||||
|
||||
## 背景
|
||||
FastAPI 静态文件挂在 `/app/` 路径下,访问不带 `/app/` 前缀的 URL(如 `/login.html`)时,FastAPI 返回 JSON `{"detail":"Not Found"}`,浏览器直接渲染白屏显示该错误。
|
||||
|
||||
## 变更内容
|
||||
|
||||
### 1. Nginx 配置 (远程)
|
||||
在 `location /` 前插入重定向规则,15 个页面路径自动 301 到 `/app/` 下:
|
||||
```nginx
|
||||
location ~ ^/(login|index|servers|files|push|scripts|script-executions|credentials|schedules|retries|commands|alerts|audit|settings|install|terminal|assets)\.html$ {
|
||||
return 301 /app/$1.html;
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 部署模板更新
|
||||
`deploy/nginx_https.conf` 新增注释块,提示反代部署时取消注释该重定向规则。
|
||||
|
||||
## 涉及文件
|
||||
- `deploy/nginx_https.conf` — 模板注释
|
||||
- `/www/server/panel/vhost/nginx/api.synaglobal.vip.conf` — 实际生效
|
||||
|
||||
## 验证
|
||||
- `nginx -t` 通过
|
||||
- 浏览器访问 `/login.html` → 301 → `/app/login.html`,不再显示 JSON 错误
|
||||
+14
-1
@@ -24,6 +24,8 @@ from contextlib import asynccontextmanager
|
||||
from pathlib import Path
|
||||
|
||||
from fastapi import FastAPI, Request
|
||||
from fastapi.responses import HTMLResponse
|
||||
from starlette.exceptions import HTTPException as StarletteHTTPException
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
|
||||
@@ -446,6 +448,16 @@ app.include_router(sync_v2_router)
|
||||
# Global Search
|
||||
app.include_router(search_router)
|
||||
|
||||
# ── Custom 404: return blank HTML to hide backend identity ──
|
||||
@app.exception_handler(StarletteHTTPException)
|
||||
async def custom_http_exception_handler(request: Request, exc: StarletteHTTPException):
|
||||
"""Convert 404 JSON to blank HTML — don't leak backend (FastAPI) info."""
|
||||
if exc.status_code == 404:
|
||||
return HTMLResponse(status_code=404)
|
||||
# Let other HTTP exceptions return normally (auth errors, validation errors, etc.)
|
||||
from fastapi.responses import JSONResponse
|
||||
return JSONResponse(status_code=exc.status_code, content={"detail": exc.detail})
|
||||
|
||||
# ── Static files: serve web/app/ at /app/ (HTML pages + JS/CSS assets) ──
|
||||
# In production, Nginx serves these directly; this is for dev/standalone mode.
|
||||
WEB_APP_DIR = ROOT_DIR / "web" / "app"
|
||||
@@ -456,4 +468,5 @@ if WEB_APP_DIR.is_dir():
|
||||
# Required by remote install: curl -fsSL {base_url}/agent/install.sh
|
||||
WEB_AGENT_DIR = ROOT_DIR / "web" / "agent"
|
||||
if WEB_AGENT_DIR.is_dir():
|
||||
app.mount("/agent", StaticFiles(directory=str(WEB_AGENT_DIR)), name="static_agent")
|
||||
app.mount("/agent", StaticFiles(directory=str(WEB_AGENT_DIR)), name="static_agent")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user