94 lines
2.5 KiB
Python
94 lines
2.5 KiB
Python
from fastapi import FastAPI, Request, Response
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
from fastapi.responses import JSONResponse
|
|
import time
|
|
import json
|
|
|
|
from app.core.config import settings
|
|
from app.core.database import engine, Base
|
|
from app.core.events import init_minio_bucket
|
|
from app.api.v1 import api_router
|
|
from app.models import log as log_models
|
|
|
|
# Create tables (dev convenience; use Alembic in production)
|
|
Base.metadata.create_all(bind=engine)
|
|
|
|
app = FastAPI(
|
|
title=settings.PROJECT_NAME,
|
|
version=settings.VERSION,
|
|
description=settings.DESCRIPTION,
|
|
)
|
|
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=settings.CORS_ORIGINS,
|
|
allow_credentials=True,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
|
|
|
|
@app.middleware("http")
|
|
async def log_requests(request: Request, call_next):
|
|
start_time = time.time()
|
|
response = await call_next(request)
|
|
duration = int((time.time() - start_time) * 1000)
|
|
|
|
# Skip health checks
|
|
if request.url.path in ["/docs", "/openapi.json", "/redoc"]:
|
|
return response
|
|
|
|
from app.core.database import SessionLocal
|
|
try:
|
|
db = SessionLocal()
|
|
body_bytes = b""
|
|
if request.method in ["POST", "PUT", "PATCH"]:
|
|
try:
|
|
body_bytes = await request.body()
|
|
# Re-assign body for downstream
|
|
async def receive():
|
|
return {"type": "http.request", "body": body_bytes}
|
|
request._receive = receive
|
|
except Exception:
|
|
pass
|
|
|
|
log_entry = log_models.OperationLog(
|
|
module=request.url.path.split("/")[2] if len(request.url.path.split("/")) > 2 else "",
|
|
action=request.url.path,
|
|
method=request.method,
|
|
path=str(request.url),
|
|
ip=request.client.host if request.client else None,
|
|
status_code=response.status_code,
|
|
duration_ms=duration,
|
|
)
|
|
db.add(log_entry)
|
|
db.commit()
|
|
except Exception:
|
|
pass
|
|
finally:
|
|
db.close()
|
|
|
|
return response
|
|
|
|
|
|
@app.on_event("startup")
|
|
async def startup_event():
|
|
init_minio_bucket()
|
|
from app.core.database import SessionLocal
|
|
from app.services.user_service import create_initial_data
|
|
from app.services.classification_service import init_builtin_data
|
|
db = SessionLocal()
|
|
try:
|
|
create_initial_data(db)
|
|
init_builtin_data(db)
|
|
finally:
|
|
db.close()
|
|
|
|
|
|
@app.get("/health")
|
|
def health_check():
|
|
return {"status": "ok"}
|
|
|
|
|
|
app.include_router(api_router, prefix="/api/v1")
|