# Rust REST API Server - 详细实现指南 ## 阶段 1: 项目初始化和基础设置 ### 1.1 创建项目和基础配置 **目标**: 建立 Rust 项目基础结构和依赖管理 **具体步骤**: 1. 使用 `cargo new rust-user-api --bin` 创建新项目 2. 配置 `Cargo.toml` 文件,添加必要依赖 3. 创建基础目录结构 4. 设置开发环境配置 **Cargo.toml 配置**: ```toml [package] name = "rust-user-api" version = "0.1.0" edition = "2021" [dependencies] # Web 框架 axum = "0.7" tokio = { version = "1.0", features = ["full"] } # 序列化 serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" # 时间处理 chrono = { version = "0.4", features = ["serde"] } # UUID 生成 uuid = { version = "1.0", features = ["v4", "serde"] } # 环境变量 dotenv = "0.15" # 日志 tracing = "0.1" tracing-subscriber = "0.3" # HTTP 客户端(用于测试) [dev-dependencies] reqwest = { version = "0.11", features = ["json"] } ``` **学习重点**: - Cargo 包管理器的使用 - Rust 项目结构约定 - 依赖版本管理和特性选择 --- ## 阶段 2: 创建基本的 HTTP Server 和路由结构 ### 2.1 实现基础 HTTP 服务器 **目标**: 创建一个能够响应 HTTP 请求的基础服务器 **核心文件**: - `src/main.rs` - 应用入口点 - `src/lib.rs` - 库入口 - `src/routes/mod.rs` - 路由配置 **main.rs 实现**: ```rust use axum::{ routing::get, Router, response::Json, }; use serde_json::{json, Value}; use std::net::SocketAddr; use tracing_subscriber; #[tokio::main] async fn main() { // 初始化日志 tracing_subscriber::init(); // 创建路由 let app = Router::new() .route("/", get(root)) .route("/health", get(health_check)); // 启动服务器 let addr = SocketAddr::from(([127, 0, 0, 1], 3000)); println!("Server running on http://{}", addr); axum::Server::bind(&addr) .serve(app.into_make_service()) .await .unwrap(); } async fn root() -> Json { Json(json!({ "message": "Welcome to Rust User API", "version": "0.1.0" })) } async fn health_check() -> Json { Json(json!({ "status": "healthy", "timestamp": chrono::Utc::now() })) } ``` **学习重点**: - Axum 框架基础概念 - 异步编程 (`async/await`) - 路由定义和处理器函数 - JSON 响应处理 ### 2.2 模块化路由结构 **routes/mod.rs 实现**: ```rust use axum::{Router, routing::get}; use crate::handlers; pub fn create_routes() -> Router { Router::new() .route("/", get(handlers::root)) .route("/health", get(handlers::health_check)) .nest("/api", api_routes()) } fn api_routes() -> Router { Router::new() .route("/users", get(handlers::user::list_users)) // 后续添加更多路由 } ``` **学习重点**: - 模块系统和代码组织 - 路由嵌套和分组 - 处理器函数的分离 --- ## 阶段 3: 实现用户数据模型和内存存储 ### 3.1 定义数据模型 **目标**: 创建类型安全的数据模型和序列化支持 **models/user.rs 实现**: ```rust use serde::{Deserialize, Serialize}; use chrono::{DateTime, Utc}; use uuid::Uuid; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct User { pub id: Uuid, pub username: String, pub email: String, pub password_hash: String, pub created_at: DateTime, pub updated_at: DateTime, } #[derive(Debug, Serialize)] pub struct UserResponse { pub id: Uuid, pub username: String, pub email: String, pub created_at: DateTime, } #[derive(Debug, Deserialize)] pub struct CreateUserRequest { pub username: String, pub email: String, pub password: String, } #[derive(Debug, Deserialize)] pub struct UpdateUserRequest { pub username: Option, pub email: Option, } impl From for UserResponse { fn from(user: User) -> Self { UserResponse { id: user.id, username: user.username, email: user.email, created_at: user.created_at, } } } ``` **学习重点**: - Rust 结构体定义 - Serde 序列化和反序列化 - 类型转换和 `From` trait - 可选字段处理 ### 3.2 实现内存存储 **storage/memory.rs 实现**: ```rust use std::collections::HashMap; use std::sync::{Arc, RwLock}; use uuid::Uuid; use crate::models::user::User; pub type UserStorage = Arc>>; #[derive(Clone)] pub struct MemoryUserStore { users: UserStorage, } impl MemoryUserStore { pub fn new() -> Self { Self { users: Arc::new(RwLock::new(HashMap::new())), } } pub async fn create_user(&self, user: User) -> Result { let mut users = self.users.write().unwrap(); users.insert(user.id, user.clone()); Ok(user) } pub async fn get_user(&self, id: &Uuid) -> Option { let users = self.users.read().unwrap(); users.get(id).cloned() } pub async fn list_users(&self) -> Vec { let users = self.users.read().unwrap(); users.values().cloned().collect() } pub async fn update_user(&self, id: &Uuid, updated_user: User) -> Option { let mut users = self.users.write().unwrap(); users.insert(*id, updated_user.clone()); Some(updated_user) } pub async fn delete_user(&self, id: &Uuid) -> bool { let mut users = self.users.write().unwrap(); users.remove(id).is_some() } } ``` **学习重点**: - HashMap 数据结构 - 线程安全 (`Arc>`) - 异步方法定义 - 错误处理基础 --- ## 阶段 4: 实现用户 CRUD API 端点 ### 4.1 创建处理器函数 **handlers/user.rs 实现**: ```rust use axum::{ extract::{Path, State}, http::StatusCode, response::Json, Json as RequestJson, }; use uuid::Uuid; use chrono::Utc; use crate::models::user::{User, UserResponse, CreateUserRequest, UpdateUserRequest}; use crate::storage::memory::MemoryUserStore; pub async fn create_user( State(store): State, RequestJson(payload): RequestJson, ) -> Result<(StatusCode, Json), StatusCode> { let user = User { id: Uuid::new_v4(), username: payload.username, email: payload.email, password_hash: hash_password(&payload.password), created_at: Utc::now(), updated_at: Utc::now(), }; match store.create_user(user).await { Ok(user) => Ok((StatusCode::CREATED, Json(user.into()))), Err(_) => Err(StatusCode::INTERNAL_SERVER_ERROR), } } pub async fn get_user( State(store): State, Path(id): Path, ) -> Result, StatusCode> { match store.get_user(&id).await { Some(user) => Ok(Json(user.into())), None => Err(StatusCode::NOT_FOUND), } } pub async fn list_users( State(store): State, ) -> Json> { let users = store.list_users().await; let responses: Vec = users.into_iter().map(|u| u.into()).collect(); Json(responses) } pub async fn update_user( State(store): State, Path(id): Path, RequestJson(payload): RequestJson, ) -> Result, StatusCode> { match store.get_user(&id).await { Some(mut user) => { if let Some(username) = payload.username { user.username = username; } if let Some(email) = payload.email { user.email = email; } user.updated_at = Utc::now(); match store.update_user(&id, user).await { Some(updated_user) => Ok(Json(updated_user.into())), None => Err(StatusCode::INTERNAL_SERVER_ERROR), } } None => Err(StatusCode::NOT_FOUND), } } pub async fn delete_user( State(store): State, Path(id): Path, ) -> StatusCode { if store.delete_user(&id).await { StatusCode::NO_CONTENT } else { StatusCode::NOT_FOUND } } fn hash_password(password: &str) -> String { // 简单的密码哈希(生产环境应使用 bcrypt) format!("hashed_{}", password) } ``` **学习重点**: - Axum 提取器 (`State`, `Path`, `Json`) - HTTP 状态码处理 - 错误处理和 `Result` 类型 - 异步处理器函数 ### 4.2 完整路由配置 **更新 routes/mod.rs**: ```rust use axum::{ Router, routing::{get, post, put, delete}, }; use crate::handlers; use crate::storage::memory::MemoryUserStore; pub fn create_routes(store: MemoryUserStore) -> Router { Router::new() .route("/", get(handlers::root)) .route("/health", get(handlers::health_check)) .nest("/api", api_routes()) .with_state(store) } fn api_routes() -> Router { Router::new() .route("/users", get(handlers::user::list_users).post(handlers::user::create_user)) .route("/users/:id", get(handlers::user::get_user) .put(handlers::user::update_user) .delete(handlers::user::delete_user) ) } ``` **学习重点**: - 状态管理和依赖注入 - RESTful 路由设计 - HTTP 方法映射 --- ## 阶段 5: 添加请求验证和错误处理 ### 5.1 自定义错误类型 **utils/errors.rs 实现**: ```rust use axum::{ http::StatusCode, response::{IntoResponse, Response}, Json, }; use serde_json::json; #[derive(Debug)] pub enum ApiError { ValidationError(String), NotFound(String), InternalError(String), Unauthorized, } impl IntoResponse for ApiError { fn into_response(self) -> Response { let (status, error_message) = match self { ApiError::ValidationError(msg) => (StatusCode::BAD_REQUEST, msg), ApiError::NotFound(msg) => (StatusCode::NOT_FOUND, msg), ApiError::InternalError(msg) => (StatusCode::INTERNAL_SERVER_ERROR, msg), ApiError::Unauthorized => (StatusCode::UNAUTHORIZED, "Unauthorized".to_string()), }; let body = Json(json!({ "error": error_message, "status": status.as_u16() })); (status, body).into_response() } } ``` ### 5.2 请求验证 **添加验证逻辑**: ```rust use validator::{Validate, ValidationError}; #[derive(Debug, Deserialize, Validate)] pub struct CreateUserRequest { #[validate(length(min = 3, max = 50))] pub username: String, #[validate(email)] pub email: String, #[validate(length(min = 8))] pub password: String, } // 在处理器中使用验证 pub async fn create_user( State(store): State, RequestJson(payload): RequestJson, ) -> Result<(StatusCode, Json), ApiError> { // 验证请求数据 payload.validate() .map_err(|e| ApiError::ValidationError(format!("Validation failed: {:?}", e)))?; // ... 其余逻辑 } ``` **学习重点**: - 自定义错误类型 - `IntoResponse` trait 实现 - 请求验证和数据校验 - 错误传播 (`?` 操作符) --- ## 阶段 6: 实现基础的身份认证 (JWT) ### 6.1 JWT 中间件 **middleware/auth.rs 实现**: ```rust use axum::{ extract::{Request, State}, http::{header, StatusCode}, middleware::Next, response::Response, }; use jsonwebtoken::{decode, encode, DecodingKey, EncodingKey, Header, Validation}; use serde::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize)] pub struct Claims { pub sub: String, // 用户ID pub exp: usize, // 过期时间 } pub async fn auth_middleware( mut req: Request, next: Next, ) -> Result { let auth_header = req.headers() .get(header::AUTHORIZATION) .and_then(|header| header.to_str().ok()); let auth_header = if let Some(auth_header) = auth_header { auth_header } else { return Err(StatusCode::UNAUTHORIZED); }; if let Some(token) = auth_header.strip_prefix("Bearer ") { match verify_jwt(token) { Ok(claims) => { req.extensions_mut().insert(claims); Ok(next.run(req).await) } Err(_) => Err(StatusCode::UNAUTHORIZED), } } else { Err(StatusCode::UNAUTHORIZED) } } fn verify_jwt(token: &str) -> Result { let key = DecodingKey::from_secret("secret".as_ref()); let validation = Validation::default(); decode::(token, &key, &validation) .map(|data| data.claims) } pub fn create_jwt(user_id: &str) -> Result { let expiration = chrono::Utc::now() .checked_add_signed(chrono::Duration::hours(24)) .expect("valid timestamp") .timestamp() as usize; let claims = Claims { sub: user_id.to_string(), exp: expiration, }; let key = EncodingKey::from_secret("secret".as_ref()); encode(&Header::default(), &claims, &key) } ``` ### 6.2 登录端点 **添加认证处理器**: ```rust #[derive(Deserialize)] pub struct LoginRequest { pub username: String, pub password: String, } #[derive(Serialize)] pub struct LoginResponse { pub token: String, pub user: UserResponse, } pub async fn login( State(store): State, RequestJson(payload): RequestJson, ) -> Result, ApiError> { // 查找用户(简化版本,实际应该按用户名查找) let users = store.list_users().await; let user = users.into_iter() .find(|u| u.username == payload.username) .ok_or_else(|| ApiError::NotFound("User not found".to_string()))?; // 验证密码(简化版本) if user.password_hash != format!("hashed_{}", payload.password) { return Err(ApiError::Unauthorized); } // 生成 JWT let token = create_jwt(&user.id.to_string()) .map_err(|_| ApiError::InternalError("Failed to create token".to_string()))?; Ok(Json(LoginResponse { token, user: user.into(), })) } ``` **学习重点**: - JWT 概念和实现 - 中间件设计模式 - 请求扩展和状态传递 - 身份认证流程 --- ## 阶段 7: 添加 API 文档和测试用例 ### 7.1 集成测试 **tests/api_tests.rs 实现**: ```rust use reqwest; use serde_json::json; use tokio; #[tokio::test] async fn test_create_user() { let client = reqwest::Client::new(); let user_data = json!({ "username": "testuser", "email": "test@example.com", "password": "password123" }); let response = client .post("http://localhost:3000/api/users") .json(&user_data) .send() .await .expect("Failed to send request"); assert_eq!(response.status(), 201); let user: serde_json::Value = response.json().await.expect("Failed to parse JSON"); assert_eq!(user["username"], "testuser"); assert_eq!(user["email"], "test@example.com"); } #[tokio::test] async fn test_get_user() { // 首先创建用户,然后获取 // ... 测试逻辑 } ``` ### 7.2 API 文档 **docs/api.md**: ```markdown # User API Documentation ## Authentication All protected endpoints require a Bearer token in the Authorization header: ``` Authorization: Bearer ``` ## Endpoints ### POST /api/auth/login Login with username and password. **Request Body:** ```json { "username": "string", "password": "string" } ``` **Response:** ```json { "token": "jwt_token_string", "user": { "id": "uuid", "username": "string", "email": "string", "created_at": "timestamp" } } ``` ### GET /api/users Get all users (requires authentication). **Response:** ```json [ { "id": "uuid", "username": "string", "email": "string", "created_at": "timestamp" } ] ``` ``` **学习重点**: - 集成测试编写 - HTTP 客户端测试 - API 文档编写规范 - 测试驱动开发 --- ## 后续阶段概览 ### 阶段 8-12: 高级功能 - **数据库集成**: SQLite/PostgreSQL 集成,ORM 使用 - **高级功能**: 分页、搜索、过滤、排序 - **生产准备**: 配置管理、日志记录、错误监控 - **部署**: Docker 容器化、环境配置 每个阶段都建立在前一个阶段的基础上,确保学习的连续性和实用性。通过这种渐进式的方法,您将全面掌握 Rust web 开发的各个方面。