main.py 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. from contextlib import asynccontextmanager
  2. import logging
  3. from pathlib import Path
  4. from fastapi import FastAPI, Request
  5. from fastapi.middleware.cors import CORSMiddleware
  6. from fastapi.responses import JSONResponse
  7. from fastapi.staticfiles import StaticFiles
  8. from app.core.config import get_settings
  9. from app.api import chat, drug, auth, admin
  10. from app.api import admin_knowledge
  11. from app.api.exam import chapter, practice, exam_qa, progress
  12. settings = get_settings()
  13. logging.basicConfig(
  14. level=settings.log_level,
  15. format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
  16. handlers=[
  17. logging.FileHandler(settings.log_file),
  18. logging.StreamHandler(),
  19. ],
  20. )
  21. logger = logging.getLogger(__name__)
  22. @asynccontextmanager
  23. async def lifespan(app: FastAPI):
  24. logger.info(f"Starting {settings.app_name} in {settings.app_env} mode")
  25. yield
  26. logger.info(f"Shutting down {settings.app_name}")
  27. app = FastAPI(
  28. title=settings.app_name,
  29. version="1.0.0",
  30. lifespan=lifespan,
  31. )
  32. app.add_middleware(
  33. CORSMiddleware,
  34. allow_origins=["*"],
  35. allow_credentials=True,
  36. allow_methods=["*"],
  37. allow_headers=["*"],
  38. )
  39. app.include_router(chat.router, prefix=settings.api_prefix)
  40. app.include_router(drug.router, prefix=settings.api_prefix)
  41. app.include_router(auth.router, prefix=settings.api_prefix)
  42. app.include_router(admin.router, prefix=settings.api_prefix)
  43. app.include_router(admin_knowledge.router, prefix=settings.api_prefix)
  44. app.include_router(chapter.router, prefix=settings.api_prefix)
  45. app.include_router(practice.router, prefix=settings.api_prefix)
  46. app.include_router(exam_qa.router, prefix=settings.api_prefix)
  47. app.include_router(progress.router, prefix=settings.api_prefix)
  48. # 静态文件
  49. static_dir = Path(__file__).resolve().parent.parent.parent / "static"
  50. static_dir.mkdir(parents=True, exist_ok=True)
  51. app.mount("/static", StaticFiles(directory=str(static_dir), html=True), name="static")
  52. @app.get("/")
  53. async def root():
  54. from fastapi.responses import FileResponse
  55. return FileResponse(static_dir / "index.html")
  56. @app.get("/health")
  57. async def health_check():
  58. return {"status": "ok", "app": settings.app_name, "env": settings.app_env}
  59. @app.exception_handler(Exception)
  60. async def global_exception_handler(request: Request, exc: Exception):
  61. logger.error(f"Unhandled exception: {exc}", exc_info=True)
  62. return JSONResponse(
  63. status_code=500,
  64. content={"detail": "Internal server error"},
  65. )