# 路由层文档 ## 概述 路由层是 UdminAI 的 HTTP API 接口层,负责处理客户端请求、参数验证、权限检查、调用服务层业务逻辑,并返回统一格式的响应。基于 Axum 框架构建,提供 RESTful API 接口。 ## 架构设计 ### 路由模块结构 ``` routes/ ├── mod.rs # 路由模块导出和总路由配置 ├── auth.rs # 认证相关路由 ├── user.rs # 用户管理路由 ├── role.rs # 角色管理路由 ├── permission.rs # 权限管理路由 ├── flow.rs # 流程管理路由 ├── schedule_job.rs # 定时任务路由 ├── system.rs # 系统管理路由 ├── log.rs # 日志查询路由 ├── notification.rs # 通知管理路由 └── websocket.rs # WebSocket 路由 ``` ### 设计原则 - **RESTful 设计**: 遵循 REST API 设计规范 - **统一响应格式**: 所有接口返回统一的响应格式 - **参数验证**: 在路由层进行请求参数验证 - **权限控制**: 集成权限中间件进行访问控制 - **错误处理**: 统一的错误处理和响应 - **文档支持**: 支持 OpenAPI/Swagger 文档生成 ## 总路由配置 (mod.rs) ### 路由树结构 ```rust pub fn create_routes() -> Router { Router::new() // 认证路由 (无需认证) .nest("/auth", auth::routes()) // API 路由 (需要认证) .nest("/api", Router::new() .nest("/users", user::routes()) .nest("/roles", role::routes()) .nest("/permissions", permission::routes()) .nest("/flows", flow::routes()) .nest("/jobs", schedule_job::routes()) .nest("/system", system::routes()) .nest("/logs", log::routes()) .nest("/notifications", notification::routes()) .layer(AuthMiddleware::new()) ) // WebSocket 路由 .nest("/ws", websocket::routes()) // 静态文件路由 .nest("/static", static_files::routes()) // 健康检查 .route("/health", get(health_check)) // 中间件层 .layer(CorsLayer::permissive()) .layer(TraceLayer::new_for_http()) .layer(CompressionLayer::new()) } ``` ### 中间件配置 ```rust /// 应用中间件 pub fn apply_middlewares(app: Router) -> Router { app // 请求追踪 .layer(TraceLayer::new_for_http()) // CORS 支持 .layer(CorsLayer::new() .allow_origin(Any) .allow_methods([Method::GET, Method::POST, Method::PUT, Method::DELETE]) .allow_headers([AUTHORIZATION, CONTENT_TYPE]) ) // 请求压缩 .layer(CompressionLayer::new()) // 请求限流 .layer(RateLimitLayer::new(100, Duration::from_secs(60))) // 请求日志 .layer(RequestLogLayer::new()) } ``` ## 认证路由 (auth.rs) ### 路由定义 ```rust pub fn routes() -> Router { Router::new() .route("/login", post(login)) .route("/logout", post(logout)) .route("/refresh", post(refresh_token)) .route("/register", post(register)) .route("/forgot-password", post(forgot_password)) .route("/reset-password", post(reset_password)) .route("/verify-email", post(verify_email)) } ``` ### 接口实现 #### 用户登录 ```rust /// POST /auth/login /// 用户登录接口 pub async fn login( State(app_state): State, Json(req): Json, ) -> Result>, AppError> { // 参数验证 req.validate().map_err(|e| AppError::BadRequest(e.to_string()))?; // 用户认证 let user = user_service::authenticate( &app_state.db, &req.username, &req.password, ).await?; // 生成 JWT Token let token = jwt::generate_token(&user.id, &app_state.jwt_secret)?; let refresh_token = jwt::generate_refresh_token(&user.id, &app_state.jwt_secret)?; // 记录登录日志 log_service::log_operation( &app_state.db, OperationLog { user_id: user.id.clone(), operation: "login".to_string(), resource: "auth".to_string(), resource_id: None, details: json!({ "username": req.username }), ip_address: extract_client_ip(&req), user_agent: extract_user_agent(&req), timestamp: now_fixed_offset(), }, ).await?; Ok(Json(ApiResponse::success(LoginResp { user, token, refresh_token, expires_in: 3600, }))) } ``` #### 请求/响应结构 ```rust #[derive(Debug, Deserialize, Validate)] pub struct LoginReq { #[validate(length(min = 3, max = 50))] pub username: String, #[validate(length(min = 6))] pub password: String, pub remember_me: Option, } #[derive(Debug, Serialize)] pub struct LoginResp { pub user: UserDoc, pub token: String, pub refresh_token: String, pub expires_in: u64, } ``` ## 用户管理路由 (user.rs) ### 路由定义 ```rust pub fn routes() -> Router { Router::new() .route("/", get(list_users).post(create_user)) .route("/:id", get(get_user).put(update_user).delete(delete_user)) .route("/:id/roles", get(get_user_roles).put(update_user_roles)) .route("/:id/permissions", get(get_user_permissions)) .route("/:id/password", put(change_password)) .route("/:id/status", put(update_user_status)) .route("/profile", get(get_current_user).put(update_profile)) .route("/avatar", post(upload_avatar)) } ``` ### 接口实现 #### 用户列表查询 ```rust /// GET /api/users /// 分页查询用户列表 pub async fn list_users( State(app_state): State, Query(params): Query, Extension(current_user): Extension, ) -> Result>>, AppError> { // 权限检查 permission_service::check_user_permission( &app_state.db, ¤t_user.id, "user", "read", ).await?; // 构建过滤条件 let filters = UserFilters { username: params.username, email: params.email, status: params.status, role_ids: params.role_ids, created_after: params.created_after, created_before: params.created_before, }; // 查询用户列表 let result = user_service::list_users( &app_state.db, params.page.unwrap_or(1), params.page_size.unwrap_or(20), Some(filters), ).await?; Ok(Json(ApiResponse::success(result))) } ``` #### 创建用户 ```rust /// POST /api/users /// 创建新用户 pub async fn create_user( State(app_state): State, Extension(current_user): Extension, Json(req): Json, ) -> Result>, AppError> { // 参数验证 req.validate().map_err(|e| AppError::BadRequest(e.to_string()))?; // 权限检查 permission_service::check_user_permission( &app_state.db, ¤t_user.id, "user", "create", ).await?; // 创建用户 let user = user_service::create_user(&app_state.db, req).await?; // 记录操作日志 log_service::log_operation( &app_state.db, OperationLog { user_id: current_user.id, operation: "create_user".to_string(), resource: "user".to_string(), resource_id: Some(user.id.clone()), details: json!({ "username": user.username }), ip_address: None, user_agent: None, timestamp: now_fixed_offset(), }, ).await?; Ok(Json(ApiResponse::success(user))) } ``` ### 查询参数结构 ```rust #[derive(Debug, Deserialize)] pub struct ListUsersQuery { pub page: Option, pub page_size: Option, pub username: Option, pub email: Option, pub status: Option, pub role_ids: Option>, pub created_after: Option>, pub created_before: Option>, pub sort_by: Option, pub sort_order: Option, } ``` ## 流程管理路由 (flow.rs) ### 路由定义 ```rust pub fn routes() -> Router { Router::new() .route("/", get(list_flows).post(create_flow)) .route("/:id", get(get_flow).put(update_flow).delete(delete_flow)) .route("/:id/versions", get(list_flow_versions).post(create_flow_version)) .route("/:id/publish", post(publish_flow)) .route("/:id/execute", post(execute_flow)) .route("/:id/executions", get(list_flow_executions)) .route("/executions/:execution_id", get(get_execution_detail)) .route("/executions/:execution_id/stop", post(stop_execution)) .route("/categories", get(list_flow_categories)) .route("/templates", get(list_flow_templates)) } ``` ### 接口实现 #### 执行流程 ```rust /// POST /api/flows/:id/execute /// 执行指定流程 pub async fn execute_flow( State(app_state): State, Path(flow_id): Path, Extension(current_user): Extension, Json(req): Json, ) -> Result>, AppError> { // 权限检查 permission_service::check_user_permission( &app_state.db, ¤t_user.id, "flow", "execute", ).await?; // 获取流程信息 let flow = flow_service::get_flow_by_id(&app_state.db, &flow_id).await? .ok_or_else(|| AppError::NotFound("流程不存在".to_string()))?; // 检查流程状态 if flow.status != FlowStatus::Published { return Err(AppError::BadRequest("只能执行已发布的流程".to_string())); } // 执行选项 let options = ExecuteOptions { max_steps: req.max_steps, timeout_ms: req.timeout_ms, parallel: req.parallel.unwrap_or(false), stream_events: req.stream_events.unwrap_or(false), }; // 执行流程 let result = flow_service::execute_flow( &app_state.db, &flow_id, req.input.unwrap_or(json!({})), options, ).await?; // 记录执行日志 log_service::log_operation( &app_state.db, OperationLog { user_id: current_user.id, operation: "execute_flow".to_string(), resource: "flow".to_string(), resource_id: Some(flow_id), details: json!({ "execution_id": result.execution_id, "status": result.status }), ip_address: None, user_agent: None, timestamp: now_fixed_offset(), }, ).await?; Ok(Json(ApiResponse::success(result))) } ``` #### 请求/响应结构 ```rust #[derive(Debug, Deserialize, Validate)] pub struct ExecuteFlowReq { pub input: Option, pub max_steps: Option, pub timeout_ms: Option, pub parallel: Option, pub stream_events: Option, } #[derive(Debug, Serialize)] pub struct ExecutionResult { pub execution_id: String, pub status: ExecutionStatus, pub result: Option, pub error: Option, pub start_time: DateTime, pub end_time: Option>, pub duration_ms: Option, } ``` ## 定时任务路由 (schedule_job.rs) ### 路由定义 ```rust pub fn routes() -> Router { Router::new() .route("/", get(list_jobs).post(create_job)) .route("/:id", get(get_job).put(update_job).delete(delete_job)) .route("/:id/enable", post(enable_job)) .route("/:id/disable", post(disable_job)) .route("/:id/trigger", post(trigger_job)) .route("/:id/executions", get(list_job_executions)) .route("/executions/:execution_id", get(get_execution_detail)) .route("/cron/validate", post(validate_cron)) .route("/cron/next-runs", post(get_next_runs)) } ``` ### 接口实现 #### 创建定时任务 ```rust /// POST /api/jobs /// 创建定时任务 pub async fn create_job( State(app_state): State, Extension(current_user): Extension, Json(req): Json, ) -> Result>, AppError> { // 参数验证 req.validate().map_err(|e| AppError::BadRequest(e.to_string()))?; // 权限检查 permission_service::check_user_permission( &app_state.db, ¤t_user.id, "job", "create", ).await?; // 验证 Cron 表达式 cron::Schedule::from_str(&req.cron_expression) .map_err(|_| AppError::BadRequest("无效的 Cron 表达式".to_string()))?; // 创建任务 let job = schedule_job_service::create_schedule_job(&app_state.db, req).await?; // 注册到调度器 if job.enabled { schedule_job_service::register_job_to_scheduler( &app_state.scheduler, &job, ).await?; } Ok(Json(ApiResponse::success(job))) } ``` #### Cron 表达式验证 ```rust /// POST /api/jobs/cron/validate /// 验证 Cron 表达式 pub async fn validate_cron( Json(req): Json, ) -> Result>, AppError> { let schedule = cron::Schedule::from_str(&req.cron_expression) .map_err(|e| AppError::BadRequest(format!("无效的 Cron 表达式: {}", e)))?; // 计算接下来的执行时间 let now = Utc::now(); let next_runs: Vec> = schedule .upcoming(Utc) .take(5) .collect(); Ok(Json(ApiResponse::success(ValidateCronResp { valid: true, next_runs, description: describe_cron(&req.cron_expression), }))) } ``` ## WebSocket 路由 (websocket.rs) ### 路由定义 ```rust pub fn routes() -> Router { Router::new() .route("/flow-execution/:execution_id", get(flow_execution_ws)) .route("/system-monitor", get(system_monitor_ws)) .route("/notifications", get(notifications_ws)) .route("/logs", get(logs_ws)) } ``` ### WebSocket 处理 #### 流程执行监控 ```rust /// GET /ws/flow-execution/:execution_id /// 流程执行实时监控 pub async fn flow_execution_ws( ws: WebSocketUpgrade, Path(execution_id): Path, Extension(current_user): Extension, State(app_state): State, ) -> Result { // 权限检查 permission_service::check_user_permission( &app_state.db, ¤t_user.id, "flow", "read", ).await?; Ok(ws.on_upgrade(move |socket| { handle_flow_execution_ws(socket, execution_id, current_user, app_state) })) } async fn handle_flow_execution_ws( socket: WebSocket, execution_id: String, current_user: CurrentUser, app_state: AppState, ) { let (mut sender, mut receiver) = socket.split(); // 订阅执行事件 let mut event_stream = app_state.event_bus .subscribe(&format!("flow_execution:{}", execution_id)) .await; // 发送事件到客户端 tokio::spawn(async move { while let Ok(event) = event_stream.recv().await { let message = serde_json::to_string(&event).unwrap(); if sender.send(Message::Text(message)).await.is_err() { break; } } }); // 处理客户端消息 while let Some(msg) = receiver.next().await { match msg { Ok(Message::Text(text)) => { // 处理客户端命令 if let Ok(command) = serde_json::from_str::(&text) { handle_ws_command(command, &app_state).await; } } Ok(Message::Close(_)) => break, _ => {} } } } ``` ## 系统管理路由 (system.rs) ### 路由定义 ```rust pub fn routes() -> Router { Router::new() .route("/info", get(get_system_info)) .route("/status", get(get_system_status)) .route("/health", get(health_check)) .route("/metrics", get(get_metrics)) .route("/config", get(get_system_config).put(update_system_config)) .route("/cache/clear", post(clear_cache)) .route("/backup", post(create_backup)) .route("/restore", post(restore_backup)) } ``` ### 接口实现 #### 系统状态监控 ```rust /// GET /api/system/status /// 获取系统运行状态 pub async fn get_system_status( State(app_state): State, Extension(current_user): Extension, ) -> Result>, AppError> { // 权限检查 permission_service::check_user_permission( &app_state.db, ¤t_user.id, "system", "read", ).await?; // 获取系统状态 let status = system_service::get_system_status( &app_state.db, &app_state.redis, ).await?; Ok(Json(ApiResponse::success(status))) } ``` #### 健康检查 ```rust /// GET /health /// 系统健康检查 pub async fn health_check( State(app_state): State, ) -> Result, AppError> { let mut checks = HashMap::new(); // 数据库健康检查 let db_health = system_service::check_database_health(&app_state.db).await .unwrap_or(HealthStatus::Unhealthy); checks.insert("database".to_string(), db_health); // Redis 健康检查 let redis_health = system_service::check_redis_health(&app_state.redis).await .unwrap_or(HealthStatus::Unhealthy); checks.insert("redis".to_string(), redis_health); // 整体健康状态 let overall_status = if checks.values().all(|&status| status == HealthStatus::Healthy) { HealthStatus::Healthy } else { HealthStatus::Unhealthy }; Ok(Json(HealthCheckResp { status: overall_status, timestamp: Utc::now(), checks, })) } ``` ## 响应格式 ### 统一响应结构 ```rust #[derive(Debug, Serialize)] pub struct ApiResponse { pub success: bool, pub data: Option, pub message: String, pub code: u32, pub timestamp: DateTime, } impl ApiResponse { pub fn success(data: T) -> Self { Self { success: true, data: Some(data), message: "操作成功".to_string(), code: 200, timestamp: Utc::now(), } } pub fn error(message: String, code: u32) -> ApiResponse<()> { ApiResponse { success: false, data: None, message, code, timestamp: Utc::now(), } } } ``` ### 分页响应结构 ```rust #[derive(Debug, Serialize)] pub struct PageResp { pub items: Vec, pub total: u64, pub page: u64, pub page_size: u64, pub total_pages: u64, pub has_next: bool, pub has_prev: bool, } ``` ## 错误处理 ### 错误类型定义 ```rust #[derive(Debug, thiserror::Error)] pub enum AppError { #[error("请求参数错误: {0}")] BadRequest(String), #[error("未授权访问")] Unauthorized, #[error("权限不足: {0}")] Forbidden(String), #[error("资源不存在: {0}")] NotFound(String), #[error("请求冲突: {0}")] Conflict(String), #[error("请求过于频繁")] TooManyRequests, #[error("内部服务器错误: {0}")] InternalServerError(String), } ``` ### 错误响应处理 ```rust impl IntoResponse for AppError { fn into_response(self) -> Response { let (status, code, message) = match self { AppError::BadRequest(msg) => (StatusCode::BAD_REQUEST, 400, msg), AppError::Unauthorized => (StatusCode::UNAUTHORIZED, 401, "未授权访问".to_string()), AppError::Forbidden(msg) => (StatusCode::FORBIDDEN, 403, msg), AppError::NotFound(msg) => (StatusCode::NOT_FOUND, 404, msg), AppError::Conflict(msg) => (StatusCode::CONFLICT, 409, msg), AppError::TooManyRequests => (StatusCode::TOO_MANY_REQUESTS, 429, "请求过于频繁".to_string()), AppError::InternalServerError(msg) => (StatusCode::INTERNAL_SERVER_ERROR, 500, msg), }; let response = ApiResponse::<()>::error(message, code); (status, Json(response)).into_response() } } ``` ## 中间件 ### 认证中间件 ```rust #[derive(Clone)] pub struct AuthMiddleware { jwt_secret: String, } impl AuthMiddleware { pub fn new(jwt_secret: String) -> Self { Self { jwt_secret } } } #[async_trait] impl FromRequestParts for CurrentUser where S: Send + Sync, { type Rejection = AppError; async fn from_request_parts( parts: &mut Parts, state: &S, ) -> Result { // 从请求头获取 Token let auth_header = parts.headers .get(AUTHORIZATION) .and_then(|header| header.to_str().ok()) .ok_or(AppError::Unauthorized)?; // 验证 Bearer Token 格式 let token = auth_header .strip_prefix("Bearer ") .ok_or(AppError::Unauthorized)?; // 验证 JWT Token let claims = jwt::verify_token(token, &jwt_secret) .map_err(|_| AppError::Unauthorized)?; // 获取用户信息 let app_state = parts.extensions.get::() .ok_or(AppError::InternalServerError("应用状态未找到".to_string()))?; let user = user_service::get_user_by_id(&app_state.db, &claims.user_id).await .map_err(|e| AppError::InternalServerError(e.to_string()))? .ok_or(AppError::Unauthorized)?; Ok(CurrentUser { id: user.id, username: user.username, roles: user.roles, }) } } ``` ### 权限中间件 ```rust pub struct PermissionMiddleware { resource: String, action: String, } impl PermissionMiddleware { pub fn new(resource: &str, action: &str) -> Self { Self { resource: resource.to_string(), action: action.to_string(), } } } #[async_trait] impl FromRequestParts for PermissionGuard where S: Send + Sync, { type Rejection = AppError; async fn from_request_parts( parts: &mut Parts, state: &S, ) -> Result { // 获取当前用户 let current_user = CurrentUser::from_request_parts(parts, state).await?; // 获取权限要求 let permission_req = parts.extensions.get::() .ok_or(AppError::InternalServerError("权限要求未设置".to_string()))?; // 检查权限 let app_state = parts.extensions.get::() .ok_or(AppError::InternalServerError("应用状态未找到".to_string()))?; let has_permission = permission_service::check_user_permission( &app_state.db, ¤t_user.id, &permission_req.resource, &permission_req.action, ).await .map_err(|e| AppError::InternalServerError(e.to_string()))?; if !has_permission { return Err(AppError::Forbidden("权限不足".to_string())); } Ok(PermissionGuard { current_user }) } } ``` ### 请求日志中间件 ```rust pub struct RequestLogMiddleware; impl Layer for RequestLogMiddleware { type Service = RequestLogService; fn layer(&self, inner: S) -> Self::Service { RequestLogService { inner } } } pub struct RequestLogService { inner: S, } impl Service> for RequestLogService where S: Service, Response = Response> + Clone + Send + 'static, S::Future: Send + 'static, { type Response = S::Response; type Error = S::Error; type Future = Pin> + Send>>; fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { self.inner.poll_ready(cx) } fn call(&mut self, request: Request) -> Self::Future { let start_time = Instant::now(); let method = request.method().clone(); let uri = request.uri().clone(); let user_agent = request.headers() .get(USER_AGENT) .and_then(|h| h.to_str().ok()) .unwrap_or("") .to_string(); let future = self.inner.call(request); Box::pin(async move { let response = future.await?; let duration = start_time.elapsed(); info!( target = "udmin", method = %method, uri = %uri, status = %response.status(), duration_ms = %duration.as_millis(), user_agent = %user_agent, "http.request.completed" ); Ok(response) }) } } ``` ## API 文档 ### OpenAPI 集成 ```rust use utoipa::{OpenApi, ToSchema}; use utoipa_swagger_ui::SwaggerUi; #[derive(OpenApi)] #[openapi( paths( auth::login, auth::logout, user::list_users, user::create_user, flow::execute_flow, ), components( schemas( LoginReq, LoginResp, UserDoc, CreateUserReq, ExecuteFlowReq, ExecutionResult, ) ), tags( (name = "auth", description = "认证相关接口"), (name = "user", description = "用户管理接口"), (name = "flow", description = "流程管理接口"), ) )] struct ApiDoc; pub fn create_swagger_routes() -> Router { Router::new() .merge(SwaggerUi::new("/swagger-ui").url("/api-docs/openapi.json", ApiDoc::openapi())) } ``` ### 接口文档注解 ```rust #[utoipa::path( post, path = "/auth/login", tag = "auth", summary = "用户登录", description = "用户名密码登录,返回 JWT Token", request_body = LoginReq, responses( (status = 200, description = "登录成功", body = ApiResponse), (status = 400, description = "请求参数错误", body = ApiResponse<()>), (status = 401, description = "用户名或密码错误", body = ApiResponse<()>), ) )] pub async fn login( State(app_state): State, Json(req): Json, ) -> Result>, AppError> { // 实现代码... } ``` ## 性能优化 ### 请求缓存 ```rust pub struct CacheMiddleware { redis: RedisConnection, ttl: Duration, } impl CacheMiddleware { pub fn new(redis: RedisConnection, ttl: Duration) -> Self { Self { redis, ttl } } async fn get_cache_key(&self, request: &Request) -> String { let method = request.method(); let uri = request.uri(); let query = uri.query().unwrap_or(""); format!("api_cache:{}:{}:{}", method, uri.path(), query) } } ``` ### 响应压缩 ```rust pub fn create_compression_layer() -> CompressionLayer { CompressionLayer::new() .gzip(true) .br(true) .deflate(true) .quality(CompressionLevel::Default) } ``` ### 请求限流 ```rust pub struct RateLimitMiddleware { redis: RedisConnection, max_requests: u32, window: Duration, } impl RateLimitMiddleware { pub async fn check_rate_limit( &self, client_id: &str, ) -> Result { let key = format!("rate_limit:{}", client_id); let current_count: u32 = self.redis.get(&key).await.unwrap_or(0); if current_count >= self.max_requests { return Ok(false); } let _: () = self.redis.incr(&key, 1).await?; let _: () = self.redis.expire(&key, self.window.as_secs() as usize).await?; Ok(true) } } ``` ## 测试策略 ### 单元测试 ```rust #[cfg(test)] mod tests { use super::*; use axum_test::TestServer; #[tokio::test] async fn test_login_success() { let app = create_test_app().await; let server = TestServer::new(app).unwrap(); let response = server .post("/auth/login") .json(&json!({ "username": "admin", "password": "password123" })) .await; response.assert_status_ok(); let body: ApiResponse = response.json(); assert!(body.success); assert!(body.data.is_some()); } #[tokio::test] async fn test_login_invalid_credentials() { let app = create_test_app().await; let server = TestServer::new(app).unwrap(); let response = server .post("/auth/login") .json(&json!({ "username": "admin", "password": "wrong_password" })) .await; response.assert_status(StatusCode::UNAUTHORIZED); } } ``` ### 集成测试 ```rust #[tokio::test] async fn test_user_crud_flow() { let app = create_test_app().await; let server = TestServer::new(app).unwrap(); // 登录获取 Token let login_response = server .post("/auth/login") .json(&json!({ "username": "admin", "password": "password123" })) .await; let login_body: ApiResponse = login_response.json(); let token = login_body.data.unwrap().token; // 创建用户 let create_response = server .post("/api/users") .add_header(AUTHORIZATION, format!("Bearer {}", token)) .json(&json!({ "username": "test_user", "password": "password123", "email": "test@example.com" })) .await; create_response.assert_status_ok(); let create_body: ApiResponse = create_response.json(); let user_id = create_body.data.unwrap().id; // 获取用户 let get_response = server .get(&format!("/api/users/{}", user_id)) .add_header(AUTHORIZATION, format!("Bearer {}", token)) .await; get_response.assert_status_ok(); // 删除用户 let delete_response = server .delete(&format!("/api/users/{}", user_id)) .add_header(AUTHORIZATION, format!("Bearer {}", token)) .await; delete_response.assert_status_ok(); } ``` ## 最佳实践 ### 路由设计 - **RESTful 风格**: 遵循 REST API 设计原则 - **资源命名**: 使用复数名词表示资源 - **HTTP 方法**: 正确使用 GET、POST、PUT、DELETE - **状态码**: 返回合适的 HTTP 状态码 ### 参数验证 - **输入验证**: 使用 validator 进行参数验证 - **类型安全**: 使用强类型结构体 - **错误信息**: 提供清晰的验证错误信息 - **安全过滤**: 过滤恶意输入 ### 错误处理 - **统一格式**: 使用统一的错误响应格式 - **错误分类**: 合理分类不同类型的错误 - **日志记录**: 记录详细的错误日志 - **用户友好**: 提供用户友好的错误信息 ### 安全考虑 - **认证授权**: 实现完善的认证授权机制 - **输入验证**: 严格验证所有输入参数 - **HTTPS**: 在生产环境使用 HTTPS - **CORS**: 正确配置 CORS 策略