使用 Actix-web/Rocket 构建 REST API
使用 Actix-web 或 Rocket 等现代 Rust Web 框架开发 RESTful API,处理路由、请求和响应。
使用 Actix-web/Rocket 构建 REST API 是 CoddyKit 上的免费 Learn Rust Coding 课时。 这是第 1 节课,共 3 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Learn Rust Coding 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Learn Rust Coding 课程共包含 3 节课。
什么是 REST API?
REST,即 RE 表述性状态转移,是一种用于网络应用的架构风格。它定义了一组原则,用于规定 Web 服务应如何进行通信。
您可以将其理解为一组构建 Web 服务的指导原则:服务应当无状态、可缓存,并使用标准 HTTP 方法与资源进行交互。
- 资源:任何可以命名的对象,例如用户、产品或订单。
- URI:资源的唯一标识符(例如
/users/123)。 - HTTP 方法:对资源执行的标准操作(GET、POST、PUT、DELETE)。
为什么选择 Rust 构建 Web 服务?
Rust 为 Web 服务开发带来了独特优势,因此非常适合构建高性能且可靠的 API:
- 性能:Rust 的零成本抽象意味着代码非常高效,通常可以达到与 C/C++ 相当的水平。
- 内存安全:所有权系统可以防止空指针解引用和数据竞争等常见错误,从而带来更加稳健的服务。
- 并发:Rust 的 async/await 模型结合其安全保证,使构建并发 Web 服务变得更加安心。
- 可靠性:强大的类型系统和编译时检查可以尽早发现许多错误。
认识 Actix-web
在 Rust 中构建 Web 服务时,我们通常会使用框架。Actix-web 是一个功能强大、实用且速度极快的 Rust Web 框架。
它构建于 Actix(一个参与者框架)之上,但要有效使用 Actix-web,您不需要理解参与者。它专为异步操作而设计,非常适合处理大量并发 API 请求等受 I/O 限制的任务。
Actix-web 提供了路由、请求与响应处理、中间件等多种工具,大大简化了复杂 API 的创建过程。
项目设置与依赖项
首先,我们将创建一个新的 Rust 项目,并添加必要的依赖项。我们将使用 actix-web 作为框架,使用 serde 对 JSON 数据进行序列化和反序列化。
首先,创建一个新项目:
cargo new my_rest_api --bin
然后,将以下几行添加到 Cargo.toml 文件的 [dependencies] 部分:
[dependencies]
actix-web = "4"
serde = { version = "1.0", features = ["derive"] }
您的第一个 Actix-web 服务器
让我们编写一个最小化的 Actix-web 服务器。这段代码会建立基本结构,以监听 8080 端口上的传入 HTTP 请求。它目前还不会处理任何特定路由,但这是后续开发的基础。
#[actix_web::main] 宏会使我们的 async fn main 与 Actix-web 的运行时兼容。
use actix_web::{App, HttpServer};
#[actix_web::main]
async fn main() -> std::io::Result<()> {
println!("Server running at http://127.0.0.1:8080");
HttpServer::new(|| {
// Our application instance, where we'll add routes
App::new()
})
.bind(("127.0.0.1", 8080))? // Bind to an IP address and port
.run() // Start the server
.await // Await its completion
}定义 GET 路由
现在,让我们为服务器添加一个简单的路由。路由会将传入的 HTTP 请求路径和方法(例如 GET /hello)映射到特定的处理函数。
我们的处理函数 hello_world 只会返回一个字符串。web::get().to() 会将此处理函数注册为处理发往 /hello 路径的 GET 请求。
use actix_web::{web, App, HttpServer, Responder};
// A handler function that returns a simple string response
async fn hello_world() -> impl Responder {
"Hello, Actix-web!"
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
println!("Server running at http://127.0.0.1:8080");
HttpServer::new(|| {
App::new()
// Register our route: GET /hello maps to hello_world()
.route("/hello", web::get().to(hello_world))
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}用于动态路由的路径参数
API 通常需要处理 URL 中的动态部分,例如 ID 或名称。Actix-web 使用路径参数来捕获这些值。
我们在路由中定义一个占位符(例如 /{name})。在处理函数中,我们使用 web::Path<String>(或任何可以反序列化的其他类型)来提取该值。
use actix_web::{web, App, HttpServer, Responder};
// Handler function with a path parameter 'name'
async fn greet_name(name: web::Path<String>) -> impl Responder {
format!("Hello, {}!", name.into_inner())
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
println!("Server running at http://127.0.0.1:8080");
HttpServer::new(|| {
App::new()
// Route with a dynamic path segment for a name
.route("/greet/{name}", web::get().to(greet_name))
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}处理 POST 请求与 JSON
创建或更新资源时,我们使用 POST 或 PUT 请求,并通常将数据以 JSON 形式放在请求正文中发送。
使用 web::Json<T> 可以轻松处理 JSON。我们定义一个与预期 JSON 结构相匹配的 Rust struct,从 serde 派生 Deserialize,Actix-web 就会自动将传入的 JSON 解析为我们的结构体。
use actix_web::{web, App, HttpServer, Responder};
use serde::{Deserialize, Serialize};
// Define a struct to represent our incoming JSON data
#[derive(Deserialize, Serialize)]
struct User {
username: String,
email: String,
}
// Handler for POST requests that accepts a JSON User object
async fn create_user(user: web::Json<User>) -> impl Responder {
// In a real app, you'd save this user to a database
format!("User created: {} ({})", user.username, user.email)
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
println!("Server running at http://127.0.0.1:8080");
HttpServer::new(|| {
App::new()
// POST /users expects a JSON body and maps to create_user()
.route("/users", web::post().to(create_user))
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}使用状态构建简单 API
让我们结合所学内容,构建一个在内存中管理用户列表的小型 API。我们将使用 web::Data,在各个处理函数之间共享特定于应用程序的状态(即用户列表)。
std::sync::Mutex 用于确保多个并发请求能够安全地访问和修改我们的 Vec<User>。我们将提供 GET /users 和 POST /users 端点。
use actix_web::{web, App, HttpServer, Responder, HttpResponse};
use serde::{Deserialize, Serialize};
use std::sync::Mutex; // For shared mutable state
// Define a User struct that can be serialized/deserialized and cloned
#[derive(Deserialize, Serialize, Clone)]
struct User {
id: u32,
username: String,
email: String,
}
// Application state to hold our users and track next ID
struct AppState {
users: Mutex<Vec<User>>,
next_id: Mutex<u32>,
}
// Handler to get all users
async fn get_users(data: web::Data<AppState>) -> impl Responder {
let users = data.users.lock().unwrap(); // Acquire a lock
web::Json(users.clone()) // Return users as JSON
}
// Handler to create a new user
async fn create_user(
data: web::Data<AppState>,
new_user: web::Json<User>,
) -> impl Responder {
let mut users = data.users.lock().unwrap();
let mut next_id = data.next_id.lock().unwrap();
let user = User {
id: *next_id,
username: new_user.username.clone(),
email: new_user.email.clone(),
};
users.push(user.clone());
*next_id += 1; // Increment for the next user
HttpResponse::Created().json(user) // Return 201 Created status and user
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
println!("Server running at http://127.0.0.1:8080");
// Create shared application state
let app_state = web::Data::new(AppState {
users: Mutex::new(vec![]), // Initialize with an empty user list
next_id: Mutex::new(1), // Start IDs from 1
});
HttpServer::new(move || { // 'move' closure to capture app_state
App::new()
.app_data(app_state.clone()) // Register shared state with the app
.route("/users", web::get().to(get_users))
.route("/users", web::post().to(create_user))
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}API 概念快速检查
您已经学会了如何设置基本的 Actix-web 服务器,以及如何处理不同的 HTTP 请求。让我们 test 一下您的理解!
回顾与后续步骤
做得很好!您已经迈出了使用 Rust 和 Actix-web 构建 RESTful API 的第一步。
- 我们探讨了 REST API 的基础知识,以及 Rust 为什么非常适合这一领域。
- 您学会了如何设置基本的 Actix-web 项目。
- 我们介绍了如何定义 GET 和 POST 路由。
- 您了解了如何提取路径参数并处理 JSON 负载。
- 最后,您使用
web::Data构建了一个管理内存状态的简单 API。
接下来,您将深入学习数据库集成和稳健的错误处理,以构建更强大、更适合投入生产的 Web 服务!
常见问题解答
「使用 Actix-web/Rocket 构建 REST API」课时是免费的吗?
是的 — 「使用 Actix-web/Rocket 构建 REST API」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Learn Rust Coding 课程的其余内容,请升级到 CoddyKit PRO。 Learn Rust Coding 课程共包含 3 节课。
「使用 Actix-web/Rocket 构建 REST API」这节课中我会学到什么?
使用 Actix-web 或 Rocket 等现代 Rust Web 框架开发 RESTful API,处理路由、请求和响应。 你通过在浏览器中直接运行的动手代码来练习 Learn Rust Coding,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Learn Rust Coding 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Learn Rust Coding 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 3 节。
「使用 Actix-web/Rocket 构建 REST API」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Learn Rust Coding 课中编写并运行代码吗?
能。每节 Learn Rust Coding 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 使用 Actix-web/Rocket 构建 REST API
- 数据库集成(SQLx/Diesel)
- 身份验证与授权