Files
rssKeeper/backend/main.py
T
congsh 4286731348 feat: 代理支持、外部API增强、调度器修复、每日文章看板
- 添加 HTTP 代理支持(国内直连、外网走代理)
- 外部 API 新增全文搜索、源健康度/错误筛选、未读筛选
- 修复 APScheduler 线程静默崩溃(_safe_fetch 异常保护)
- 健康检查暴露调度器状态
- Dashboard 新增每日文章数柱状图(按 published_at)
- 文章列表 API 补上 content 字段,日期筛选修复时间范围
- 修复外部 API 双重 external 前缀
- User-Agent 改为 Chrome 标识缓解 403
- 添加完整 API 接口文档

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-12 09:58:32 +08:00

68 lines
1.9 KiB
Python

"""rssKeeper - FastAPI 入口"""
import os
from contextlib import asynccontextmanager
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
from starlette.middleware.cors import CORSMiddleware
from database import init_db, SessionLocal
from scheduler import init_feed_jobs, stop_scheduler, scheduler_status
from routers import feeds, articles, dashboard, external_api
import config
@asynccontextmanager
async def lifespan(app: FastAPI):
"""应用生命周期管理"""
# 启动时:初始化数据库 + 注册定时任务
init_db()
db = SessionLocal()
try:
init_feed_jobs(db)
finally:
db.close()
yield
# 关闭时:停止调度器
stop_scheduler()
app = FastAPI(
title="rssKeeper",
description="RSS 抓取、管理与检索系统",
version="1.0.0",
lifespan=lifespan,
)
# CORS — 仅允许同源和开发环境
app.add_middleware(
CORSMiddleware,
allow_origins=[
"http://localhost:7329",
"http://localhost:7330",
"http://127.0.0.1:7329",
],
allow_credentials=False,
allow_methods=["GET", "POST", "PUT", "DELETE"],
allow_headers=["Content-Type", "Authorization", "X-API-Key"],
)
# API 路由
app.include_router(feeds.router, prefix=config.API_PREFIX)
app.include_router(articles.router, prefix=config.API_PREFIX)
app.include_router(dashboard.router, prefix=config.API_PREFIX)
app.include_router(external_api.router, prefix=config.EXTERNAL_API_PREFIX)
@app.get("/api/health")
def health_check():
"""健康检查"""
sched = scheduler_status()
return {"status": "ok", "service": "rssKeeper", "scheduler": sched}
# 静态文件服务(前端构建产物)— 必须放在最后,API 路由优先匹配
static_dir = os.path.join(config.BASE_DIR, "static")
if os.path.exists(static_dir):
app.mount("/", StaticFiles(directory=static_dir, html=True), name="static")