mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-10 19:29:50 +08:00
feat: 全栈功能增强 - 扩展 provider/pool 管理、完善调度与数据层、重构前端 Pool 页面
后端: - 扩展 pool_admin payloads 和 provider query models,增强 endpoint key 管理 - 完善 scheduler-core 候选排序与请求候选逻辑 - 增强 usage-runtime 写入、provider-transport 网络层与 OAuth 刷新 - 改进 AI pipeline 响应转换与流式处理 - 扩展 global_models/provider_catalog 数据层查询能力 - 增强 video-tasks-core 多 provider 支持 - 新增大量集成测试覆盖 pool/keys/provider_query/frontdoor 前端: - 重构 PoolManagement 页面,拆分状态管理/对话框逻辑到独立模块 - 新增 poolAdvancedDialog/poolSchedulingDialog/poolManagementState/poolMobilePresentation 工具函数及测试 - 改进 Dialog 组件与 provider tabs 显示 部署: - 更新 Rust CI workflow 和 Dockerfile 构建配置 Closes #275 Co-authored-by: AAEE86 <[email protected]>
This commit is contained in:
@@ -1,5 +1,13 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
use axum::extract::Request;
|
||||
use axum::http::Method;
|
||||
use axum::response::{IntoResponse, Response};
|
||||
use axum::routing::any;
|
||||
use axum::Router;
|
||||
use tower::ServiceExt;
|
||||
use tower_http::services::{ServeDir, ServeFile};
|
||||
use tracing::warn;
|
||||
|
||||
use aether_runtime::{prometheus_response, ConcurrencyError, DistributedConcurrencyError};
|
||||
|
||||
@@ -9,6 +17,12 @@ pub fn build_router() -> Result<Router, reqwest::Error> {
|
||||
Ok(build_router_with_state(AppState::new()?))
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct FrontendStaticState {
|
||||
static_dir: PathBuf,
|
||||
index_html: PathBuf,
|
||||
}
|
||||
|
||||
pub fn build_router_with_state(state: AppState) -> Router {
|
||||
let cors_state = state.clone();
|
||||
let mut router = Router::<AppState>::new();
|
||||
@@ -32,6 +46,75 @@ pub fn build_router_with_state(state: AppState) -> Router {
|
||||
router
|
||||
}
|
||||
|
||||
pub fn attach_static_frontend(router: Router, static_dir: impl Into<PathBuf>) -> Router {
|
||||
let static_dir = static_dir.into();
|
||||
let index_html = static_dir.join("index.html");
|
||||
router.layer(axum::middleware::from_fn_with_state(
|
||||
FrontendStaticState {
|
||||
static_dir,
|
||||
index_html,
|
||||
},
|
||||
frontend_static_middleware,
|
||||
))
|
||||
}
|
||||
|
||||
async fn frontend_static_middleware(
|
||||
axum::extract::State(frontend): axum::extract::State<FrontendStaticState>,
|
||||
request: Request,
|
||||
next: axum::middleware::Next,
|
||||
) -> Response {
|
||||
let path = request.uri().path().to_string();
|
||||
if !matches!(request.method(), &Method::GET | &Method::HEAD)
|
||||
|| frontend_path_bypasses_static(&path)
|
||||
{
|
||||
return next.run(request).await;
|
||||
}
|
||||
|
||||
if frontend_path_targets_static_asset(&path) {
|
||||
return serve_static_asset(&frontend.static_dir, request).await;
|
||||
}
|
||||
|
||||
serve_frontend_index(&frontend.index_html, request).await
|
||||
}
|
||||
|
||||
fn frontend_path_bypasses_static(path: &str) -> bool {
|
||||
matches!(
|
||||
path,
|
||||
"/health" | "/test-connection" | crate::constants::READYZ_PATH
|
||||
) || path.starts_with("/api/")
|
||||
|| path.starts_with("/v1/")
|
||||
|| path.starts_with("/v1beta/")
|
||||
|| path.starts_with("/upload/")
|
||||
|| path.starts_with("/_gateway/")
|
||||
|| path.starts_with("/.well-known/")
|
||||
}
|
||||
|
||||
fn frontend_path_targets_static_asset(path: &str) -> bool {
|
||||
path.rsplit('/')
|
||||
.next()
|
||||
.is_some_and(|segment| !segment.is_empty() && segment.contains('.'))
|
||||
}
|
||||
|
||||
async fn serve_static_asset(static_dir: &PathBuf, request: Request) -> Response {
|
||||
match ServeDir::new(static_dir).oneshot(request).await {
|
||||
Ok(response) => response.into_response(),
|
||||
Err(err) => {
|
||||
warn!(error = %err, "failed to serve frontend static asset");
|
||||
axum::http::StatusCode::INTERNAL_SERVER_ERROR.into_response()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn serve_frontend_index(index_html: &PathBuf, request: Request) -> Response {
|
||||
match ServeFile::new(index_html).oneshot(request).await {
|
||||
Ok(response) => response.into_response(),
|
||||
Err(err) => {
|
||||
warn!(error = %err, "failed to serve frontend index");
|
||||
axum::http::StatusCode::INTERNAL_SERVER_ERROR.into_response()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn metrics(
|
||||
axum::extract::State(state): axum::extract::State<AppState>,
|
||||
) -> impl axum::response::IntoResponse {
|
||||
|
||||
Reference in New Issue
Block a user