- 新增完整的 Python 实现,替代 Go 版本 - 添加 Web 登录界面和仪表板 - 实现 JWT 认证和 API 密钥管理 - 添加数据库存储功能 - 保持与 Go 版本一致的目录结构和启动脚本 - 包含完整的文档和测试脚本
145 lines
3.8 KiB
Python
145 lines
3.8 KiB
Python
"""
|
|
简化版 FastAPI 应用主入口
|
|
用于快速启动和测试
|
|
"""
|
|
|
|
from fastapi import FastAPI, Request
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
from fastapi.responses import JSONResponse
|
|
import structlog
|
|
from datetime import datetime
|
|
|
|
from app.config import get_settings
|
|
from app.handlers.webhook import router as webhook_router
|
|
from app.handlers.health import router as health_router
|
|
from app.handlers.logs import router as logs_router
|
|
from app.handlers.admin import router as admin_router
|
|
|
|
# 配置日志
|
|
structlog.configure(
|
|
processors=[
|
|
structlog.stdlib.filter_by_level,
|
|
structlog.stdlib.add_logger_name,
|
|
structlog.stdlib.add_log_level,
|
|
structlog.stdlib.PositionalArgumentsFormatter(),
|
|
structlog.processors.TimeStamper(fmt="iso"),
|
|
structlog.processors.StackInfoRenderer(),
|
|
structlog.processors.format_exc_info,
|
|
structlog.processors.UnicodeDecoder(),
|
|
structlog.processors.JSONRenderer()
|
|
],
|
|
context_class=dict,
|
|
logger_factory=structlog.stdlib.LoggerFactory(),
|
|
wrapper_class=structlog.stdlib.BoundLogger,
|
|
cache_logger_on_first_use=True,
|
|
)
|
|
|
|
logger = structlog.get_logger()
|
|
|
|
# 创建 FastAPI 应用
|
|
app = FastAPI(
|
|
title="Gitea Webhook Ambassador",
|
|
description="高性能的 Gitea 到 Jenkins 的 Webhook 服务",
|
|
version="1.0.0"
|
|
)
|
|
|
|
# 添加 CORS 中间件
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=["*"],
|
|
allow_credentials=True,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
|
|
# 包含路由
|
|
app.include_router(webhook_router)
|
|
app.include_router(health_router)
|
|
app.include_router(logs_router)
|
|
app.include_router(admin_router)
|
|
|
|
@app.get("/")
|
|
async def root():
|
|
"""根路径"""
|
|
return {
|
|
"name": "Gitea Webhook Ambassador",
|
|
"version": "1.0.0",
|
|
"description": "高性能的 Gitea 到 Jenkins 的 Webhook 服务",
|
|
"endpoints": {
|
|
"webhook": "/webhook/gitea",
|
|
"health": "/health",
|
|
"metrics": "/metrics",
|
|
"logs": "/api/logs",
|
|
"admin": "/api/admin"
|
|
}
|
|
}
|
|
|
|
@app.middleware("http")
|
|
async def log_requests(request: Request, call_next):
|
|
"""请求日志中间件"""
|
|
start_time = datetime.utcnow()
|
|
|
|
# 记录请求
|
|
logger.info(
|
|
"Request started",
|
|
method=request.method,
|
|
url=str(request.url),
|
|
client_ip=request.client.host if request.client else None
|
|
)
|
|
|
|
# 处理请求
|
|
response = await call_next(request)
|
|
|
|
# 计算处理时间
|
|
process_time = (datetime.utcnow() - start_time).total_seconds()
|
|
|
|
# 记录响应
|
|
logger.info(
|
|
"Request completed",
|
|
method=request.method,
|
|
url=str(request.url),
|
|
status_code=response.status_code,
|
|
process_time=process_time
|
|
)
|
|
|
|
# 添加处理时间到响应头
|
|
response.headers["X-Process-Time"] = str(process_time)
|
|
|
|
return response
|
|
|
|
@app.exception_handler(Exception)
|
|
async def global_exception_handler(request: Request, exc: Exception):
|
|
"""全局异常处理器"""
|
|
logger.error(
|
|
"Unhandled exception",
|
|
method=request.method,
|
|
url=str(request.url),
|
|
error=str(exc),
|
|
exc_info=True
|
|
)
|
|
|
|
return JSONResponse(
|
|
status_code=500,
|
|
content={
|
|
"error": "Internal server error",
|
|
"message": "An unexpected error occurred"
|
|
}
|
|
)
|
|
|
|
if __name__ == "__main__":
|
|
import uvicorn
|
|
settings = get_settings()
|
|
|
|
logger.info(
|
|
"Starting Gitea Webhook Ambassador",
|
|
host=settings.server.host,
|
|
port=settings.server.port,
|
|
version=settings.version
|
|
)
|
|
|
|
uvicorn.run(
|
|
"app.main_simple:app",
|
|
host=settings.server.host,
|
|
port=settings.server.port,
|
|
reload=settings.server.reload
|
|
) |