From 9f4a51843b6b170f57f2735420b77acd214c3f76 Mon Sep 17 00:00:00 2001 From: kdletters Date: Tue, 21 Apr 2026 01:03:21 +0800 Subject: [PATCH] build: add api server config loader --- .../01_M0_M2_FOUNDATION_AND_AUTH.md | 3 +- server-rs/apps/api-server/README.md | 12 ++--- server-rs/apps/api-server/src/config.rs | 44 +++++++++++++++++++ server-rs/apps/api-server/src/main.rs | 12 ++--- server-rs/apps/api-server/src/state.rs | 14 ++++-- 5 files changed, 68 insertions(+), 17 deletions(-) create mode 100644 server-rs/apps/api-server/src/config.rs diff --git a/backend-rewrite-tasklist/01_M0_M2_FOUNDATION_AND_AUTH.md b/backend-rewrite-tasklist/01_M0_M2_FOUNDATION_AND_AUTH.md index 33fa8042..0a17cfc0 100644 --- a/backend-rewrite-tasklist/01_M0_M2_FOUNDATION_AND_AUTH.md +++ b/backend-rewrite-tasklist/01_M0_M2_FOUNDATION_AND_AUTH.md @@ -94,7 +94,8 @@ - [x] 搭建 `main.rs` / `Router` / `with_state` 交付物:[../server-rs/apps/api-server/src/main.rs](../server-rs/apps/api-server/src/main.rs) -- [ ] 接入统一配置加载 +- [x] 接入统一配置加载 + 交付物:[../server-rs/apps/api-server/src/config.rs](../server-rs/apps/api-server/src/config.rs) - [ ] 接入统一日志与 tracing - [ ] 接入 `request_id` 中间件 - [ ] 接入统一错误处理中间件 diff --git a/server-rs/apps/api-server/README.md b/server-rs/apps/api-server/README.md index 75b7f1c8..35ff7b5e 100644 --- a/server-rs/apps/api-server/README.md +++ b/server-rs/apps/api-server/README.md @@ -21,15 +21,15 @@ 3. `src/main.rs` 4. `src/app.rs` 5. `src/state.rs` +6. `src/config.rs` 后续与本 package 直接相关的任务包括: -1. 接入统一配置加载 -2. 接入统一日志与 tracing -3. 接入 `request_id` -4. 接入统一错误处理中间件 -5. 接入 response envelope -6. 接入 `/healthz` +1. 接入统一日志与 tracing +2. 接入 `request_id` +3. 接入统一错误处理中间件 +4. 接入 response envelope +5. 接入 `/healthz` ## 3. 边界约束 diff --git a/server-rs/apps/api-server/src/config.rs b/server-rs/apps/api-server/src/config.rs new file mode 100644 index 00000000..2807ce31 --- /dev/null +++ b/server-rs/apps/api-server/src/config.rs @@ -0,0 +1,44 @@ +use std::{env, net::SocketAddr}; + +// 集中管理 api-server 的启动配置,避免入口层直接散落环境变量解析逻辑。 +#[derive(Clone, Debug)] +pub struct AppConfig { + pub bind_host: String, + pub bind_port: u16, +} + +impl Default for AppConfig { + fn default() -> Self { + Self { + bind_host: "127.0.0.1".to_string(), + bind_port: 3000, + } + } +} + +impl AppConfig { + pub fn from_env() -> Self { + let mut config = Self::default(); + + if let Ok(bind_host) = env::var("GENARRATIVE_API_HOST") { + if !bind_host.trim().is_empty() { + config.bind_host = bind_host; + } + } + + if let Ok(bind_port) = env::var("GENARRATIVE_API_PORT") { + if let Ok(parsed_port) = bind_port.parse::() { + config.bind_port = parsed_port; + } + } + + config + } + + pub fn bind_socket_addr(&self) -> SocketAddr { + let address = format!("{}:{}", self.bind_host, self.bind_port); + address + .parse() + .unwrap_or_else(|_| SocketAddr::from(([127, 0, 0, 1], 3000))) + } +} diff --git a/server-rs/apps/api-server/src/main.rs b/server-rs/apps/api-server/src/main.rs index a0328fa4..0cab5b62 100644 --- a/server-rs/apps/api-server/src/main.rs +++ b/server-rs/apps/api-server/src/main.rs @@ -1,19 +1,19 @@ mod app; +mod config; mod state; -use std::net::SocketAddr; - use tokio::net::TcpListener; -use crate::{app::build_router, state::AppState}; +use crate::{app::build_router, config::AppConfig, state::AppState}; #[tokio::main] async fn main() -> Result<(), std::io::Error> { - // 当前阶段先用固定地址启动最小骨架,后续再切到统一配置加载。 - let bind_address = SocketAddr::from(([127, 0, 0, 1], 3000)); + // 统一先从配置对象读取监听地址,避免后续把环境变量读取散落到入口和路由层。 + let config = AppConfig::from_env(); + let bind_address = config.bind_socket_addr(); let listener = TcpListener::bind(bind_address).await?; - let state = AppState::new(); + let state = AppState::new(config); let router = build_router(state); axum::serve(listener, router).await diff --git a/server-rs/apps/api-server/src/state.rs b/server-rs/apps/api-server/src/state.rs index eb6671a6..1d55662c 100644 --- a/server-rs/apps/api-server/src/state.rs +++ b/server-rs/apps/api-server/src/state.rs @@ -1,9 +1,15 @@ +use crate::config::AppConfig; + // 当前阶段先保留最小共享状态壳,后续逐步接入配置、客户端与平台适配。 -#[derive(Clone, Debug, Default)] -pub struct AppState; +#[derive(Clone, Debug)] +pub struct AppState { + // 配置会在后续中间件、路由和平台适配接入时逐步消费。 + #[allow(dead_code)] + pub config: AppConfig, +} impl AppState { - pub fn new() -> Self { - Self + pub fn new(config: AppConfig) -> Self { + Self { config } } }