feat(auth): 内测登录改为显式开关,并支持后端单端口托管前端产物
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from contextlib import asynccontextmanager
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from fastapi import FastAPI, Request
|
||||
@@ -11,6 +12,9 @@ from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.responses import JSONResponse
|
||||
from sqlalchemy import text
|
||||
from starlette.exceptions import HTTPException as StarletteHTTPException
|
||||
from starlette.responses import Response
|
||||
from starlette.staticfiles import StaticFiles
|
||||
from starlette.types import Scope
|
||||
|
||||
from .api import attachments, auth, items, knowledge, tickets, workspaces
|
||||
from .config import get_settings
|
||||
@@ -27,6 +31,11 @@ logger = get_logger("app")
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
settings.validate_runtime()
|
||||
if settings.env == "prod" and settings.internal_test_login:
|
||||
logger.warning(
|
||||
"内测登录已开启:任意手机号可用固定验证码登录,只能在内网访问,切勿暴露公网",
|
||||
extra={"extra_fields": {"sms_provider": settings.sms_provider}},
|
||||
)
|
||||
logger.info(
|
||||
"服务启动",
|
||||
extra={"extra_fields": {"env": settings.env, "commit": settings.build_commit}},
|
||||
@@ -138,3 +147,22 @@ async def version() -> dict:
|
||||
"api_prefix": settings.api_prefix,
|
||||
"db_role": role,
|
||||
}
|
||||
|
||||
|
||||
# ── 前端产物:单端口部署(没有 nginx 时也让一个端口提供完整站点)────────
|
||||
# 顺序很重要:必须挂在所有 API 路由之后,否则挂载 "/" 会吞掉 /api、/health、/version。
|
||||
class _SPAStaticFiles(StaticFiles):
|
||||
"""静态命中就返回,未命中回退 index.html——前端路由(如 /w/<id>)交给浏览器处理。"""
|
||||
|
||||
async def get_response(self, path: str, scope: Scope) -> Response:
|
||||
try:
|
||||
return await super().get_response(path, scope)
|
||||
except StarletteHTTPException as exc:
|
||||
if exc.status_code == 404:
|
||||
return await super().get_response("index.html", scope)
|
||||
raise
|
||||
|
||||
|
||||
_web_dist = Path(settings.web_dist_dir) if settings.web_dist_dir else None
|
||||
if _web_dist is not None and (_web_dist / "index.html").is_file():
|
||||
app.mount("/", _SPAStaticFiles(directory=str(_web_dist), html=True), name="web")
|
||||
|
||||
Reference in New Issue
Block a user