main.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. import time
  2. import traceback
  3. from fastapi import FastAPI
  4. from .api import vector, raster, cd_prediction, unit_grouping, water, agricultural_input, cd_flux_removal, cd_flux
  5. from .database import engine, Base
  6. from fastapi.middleware.cors import CORSMiddleware
  7. import logging
  8. import sys
  9. import os
  10. from fastapi import FastAPI, HTTPException, Request, status
  11. from fastapi.responses import JSONResponse
  12. from app.log.logger import get_logger, ExceptionLogger, setup_logging # 导入日志模块
  13. from app.log import error
  14. # 配置日志
  15. from app.log.logger import get_logger
  16. logger = get_logger(__name__)
  17. def safe_create_tables():
  18. """
  19. 安全地创建数据库表
  20. @description: 直接创建表结构,跳过迁移检查
  21. """
  22. try:
  23. # 直接创建数据库表
  24. Base.metadata.create_all(bind=engine)
  25. logger.info("数据库表结构创建完成")
  26. except Exception as e:
  27. logger.error(f"数据库表创建失败: {str(e)}")
  28. logger.error("请检查数据库连接和表结构定义")
  29. # 不要退出,继续运行应用
  30. # sys.exit(1) # 注释掉这行,避免应用退出
  31. # 执行数据库初始化
  32. safe_create_tables()
  33. app = FastAPI(
  34. title="地图数据处理系统",
  35. description="一个用于处理地图数据的API系统",
  36. version="1.0.0",
  37. openapi_tags=[
  38. # ...(保持原有标签定义不变)
  39. ]
  40. )
  41. # ---------------------------
  42. # 添加 CORS 配置(关键修改)
  43. # ---------------------------
  44. app.add_middleware(
  45. CORSMiddleware,
  46. allow_origins=["https://soilgd.com", "http://localhost:5173", "https://www.soilgd.com"],
  47. allow_methods=["*"],
  48. allow_headers=["*"],
  49. allow_credentials=True,
  50. )
  51. # 注册路由(保持原有路由注册不变)
  52. app.include_router(vector.router, prefix="/api/vector", tags=["vector"])
  53. app.include_router(raster.router, prefix="/api/raster", tags=["raster"])
  54. app.include_router(cd_prediction.router, prefix="/api/cd-prediction", tags=["cd-prediction"])
  55. app.include_router(unit_grouping.router, prefix="/api/unit-grouping", tags=["unit-grouping"])
  56. app.include_router(water.router, prefix="/api/water", tags=["water"])
  57. app.include_router(agricultural_input.router, prefix="/api/agricultural-input", tags=["agricultural-input"])
  58. app.include_router(cd_flux_removal.router, prefix="/api/cd-flux-removal", tags=["cd-flux-removal"])
  59. app.include_router(cd_flux.router, prefix="/api/cd-flux", tags=["cd-flux"])
  60. app.include_router(error.router, prefix="/api/errors", tags=["errors"])
  61. @app.get("/")
  62. async def root():
  63. return {"message": "Welcome to the GIS Data Management API"}
  64. # 可选:添加健康检查端点
  65. @app.get("/health")
  66. async def health_check():
  67. return {"status": "healthy", "database": "connected"}
  68. # 全局异常处理器
  69. @app.exception_handler(Exception)
  70. async def global_exception_handler(request: Request, exc: Exception):
  71. """全局异常处理器"""
  72. # 生成唯一错误ID
  73. error_id = f"ERR-{int(time.time() * 1000)}"
  74. # 获取完整的堆栈跟踪
  75. tb_str = traceback.format_exc()
  76. # 记录完整错误信息(包含堆栈跟踪)
  77. logger.error(f"ErrorID: {error_id} - {str(exc)}\n{tb_str}")
  78. return JSONResponse(
  79. status_code=500,
  80. content={
  81. "code": error_id,
  82. "message": "Internal server error",
  83. "documentation": f"/api/errors/{error_id}"
  84. }
  85. )
  86. # 自定义HTTP异常处理
  87. @app.exception_handler(HTTPException)
  88. async def http_exception_handler(request: Request, exc: HTTPException):
  89. """HTTP异常处理器"""
  90. # 生成错误ID
  91. error_id = f"HTTP-{exc.status_code}-{int(time.time() * 1000)}"
  92. # 记录到错误日志
  93. logger.error(f"ErrorID: {error_id} - HTTP {exc.status_code}: {exc.detail}")
  94. return JSONResponse(
  95. status_code=exc.status_code,
  96. content={
  97. "code": error_id,
  98. "message": exc.detail,
  99. "documentation": f"/api/errors/{error_id}"
  100. }
  101. )