fix: add API key auth, rate limiting, and safe error messages

This commit is contained in:
2026-07-05 01:33:02 +08:00
parent 2ef0cf4a4e
commit 157155c0d2
2 changed files with 66 additions and 6 deletions
+19 -6
View File
@@ -1,8 +1,10 @@
"""FastAPI 服务层."""
import os
import logging
from pathlib import Path
from fastapi import FastAPI, HTTPException
from fastapi import FastAPI, HTTPException, Depends, Request
from fastapi.responses import RedirectResponse
from pydantic import BaseModel
from src.core.config import load_config, EmbedConfig, DEFAULT_CONFIG_PATH
@@ -10,6 +12,9 @@ from src.core.db import VectorDB
from src.core.embedder import create_embedder
from src.core.ingest import DocumentIngestor
from src.core.search import Searcher
from src.server.auth import verify_api_key, rate_limiter
logger = logging.getLogger("md-vector-db")
def _is_safe_path(path_str: str) -> bool:
@@ -94,6 +99,13 @@ app = FastAPI(
)
@app.middleware("http")
async def rate_limit_middleware(request: Request, call_next):
await rate_limiter(request)
response = await call_next(request)
return response
@app.get("/")
def root():
"""根路径重定向到 API 文档."""
@@ -115,7 +127,7 @@ def list_collections():
@app.post("/api/v1/ingest")
def ingest_document(req: IngestRequest):
def ingest_document(req: IngestRequest, _: bool = Depends(verify_api_key)):
ingestor = _get_ingestor()
try:
if req.file_path:
@@ -136,19 +148,20 @@ def ingest_document(req: IngestRequest):
return {"status": "ok", "chunks": count, "file": file_name}
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
except Exception:
logger.exception("入库失败")
raise HTTPException(status_code=500, detail="服务器内部错误")
@app.post("/api/v1/search")
def search_documents(req: SearchRequest):
def search_documents(req: SearchRequest, _: bool = Depends(verify_api_key)):
searcher = _get_searcher()
results = searcher.search(req.query, top_k=req.top_k)
return {"results": results}
@app.delete("/api/v1/documents/{file_name}")
def delete_document(file_name: str):
def delete_document(file_name: str, _: bool = Depends(verify_api_key)):
searcher = _get_searcher()
deleted = searcher.delete_by_source(file_name)
if not deleted: