mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-09 02:47:45 +08:00
feat(proxy): 实现代理节点批量升级回滚、隧道重定向跟随及远程配置管理
核心功能: - 新增代理节点批量升级回滚工作流,支持分批升级、健康探针、跳过/重试/取消等操作 - proxy 隧道流处理器支持 HTTP 重定向跟随(最多 10 跳),区分 307/308 可重播与不可重播请求体 - proxy 协议新增 follow_redirects / http1_only 字段,网关侧同步支持 - 新增代理节点远端配置变更接口(名称、允许端口、调度状态、升级目标等) - 新增代理节点注册/反注册/心跳的 Admin API,及节点过期清理维护任务 - gateway 隧道 owner-relay 支持流式代理大请求体,新增 5 MiB 默认限制 - 新增 ProxyNodeRegistrationMutation / ProxyNodeRemoteConfigMutation 数据类型 - proxy 配置新增重定向重播预算、心跳间隔等参数,TUI 安装向导同步更新 - 前端 ProxyNodes 页面新增批量升级操作面板及滚动进度展示
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
use crate::handlers::admin::request::AdminAppState;
|
||||
use crate::handlers::shared::unix_secs_to_rfc3339;
|
||||
use crate::maintenance::{inspect_proxy_upgrade_rollout, ProxyUpgradeRolloutStatus};
|
||||
use crate::GatewayError;
|
||||
use aether_admin::system::{
|
||||
build_admin_proxy_node_event_payload, build_admin_proxy_node_events_payload_response,
|
||||
@@ -9,6 +11,20 @@ use aether_admin::system::{
|
||||
use axum::{body::Body, response::Response};
|
||||
|
||||
impl<'a> AdminAppState<'a> {
|
||||
pub(crate) async fn register_proxy_node(
|
||||
&self,
|
||||
mutation: &aether_data::repository::proxy_nodes::ProxyNodeRegistrationMutation,
|
||||
) -> Result<Option<aether_data::repository::proxy_nodes::StoredProxyNode>, GatewayError> {
|
||||
self.app.register_proxy_node(mutation).await
|
||||
}
|
||||
|
||||
pub(crate) async fn apply_proxy_node_heartbeat(
|
||||
&self,
|
||||
mutation: &aether_data::repository::proxy_nodes::ProxyNodeHeartbeatMutation,
|
||||
) -> Result<Option<aether_data::repository::proxy_nodes::StoredProxyNode>, GatewayError> {
|
||||
self.app.apply_proxy_node_heartbeat(mutation).await
|
||||
}
|
||||
|
||||
pub(crate) async fn build_admin_proxy_nodes_list_response(
|
||||
&self,
|
||||
skip: usize,
|
||||
@@ -42,8 +58,12 @@ impl<'a> AdminAppState<'a> {
|
||||
.take(limit)
|
||||
.map(|node| build_admin_proxy_node_payload(&node))
|
||||
.collect::<Vec<_>>();
|
||||
let rollout = inspect_proxy_upgrade_rollout(self.app().data.as_ref())
|
||||
.await
|
||||
.map_err(|err| GatewayError::Internal(err.to_string()))?
|
||||
.map(build_admin_proxy_upgrade_rollout_payload);
|
||||
Ok(build_admin_proxy_nodes_list_payload_response(
|
||||
items, total, skip, limit,
|
||||
items, total, skip, limit, rollout,
|
||||
))
|
||||
}
|
||||
|
||||
@@ -66,4 +86,55 @@ impl<'a> AdminAppState<'a> {
|
||||
.collect::<Vec<_>>();
|
||||
Ok(build_admin_proxy_node_events_payload_response(items))
|
||||
}
|
||||
|
||||
pub(crate) async fn unregister_proxy_node(
|
||||
&self,
|
||||
node_id: &str,
|
||||
) -> Result<Option<aether_data::repository::proxy_nodes::StoredProxyNode>, GatewayError> {
|
||||
self.app.unregister_proxy_node(node_id).await
|
||||
}
|
||||
|
||||
pub(crate) async fn update_proxy_node_remote_config(
|
||||
&self,
|
||||
mutation: &aether_data::repository::proxy_nodes::ProxyNodeRemoteConfigMutation,
|
||||
) -> Result<Option<aether_data::repository::proxy_nodes::StoredProxyNode>, GatewayError> {
|
||||
self.app.update_proxy_node_remote_config(mutation).await
|
||||
}
|
||||
}
|
||||
|
||||
fn build_admin_proxy_upgrade_rollout_payload(
|
||||
rollout: ProxyUpgradeRolloutStatus,
|
||||
) -> serde_json::Value {
|
||||
serde_json::json!({
|
||||
"version": rollout.version,
|
||||
"batch_size": rollout.batch_size,
|
||||
"cooldown_secs": rollout.cooldown_secs,
|
||||
"started_at": unix_secs_to_rfc3339(rollout.started_at_unix_secs),
|
||||
"last_dispatched_at": rollout
|
||||
.last_dispatched_at_unix_secs
|
||||
.and_then(unix_secs_to_rfc3339),
|
||||
"updated_at": unix_secs_to_rfc3339(rollout.updated_at_unix_secs),
|
||||
"probe": rollout.probe.map(|probe| serde_json::json!({
|
||||
"url": probe.url,
|
||||
"timeout_secs": probe.timeout_secs,
|
||||
})),
|
||||
"blocked": rollout.blocked,
|
||||
"online_eligible_total": rollout.online_eligible_total,
|
||||
"completed_node_ids": rollout.completed_node_ids,
|
||||
"pending_node_ids": rollout.pending_node_ids,
|
||||
"conflict_node_ids": rollout.conflict_node_ids,
|
||||
"skipped_node_ids": rollout.skipped_node_ids,
|
||||
"tracked_nodes": rollout.tracked_nodes.into_iter().map(|tracked| serde_json::json!({
|
||||
"node_id": tracked.node_id,
|
||||
"state": tracked.state,
|
||||
"dispatched_at": unix_secs_to_rfc3339(tracked.dispatched_at_unix_secs),
|
||||
"version_confirmed_at": tracked
|
||||
.version_confirmed_at_unix_secs
|
||||
.and_then(unix_secs_to_rfc3339),
|
||||
"traffic_confirmed_at": tracked
|
||||
.traffic_confirmed_at_unix_secs
|
||||
.and_then(unix_secs_to_rfc3339),
|
||||
"cooldown_remaining_secs": tracked.cooldown_remaining_secs,
|
||||
})).collect::<Vec<_>>(),
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user