mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-03 01:40:21 +08:00
feat: delegate 客户端替换为 hyper 原生实现,新增代理管理功能
aether-proxy: - 用 hyper-util Client + 自定义 InstrumentedConnector 替换 reqwest delegate 客户端 - 支持 HTTP/HTTPS 自动 TLS,ALPN h2 协商,connect/tls 分阶段计时 - ConnectTiming 通过 hyper extensions 传递,上游响应细分 connect_ms/tls_ms/ttfb_ms - upgrade 命令在非 root 下跳过 systemd restart 并提示手动操作 后端: - 新增 /admin/proxy-nodes/test-url 接口,支持直接测试代理 URL 连通性 - 新增 /admin/proxy-nodes/hmac-key 接口,获取 HMAC Key 供部署使用 - 提取 _test_proxy_connectivity 公共函数,消除 test_node 中的重复代码 - candidate_resolver 在 extra_data 中输出 needs_conversion/provider_api_format - stats_aggregator 小时聚合增加 IntegrityError 冲突重试 前端: - 请求时间线组件展示代理 timing 细分(DNS/连接/TLS/TTFB/上游处理) - 请求时间线增加格式转换分界标记和 conversion badge - ProxyNodes 页面新增代理 URL 测试和 HMAC Key 复制功能 - HardwareTooltip 从 Popover 改为 Tooltip 组件
This commit is contained in:
@@ -216,6 +216,18 @@ async def test_proxy_node(node_id: str, request: Request, db: Session = Depends(
|
||||
return await pipeline.run(adapter=adapter, http_request=request, db=db, mode=adapter.mode)
|
||||
|
||||
|
||||
@router.get("/hmac-key")
|
||||
async def get_proxy_hmac_key(request: Request, db: Session = Depends(get_db)) -> Any:
|
||||
adapter = AdminGetProxyHmacKeyAdapter()
|
||||
return await pipeline.run(adapter=adapter, http_request=request, db=db, mode=adapter.mode)
|
||||
|
||||
|
||||
@router.post("/test-url")
|
||||
async def test_proxy_url(request: Request, db: Session = Depends(get_db)) -> Any:
|
||||
adapter = AdminTestProxyUrlAdapter()
|
||||
return await pipeline.run(adapter=adapter, http_request=request, db=db, mode=adapter.mode)
|
||||
|
||||
|
||||
@router.put("/{node_id}/config")
|
||||
async def update_proxy_node_config(
|
||||
node_id: str, request: Request, db: Session = Depends(get_db)
|
||||
@@ -485,3 +497,46 @@ class AdminUpdateProxyNodeConfigAdapter(AdminApiAdapter):
|
||||
"remote_config": node.remote_config,
|
||||
"node": node_to_dict(node),
|
||||
}
|
||||
|
||||
|
||||
@dataclass
|
||||
class AdminGetProxyHmacKeyAdapter(AdminApiAdapter):
|
||||
"""获取 proxy_hmac_key 供管理员复制到 aether-proxy 部署"""
|
||||
|
||||
name: str = "admin_get_proxy_hmac_key"
|
||||
|
||||
async def handle(self, context: ApiRequestContext) -> Any:
|
||||
from src.config.settings import config
|
||||
|
||||
key = config.proxy_hmac_key
|
||||
if not key:
|
||||
raise InvalidRequestException(
|
||||
"PROXY_HMAC_KEY 未配置(也未设置 ENCRYPTION_KEY 用于自动派生)"
|
||||
)
|
||||
return {"proxy_hmac_key": key}
|
||||
|
||||
|
||||
class TestProxyUrlRequest(BaseModel):
|
||||
proxy_url: str = Field(..., min_length=1, max_length=500)
|
||||
username: str | None = Field(None, max_length=255)
|
||||
password: str | None = Field(None, max_length=500)
|
||||
|
||||
|
||||
@dataclass
|
||||
class AdminTestProxyUrlAdapter(AdminApiAdapter):
|
||||
"""通过 proxy_url 直接测试代理连通性(无需已注册节点)"""
|
||||
|
||||
name: str = "admin_test_proxy_url"
|
||||
|
||||
async def handle(self, context: ApiRequestContext) -> Any:
|
||||
payload = context.ensure_json_body()
|
||||
try:
|
||||
req = TestProxyUrlRequest.model_validate(payload)
|
||||
except ValidationError as exc:
|
||||
raise InvalidRequestException("输入验证失败: " + _format_validation_error(exc))
|
||||
|
||||
return await ProxyNodeService.test_proxy_url(
|
||||
proxy_url=req.proxy_url,
|
||||
username=req.username,
|
||||
password=req.password,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user