# app/main.py import threading import time from contextlib import asynccontextmanager from fastapi import FastAPI, Request, Response from fastapi.middleware.cors import CORSMiddleware import uvicorn import app.services.crawler as crawler import tg_bot as tg_bot from app.api.v1 import daily_news, web_tools, analysis from app.utils.logger import log from app.core import db, cache from app.core.config import get_app_config, get_config from app.services.browser_manager import BrowserManager # 获取应用配置 app_config = get_app_config() # 应用启动和关闭的生命周期管理 @asynccontextmanager async def lifespan(app: FastAPI): # 启动时执行 log.info("Application startup") # 初始化数据库连接 db.init_db() # 初始化缓存 cache.init_cache() # 异步启动爬虫,避免阻塞应用启动 threading.Thread(target=crawler.crawlers_logic, daemon=True).start() yield # 关闭时执行 log.info("Application shutdown") # 关闭浏览器管理器 try: BrowserManager().shutdown() log.info("Browser manager shutdown") except Exception as e: log.error(f"Error shutting down browser manager: {e}") # 关闭数据库连接 db.close_db() # 关闭缓存连接 cache.close_cache() # 创建应用实例 app = FastAPI( title=app_config.title, description=app_config.description, version=app_config.version, lifespan=lifespan, # Swagger/OpenAPI 配置 docs_url="/docs", # Swagger UI 路径 redoc_url="/redoc", # ReDoc 路径 openapi_url="/openapi.json", # OpenAPI schema 路径 openapi_tags=[ { "name": "Daily News", "description": "每日热点新闻数据接口,支持 22+ 个平台(百度、微博、知乎、GitHub 等)" }, { "name": "Website Meta", "description": "网站元数据提取工具,可获取指定 URL 的标题、描述、图标等信息" }, { "name": "Analysis", "description": "新闻趋势分析和预测功能" }, { "name": "Health", "description": "健康检查接口" } ], openapi_extra={ "externalDocs": { "description": "项目源码仓库", "url": "https://github.com/hot-news/hot_news-main" } } ) # 添加CORS中间件 app.add_middleware( CORSMiddleware, allow_origins=app_config.cors["allow_origins"], allow_credentials=app_config.cors["allow_credentials"], allow_methods=app_config.cors["allow_methods"], allow_headers=app_config.cors["allow_headers"], ) # 请求计时中间件 @app.middleware("http") async def add_process_time_header(request: Request, call_next): start_time = time.time() response = await call_next(request) process_time = time.time() - start_time response.headers["X-Process-Time"] = str(process_time) return response # 注册路由 app.include_router(daily_news.router, prefix="/api/v1/dailynews", tags=["Daily News"]) app.include_router(web_tools.router, prefix="/api/v1/tools/website-meta", tags=["Website Meta"]) app.include_router(analysis.router, prefix="/api/v1/analysis", tags=["Analysis"]) # 健康检查端点 @app.get( "/health", summary="健康检查", description="检查 API 服务运行状态,返回服务状态和版本号", response_description="返回服务健康状态信息", responses={ 200: { "description": "服务正常运行", "content": { "application/json": { "example": { "status": "healthy", "version": "1.0.0" } } } } }, tags=["Health"] ) async def health_check(): """ **健康检查接口** 用于监控服务运行状态,可用于: - 负载均衡器健康检查 - 容器编排平台存活探测 - 监控系统状态检测 **返回字段:** - `status`: 服务状态(healthy/unhealthy) - `version`: 当前服务版本 """ return {"status": "healthy", "version": app_config.version} # 如果直接运行此文件 if __name__ == "__main__": uvicorn.run("app.main:app", host=app_config.host, port=app_config.port, reload=app_config.debug)