Files
findreve/app.py
2026-01-12 11:44:55 +08:00

83 lines
2.5 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from fastapi import FastAPI
from fastapi.responses import FileResponse
from fastapi import Request
from contextlib import asynccontextmanager
from slowapi import Limiter, _rate_limit_exceeded_handler
from slowapi.util import get_remote_address
from slowapi.errors import RateLimitExceeded
from pkg.utils import raise_internal_error
from routes import (session, admin, object, ota)
from model.database import Database
import os
import pkg.conf
from pkg import utils
from loguru import logger
Router = [admin, session, object, ota]
# Findreve 的生命周期
@asynccontextmanager
async def lifespan(app: FastAPI):
await Database().init_db()
yield
# 定义 Findreve 服务器
app = FastAPI(
title=pkg.conf.APP_NAME,
version=pkg.conf.VERSION,
summary=pkg.conf.summary,
description=pkg.conf.description,
lifespan=lifespan
)
@app.exception_handler(Exception)
async def handle_unexpected_exceptions(request: Request, exc: Exception):
"""
捕获所有未经处理的异常,防止敏感信息泄露。
"""
# 1. 为开发人员记录详细的、包含完整堆栈跟踪的错误日志
logger.exception(
f"An unhandled exception occurred for request: {request.method} {request.url.path}"
)
raise_internal_error()
# 挂载后端路由
for router in Router:
app.include_router(router.Router)
# 挂载Slowapi限流中间件
limiter = Limiter(key_func=get_remote_address)
app.state.limiter = limiter
app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)
@app.get("/")
async def frontend_index():
if not os.path.exists("dist/index.html"):
utils.raise_not_found("Index not found")
return FileResponse("dist/index.html")
# 回退路由
@app.get("/{path:path}")
async def frontend_path(path: str):
if not os.path.exists("dist/index.html"):
utils.raise_not_found("Index not found, please build frontend first.")
# 排除API路由
if path.startswith("api/"):
utils.raise_not_found("API route not found")
# 检查是否是静态资源请求
if path.startswith("assets/") and os.path.exists(f"dist/{path}"):
return FileResponse(f"dist/{path}")
# 检查文件是否存在于dist目录
dist_file_path = os.path.join("dist", path)
if os.path.exists(dist_file_path) and not os.path.isdir(dist_file_path):
return FileResponse(dist_file_path)
# 对于所有其他前端路由返回index.html让Vue Router处理
return FileResponse("dist/index.html")