817 lines
25 KiB
Python
817 lines
25 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
|
|
"""
|
|
API 文档生成器
|
|
自动生成 OpenAPI/Swagger 格式的 API 文档
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import json
|
|
import inspect
|
|
from datetime import datetime
|
|
from typing import Dict, List, Any, Optional
|
|
from dataclasses import dataclass, field
|
|
|
|
|
|
@dataclass
|
|
class APIDoc:
|
|
"""API 文档信息"""
|
|
title: str = "HYC下载站 API"
|
|
version: str = "2.2.0"
|
|
description: str = "HYC镜像下载站 REST API 文档"
|
|
servers: List[Dict] = field(default_factory=list)
|
|
tags: List[Dict] = field(default_factory=list)
|
|
paths: Dict = field(default_factory=dict)
|
|
components: Dict = field(default_factory=dict)
|
|
|
|
|
|
class APIDocGenerator:
|
|
"""API 文档生成器"""
|
|
|
|
def __init__(self, config: Dict = None):
|
|
self.config = config or {}
|
|
self.api_doc = APIDoc()
|
|
|
|
# 初始化组件
|
|
self._init_components()
|
|
|
|
def _init_components(self):
|
|
"""初始化文档组件"""
|
|
self.api_doc.components = {
|
|
'securitySchemes': {
|
|
'BearerAuth': {
|
|
'type': 'http',
|
|
'scheme': 'bearer',
|
|
'bearerFormat': 'JWT',
|
|
'description': 'JWT token 认证'
|
|
},
|
|
'ApiKeyAuth': {
|
|
'type': 'apiKey',
|
|
'in': 'header',
|
|
'name': 'X-API-Key',
|
|
'description': 'API Key 认证'
|
|
}
|
|
},
|
|
'schemas': {
|
|
'Error': {
|
|
'type': 'object',
|
|
'properties': {
|
|
'error': {'type': 'string', 'description': '错误信息'},
|
|
'code': {'type': 'string', 'description': '错误代码'},
|
|
'message': {'type': 'string', 'description': '详细描述'}
|
|
}
|
|
},
|
|
'Success': {
|
|
'type': 'object',
|
|
'properties': {
|
|
'success': {'type': 'boolean'},
|
|
'message': {'type': 'string'},
|
|
'data': {'type': 'object'}
|
|
}
|
|
},
|
|
'HealthStatus': {
|
|
'type': 'object',
|
|
'properties': {
|
|
'status': {'type': 'string', 'enum': ['healthy', 'degraded', 'unhealthy']},
|
|
'components': {'type': 'object'},
|
|
'timestamp': {'type': 'string', 'format': 'date-time'}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
def generate(self) -> Dict:
|
|
"""生成完整的 API 文档"""
|
|
doc = {
|
|
'openapi': '3.0.3',
|
|
'info': {
|
|
'title': self.api_doc.title,
|
|
'version': self.api_doc.version,
|
|
'description': self.api_doc.description,
|
|
'contact': {
|
|
'name': 'HYC Mirror Support',
|
|
'email': '[email protected]'
|
|
},
|
|
'license': {
|
|
'name': 'MIT',
|
|
'url': 'https://opensource.org/licenses/MIT'
|
|
}
|
|
},
|
|
'servers': self.api_doc.servers,
|
|
'tags': self.api_doc.tags,
|
|
'paths': self.api_doc.paths,
|
|
'components': self.api_doc.components
|
|
}
|
|
|
|
return doc
|
|
|
|
def add_server(self, url: str, description: str = ''):
|
|
"""添加服务器"""
|
|
self.api_doc.servers.append({
|
|
'url': url,
|
|
'description': description
|
|
})
|
|
|
|
def add_tag(self, name: str, description: str = ''):
|
|
"""添加标签"""
|
|
self.api_doc.tags.append({
|
|
'name': name,
|
|
'description': description
|
|
})
|
|
|
|
def add_endpoint(
|
|
self,
|
|
method: str,
|
|
path: str,
|
|
summary: str,
|
|
description: str = '',
|
|
tags: List[str] = None,
|
|
parameters: List[Dict] = None,
|
|
requestBody: Dict = None,
|
|
responses: Dict = None,
|
|
security: List[Dict] = None,
|
|
deprecated: bool = False
|
|
):
|
|
"""
|
|
添加 API 端点
|
|
|
|
Args:
|
|
method: HTTP 方法 (GET, POST, PUT, DELETE, PATCH)
|
|
path: API 路径
|
|
summary: 简要描述
|
|
description: 详细描述
|
|
tags: 标签列表
|
|
parameters: 参数列表
|
|
requestBody: 请求体
|
|
responses: 响应定义
|
|
security: 安全要求
|
|
deprecated: 是否废弃
|
|
"""
|
|
if parameters is None:
|
|
parameters = []
|
|
if responses is None:
|
|
responses = self._default_responses()
|
|
if security is None:
|
|
security = []
|
|
|
|
# 转换路径参数
|
|
path_params = self._extract_path_params(path)
|
|
for param in path_params:
|
|
parameters.append({
|
|
'name': param,
|
|
'in': 'path',
|
|
'required': True,
|
|
'schema': {'type': 'string'},
|
|
'description': f'Path parameter: {param}'
|
|
})
|
|
|
|
# 转换查询参数
|
|
query_params = self._extract_query_params(path)
|
|
for param in query_params:
|
|
parameters.append({
|
|
'name': param,
|
|
'in': 'query',
|
|
'required': False,
|
|
'schema': {'type': 'string'},
|
|
'description': f'Query parameter: {param}'
|
|
})
|
|
|
|
# 构建路径
|
|
clean_path = path.format(**{p: f'{{{p}}}' for p in path_params})
|
|
if clean_path not in self.api_doc.paths:
|
|
self.api_doc.paths[clean_path] = {}
|
|
|
|
endpoint = {
|
|
'summary': summary,
|
|
'description': description,
|
|
'tags': tags or [],
|
|
'parameters': parameters,
|
|
'responses': responses,
|
|
'deprecated': deprecated
|
|
}
|
|
|
|
if security:
|
|
endpoint['security'] = security
|
|
|
|
if requestBody:
|
|
endpoint['requestBody'] = requestBody
|
|
|
|
self.api_doc.paths[clean_path][method.lower()] = endpoint
|
|
|
|
def _default_responses(self) -> Dict:
|
|
"""获取默认响应"""
|
|
return {
|
|
'200': {
|
|
'description': 'Successful response',
|
|
'content': {
|
|
'application/json': {
|
|
'schema': {'type': 'object'}
|
|
}
|
|
}
|
|
},
|
|
'400': {
|
|
'description': 'Bad request',
|
|
'content': {
|
|
'application/json': {
|
|
'schema': {'$ref': '#/components/schemas/Error'}
|
|
}
|
|
}
|
|
},
|
|
'401': {
|
|
'description': 'Unauthorized',
|
|
'content': {
|
|
'application/json': {
|
|
'schema': {'$ref': '#/components/schemas/Error'}
|
|
}
|
|
}
|
|
},
|
|
'403': {
|
|
'description': 'Forbidden',
|
|
'content': {
|
|
'application/json': {
|
|
'schema': {'$ref': '#/components/schemas/Error'}
|
|
}
|
|
}
|
|
},
|
|
'404': {
|
|
'description': 'Not found',
|
|
'content': {
|
|
'application/json': {
|
|
'schema': {'$ref': '#/components/schemas/Error'}
|
|
}
|
|
}
|
|
},
|
|
'500': {
|
|
'description': 'Internal server error',
|
|
'content': {
|
|
'application/json': {
|
|
'schema': {'$ref': '#/components/schemas/Error'}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
def _extract_path_params(self, path: str) -> List[str]:
|
|
"""提取路径参数"""
|
|
import re
|
|
return re.findall(r'\{(\w+)\}', path)
|
|
|
|
def _extract_query_params(self, path: str) -> List[str]:
|
|
"""提取查询参数"""
|
|
import re
|
|
return re.findall(r':(\w+)', path)
|
|
|
|
def save(self, filepath: str, format: str = 'json'):
|
|
"""
|
|
保存 API 文档
|
|
|
|
Args:
|
|
filepath: 保存路径
|
|
format: 格式 (json, yaml)
|
|
"""
|
|
doc = self.generate()
|
|
|
|
if format == 'yaml':
|
|
try:
|
|
import yaml
|
|
with open(filepath, 'w', encoding='utf-8') as f:
|
|
yaml.dump(doc, f, default_flow_style=False, allow_unicode=True)
|
|
except ImportError:
|
|
# 回退为 JSON
|
|
format = 'json'
|
|
|
|
if format == 'json':
|
|
with open(filepath, 'w', encoding='utf-8') as f:
|
|
json.dump(doc, f, ensure_ascii=False, indent=2)
|
|
|
|
return filepath
|
|
|
|
|
|
class APIEndpointRegistry:
|
|
"""API 端点注册表"""
|
|
|
|
def __init__(self):
|
|
self.endpoints: List[Dict] = []
|
|
|
|
def register(self, method: str, path: str, handler_name: str, description: str = ''):
|
|
"""注册端点"""
|
|
self.endpoints.append({
|
|
'method': method.upper(),
|
|
'path': path,
|
|
'handler': handler_name,
|
|
'description': description
|
|
})
|
|
|
|
def get_all(self) -> List[Dict]:
|
|
"""获取所有端点"""
|
|
return self.endpoints
|
|
|
|
def generate_docs(self) -> Dict:
|
|
"""生成文档"""
|
|
generator = APIDocGenerator()
|
|
|
|
for ep in self.endpoints:
|
|
generator.add_endpoint(
|
|
method=ep['method'],
|
|
path=ep['path'],
|
|
summary=ep['description'],
|
|
description=ep['description']
|
|
)
|
|
|
|
return generator.generate()
|
|
|
|
|
|
def generate_api_docs(config: Dict = None) -> Dict:
|
|
"""
|
|
生成完整的 API 文档
|
|
|
|
Args:
|
|
config: 服务器配置
|
|
|
|
Returns:
|
|
OpenAPI 格式的文档
|
|
"""
|
|
generator = APIDocGenerator(config)
|
|
|
|
# 设置服务器信息
|
|
host = config.get('host', 'localhost')
|
|
port = config.get('port', 8080)
|
|
protocol = 'https' if config.get('ssl_cert') else 'http'
|
|
generator.add_server(f'{protocol}://{host}:{port}', 'Production server')
|
|
|
|
# 添加标签
|
|
generator.add_tag('Server', '服务器信息')
|
|
generator.add_tag('Monitoring', '监控与指标')
|
|
generator.add_tag('Mirrors', '镜像源管理')
|
|
generator.add_tag('Sync', '同步管理')
|
|
generator.add_tag('Cache', '缓存管理')
|
|
generator.add_tag('Health', '健康检查')
|
|
generator.add_tag('Alerts', '告警管理')
|
|
generator.add_tag('Webhooks', 'Webhook管理')
|
|
generator.add_tag('Configuration', '配置管理')
|
|
generator.add_tag('Authentication', '认证管理')
|
|
|
|
# ========== 服务器信息端点 ==========
|
|
generator.add_endpoint(
|
|
'GET', '/api/v2/server/info',
|
|
summary='获取服务器信息',
|
|
description='返回服务器的详细信息,包括版本、运行时间、配置等',
|
|
tags=['Server']
|
|
)
|
|
|
|
# ========== 监控端点 ==========
|
|
generator.add_endpoint(
|
|
'GET', '/api/v2/monitor/realtime',
|
|
summary='获取实时监控数据',
|
|
description='返回服务器的实时监控数据,包括 CPU、内存、磁盘使用情况',
|
|
tags=['Monitoring']
|
|
)
|
|
|
|
generator.add_endpoint(
|
|
'GET', '/api/v2/monitor/history',
|
|
summary='获取历史监控数据',
|
|
description='返回指定时间段内的历史监控数据',
|
|
tags=['Monitoring'],
|
|
parameters=[{
|
|
'name': 'period',
|
|
'in': 'query',
|
|
'schema': {'type': 'string'},
|
|
'description': '时间周期: 1h, 6h, 24h, 7d, 30d'
|
|
}]
|
|
)
|
|
|
|
generator.add_endpoint(
|
|
'GET', '/api/v2/metrics',
|
|
summary='获取 Prometheus 指标',
|
|
description='返回 Prometheus 格式的监控指标',
|
|
tags=['Monitoring']
|
|
)
|
|
|
|
# ========== 镜像源端点 ==========
|
|
generator.add_endpoint(
|
|
'GET', '/api/v2/mirrors',
|
|
summary='列出所有镜像加速源',
|
|
description='返回所有可用的镜像加速源列表',
|
|
tags=['Mirrors']
|
|
)
|
|
|
|
generator.add_endpoint(
|
|
'GET', '/api/v2/mirrors/:name',
|
|
summary='获取镜像源详情',
|
|
description='返回指定镜像源的详细信息',
|
|
tags=['Mirrors']
|
|
)
|
|
|
|
generator.add_endpoint(
|
|
'POST', '/api/v2/mirrors',
|
|
summary='添加自定义镜像源',
|
|
description='添加新的自定义镜像加速源',
|
|
tags=['Mirrors'],
|
|
requestBody={
|
|
'required': True,
|
|
'content': {
|
|
'application/json': {
|
|
'schema': {
|
|
'type': 'object',
|
|
'properties': {
|
|
'name': {'type': 'string'},
|
|
'type': {'type': 'string'},
|
|
'url': {'type': 'string'},
|
|
'enabled': {'type': 'boolean'}
|
|
},
|
|
'required': ['name', 'url']
|
|
}
|
|
}
|
|
}
|
|
}
|
|
)
|
|
|
|
generator.add_endpoint(
|
|
'DELETE', '/api/v2/mirrors/:name',
|
|
summary='删除自定义镜像源',
|
|
description='删除指定的自定义镜像加速源',
|
|
tags=['Mirrors']
|
|
)
|
|
|
|
generator.add_endpoint(
|
|
'POST', '/api/v2/mirrors/:name/refresh',
|
|
summary='刷新镜像源缓存',
|
|
description='刷新指定镜像源的缓存数据',
|
|
tags=['Mirrors']
|
|
)
|
|
|
|
# ========== 同步管理端点 ==========
|
|
generator.add_endpoint(
|
|
'GET', '/api/v2/sync/sources',
|
|
summary='获取同步源列表',
|
|
description='返回所有配置的同步源',
|
|
tags=['Sync']
|
|
)
|
|
|
|
generator.add_endpoint(
|
|
'POST', '/api/v2/sync/sources',
|
|
summary='添加同步源',
|
|
description='添加新的同步源配置',
|
|
tags=['Sync'],
|
|
requestBody={
|
|
'required': True,
|
|
'content': {
|
|
'application/json': {
|
|
'schema': {
|
|
'type': 'object',
|
|
'properties': {
|
|
'name': {'type': 'string'},
|
|
'type': {'type': 'string'},
|
|
'url': {'type': 'string'},
|
|
'schedule': {'type': 'string'}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
)
|
|
|
|
generator.add_endpoint(
|
|
'POST', '/api/v2/sync/:source_name/start',
|
|
summary='启动同步任务',
|
|
description='启动指定源的同步任务',
|
|
tags=['Sync']
|
|
)
|
|
|
|
generator.add_endpoint(
|
|
'POST', '/api/v2/sync/:source_name/stop',
|
|
summary='停止同步任务',
|
|
description='停止指定源的同步任务',
|
|
tags=['Sync']
|
|
)
|
|
|
|
generator.add_endpoint(
|
|
'GET', '/api/v2/sync/:source_name/status',
|
|
summary='获取同步状态',
|
|
description='返回指定同步源的当前状态',
|
|
tags=['Sync']
|
|
)
|
|
|
|
# ========== 缓存管理端点 ==========
|
|
generator.add_endpoint(
|
|
'GET', '/api/v2/cache/stats',
|
|
summary='获取缓存统计',
|
|
description='返回缓存的使用统计信息',
|
|
tags=['Cache']
|
|
)
|
|
|
|
generator.add_endpoint(
|
|
'GET', '/api/v2/cache/usage',
|
|
summary='获取缓存使用详情',
|
|
description='返回缓存的详细使用情况',
|
|
tags=['Cache']
|
|
)
|
|
|
|
generator.add_endpoint(
|
|
'POST', '/api/v2/cache/clean',
|
|
summary='清理缓存',
|
|
description='清理指定或全部缓存',
|
|
tags=['Cache'],
|
|
requestBody={
|
|
'content': {
|
|
'application/json': {
|
|
'schema': {
|
|
'type': 'object',
|
|
'properties': {
|
|
'source': {'type': 'string'}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
)
|
|
|
|
# ========== 缓存预热端点 ==========
|
|
generator.add_endpoint(
|
|
'GET', '/api/v2/cache/prewarm',
|
|
summary='获取预热状态',
|
|
description='返回缓存预热的当前状态',
|
|
tags=['Cache']
|
|
)
|
|
|
|
generator.add_endpoint(
|
|
'POST', '/api/v2/cache/prewarm',
|
|
summary='执行缓存预热',
|
|
description='手动执行缓存预热任务',
|
|
tags=['Cache']
|
|
)
|
|
|
|
generator.add_endpoint(
|
|
'GET', '/api/v2/cache/prewarm/items',
|
|
summary='获取预热项目列表',
|
|
description='返回待预热的项目列表',
|
|
tags=['Cache']
|
|
)
|
|
|
|
generator.add_endpoint(
|
|
'POST', '/api/v2/cache/prewarm/clear',
|
|
summary='清空预热队列',
|
|
description='清空待预热的项目队列',
|
|
tags=['Cache']
|
|
)
|
|
|
|
# ========== 健康检查端点 ==========
|
|
generator.add_endpoint(
|
|
'GET', '/api/v2/health',
|
|
summary='获取健康状态',
|
|
description='返回服务器的整体健康状态',
|
|
tags=['Health']
|
|
)
|
|
|
|
generator.add_endpoint(
|
|
'GET', '/api/v2/health/sources',
|
|
summary='获取镜像源健康状态',
|
|
description='返回所有镜像源的健康检查结果',
|
|
tags=['Health']
|
|
)
|
|
|
|
generator.add_endpoint(
|
|
'GET', '/api/v2/health/check/:source_name',
|
|
summary='检查指定源健康',
|
|
description='手动触发指定镜像源的健康检查',
|
|
tags=['Health']
|
|
)
|
|
|
|
generator.add_endpoint(
|
|
'GET', '/api/v2/health/failover',
|
|
summary='获取故障切换状态',
|
|
description='返回故障切换系统的当前状态',
|
|
tags=['Health']
|
|
)
|
|
|
|
generator.add_endpoint(
|
|
'POST', '/api/v2/health/failover/:mirror_type',
|
|
summary='触发故障切换',
|
|
description='手动触发指定镜像类型的故障切换',
|
|
tags=['Health']
|
|
)
|
|
|
|
# ========== 告警管理端点 ==========
|
|
generator.add_endpoint(
|
|
'GET', '/api/v2/alerts',
|
|
summary='获取告警列表',
|
|
description='返回当前告警列表',
|
|
tags=['Alerts'],
|
|
parameters=[{
|
|
'name': 'limit',
|
|
'in': 'query',
|
|
'schema': {'type': 'integer'},
|
|
'description': '返回数量限制'
|
|
}]
|
|
)
|
|
|
|
generator.add_endpoint(
|
|
'POST', '/api/v2/alerts/:alert_id/acknowledge',
|
|
summary='确认告警',
|
|
description='确认指定告警',
|
|
tags=['Alerts']
|
|
)
|
|
|
|
generator.add_endpoint(
|
|
'POST', '/api/v2/alerts/clear',
|
|
summary='清除告警历史',
|
|
description='清除所有告警历史记录',
|
|
tags=['Alerts']
|
|
)
|
|
|
|
generator.add_endpoint(
|
|
'POST', '/api/v2/alerts/test',
|
|
summary='测试告警发送',
|
|
description='发送测试告警以验证配置',
|
|
tags=['Alerts']
|
|
)
|
|
|
|
generator.add_endpoint(
|
|
'GET', '/api/v2/alerts/config',
|
|
summary='获取告警配置',
|
|
description='返回当前的告警配置',
|
|
tags=['Alerts']
|
|
)
|
|
|
|
generator.add_endpoint(
|
|
'PUT', '/api/v2/alerts/config',
|
|
summary='更新告警配置',
|
|
description='更新告警配置(邮件、Webhook 等)',
|
|
tags=['Alerts']
|
|
)
|
|
|
|
# ========== Webhook 端点 ==========
|
|
generator.add_endpoint(
|
|
'GET', '/api/v2/webhooks',
|
|
summary='列出所有 Webhook',
|
|
description='返回所有配置的 Webhook',
|
|
tags=['Webhooks']
|
|
)
|
|
|
|
generator.add_endpoint(
|
|
'POST', '/api/v2/webhooks',
|
|
summary='创建 Webhook',
|
|
description='创建新的 Webhook 配置',
|
|
tags=['Webhooks']
|
|
)
|
|
|
|
generator.add_endpoint(
|
|
'GET', '/api/v2/webhooks/:webhook_id',
|
|
summary='获取 Webhook 详情',
|
|
description='返回指定 Webhook 的详细信息',
|
|
tags=['Webhooks']
|
|
)
|
|
|
|
generator.add_endpoint(
|
|
'PUT', '/api/v2/webhooks/:webhook_id',
|
|
summary='更新 Webhook',
|
|
description='更新指定 Webhook 的配置',
|
|
tags=['Webhooks']
|
|
)
|
|
|
|
generator.add_endpoint(
|
|
'DELETE', '/api/v2/webhooks/:webhook_id',
|
|
summary='删除 Webhook',
|
|
description='删除指定的 Webhook',
|
|
tags=['Webhooks']
|
|
)
|
|
|
|
generator.add_endpoint(
|
|
'POST', '/api/v2/webhooks/:webhook_id/test',
|
|
summary='测试 Webhook',
|
|
description='发送测试请求到指定的 Webhook',
|
|
tags=['Webhooks']
|
|
)
|
|
|
|
generator.add_endpoint(
|
|
'GET', '/api/v2/webhooks/:webhook_id/deliveries',
|
|
summary='获取 Webhook 交付历史',
|
|
description='返回指定 Webhook 的交付历史记录',
|
|
tags=['Webhooks']
|
|
)
|
|
|
|
generator.add_endpoint(
|
|
'GET', '/api/v2/webhooks/:webhook_id/stats',
|
|
summary='获取 Webhook 统计',
|
|
description='返回指定 Webhook 的交付统计信息',
|
|
tags=['Webhooks']
|
|
)
|
|
|
|
# ========== 配置管理端点 ==========
|
|
generator.add_endpoint(
|
|
'GET', '/api/v2/config',
|
|
summary='获取配置',
|
|
description='返回当前的服务器配置',
|
|
tags=['Configuration']
|
|
)
|
|
|
|
generator.add_endpoint(
|
|
'PUT', '/api/v2/config',
|
|
summary='保存配置',
|
|
description='保存配置到 settings.json',
|
|
tags=['Configuration']
|
|
)
|
|
|
|
generator.add_endpoint(
|
|
'POST', '/api/v2/config/reload',
|
|
summary='重新加载配置',
|
|
description='重新加载配置文件(热更新)',
|
|
tags=['Configuration']
|
|
)
|
|
|
|
generator.add_endpoint(
|
|
'GET', '/api/v2/config/changes',
|
|
summary='获取配置变更历史',
|
|
description='返回配置变更的历史记录',
|
|
tags=['Configuration']
|
|
)
|
|
|
|
# ========== 重启管理端点 ==========
|
|
generator.add_endpoint(
|
|
'GET', '/api/v2/server/restart',
|
|
summary='获取重启状态',
|
|
description='返回服务器重启管理的当前状态',
|
|
tags=['Server']
|
|
)
|
|
|
|
generator.add_endpoint(
|
|
'POST', '/api/v2/server/restart',
|
|
summary='准备重启',
|
|
description='准备执行服务器重启',
|
|
tags=['Server']
|
|
)
|
|
|
|
generator.add_endpoint(
|
|
'POST', '/api/v2/server/restart/confirm',
|
|
summary='确认执行重启',
|
|
description='确认并执行服务器重启',
|
|
tags=['Server']
|
|
)
|
|
|
|
generator.add_endpoint(
|
|
'POST', '/api/v2/server/restart/immediate',
|
|
summary='立即重启',
|
|
description='立即重启服务器(不等待请求完成)',
|
|
tags=['Server']
|
|
)
|
|
|
|
generator.add_endpoint(
|
|
'GET', '/api/v2/server/restart/pending',
|
|
summary='获取待处理请求',
|
|
description='返回当前待处理的请求列表',
|
|
tags=['Server']
|
|
)
|
|
|
|
generator.add_endpoint(
|
|
'GET', '/api/v2/server/restart/history',
|
|
summary='获取重启历史',
|
|
description='返回服务器重启的历史记录',
|
|
tags=['Server']
|
|
)
|
|
|
|
# ========== 认证端点 ==========
|
|
generator.add_endpoint(
|
|
'POST', '/api/v2/admin/auth/verify',
|
|
summary='验证认证状态',
|
|
description='验证当前请求的认证状态',
|
|
tags=['Authentication']
|
|
)
|
|
|
|
return generator.generate()
|
|
|
|
|
|
def save_api_docs(config: Dict, filepath: str = None, format: str = 'json'):
|
|
"""
|
|
生成并保存 API 文档
|
|
|
|
Args:
|
|
config: 服务器配置
|
|
filepath: 保存路径
|
|
format: 输出格式 (json, yaml)
|
|
"""
|
|
doc = generate_api_docs(config)
|
|
|
|
if filepath is None:
|
|
# 默认保存到项目根目录
|
|
script_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
filepath = os.path.join(script_dir, 'docs', 'api-docs.json')
|
|
|
|
# 确保目录存在
|
|
os.makedirs(os.path.dirname(filepath), exist_ok=True)
|
|
|
|
if format == 'yaml':
|
|
try:
|
|
import yaml
|
|
with open(filepath, 'w', encoding='utf-8') as f:
|
|
yaml.dump(doc, f, default_flow_style=False, allow_unicode=True)
|
|
except ImportError:
|
|
format = 'json'
|
|
|
|
if format == 'json':
|
|
with open(filepath, 'w', encoding='utf-8') as f:
|
|
json.dump(doc, f, ensure_ascii=False, indent=2)
|
|
|
|
return filepath
|