关于 actix-web
面向使用 Rust 和 Actix-web 构建 Web 应用的开发者的核心知识技能,提供设置示例,以及路由、提取器、状态和中间件参考。
主要功能
- 01设置 Actix-web 应用
- 02使用宏定义路由
- 03使用路径、查询和 JSON 提取器
- 04管理共享应用状态
- 05应用内置日志和压缩中间件
- 06添加健康检查和就绪端点
适用场景
- 01创建 Rust HTTP 路由和处理器
- 02解析请求参数和 JSON 请求体
- 03在应用处理器间共享状态
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ claude-dev-suite/ claude-dev-suite --skill actix-web安装后在 Claude Code 中输入/actix-web确认已加载。
附带文件advanced.md
详细介绍
Actix-web 核心知识
完整参考:自定义计时中间件、身份验证中间件、自定义错误类型、WebSocket actor 和优雅关闭模式,请参阅 advanced.md。
深入了解:使用
mcp__documentation__fetch_docs,并将技术指定为actix-web,获取全面的文档。
基本设置
# Cargo.toml
[dependencies]
actix-web = "4"
actix-rt = "2"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
tokio = { version = "1", features = ["full"] }
use actix_web::{web, App, HttpServer, HttpResponse, Responder};
async fn hello() -> impl Responder {
HttpResponse::Ok().body("Hello, World!")
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.route("/", web::get().to(hello))
})
.bind("127.0.0.1:8080")?
.run()
.await
}
路由宏
use actix_web::{get, post, web, HttpResponse, Responder};
#[get("/users/{id}")]
async fn get_user(path: web::Path<u32>) -> impl Responder {
let id = path.into_inner();
HttpResponse::Ok().json(serde_json::json!({ "id": id }))
}
#[post("/users")]
async fn create_user(body: web::Json<CreateUser>) -> impl Responder {
HttpResponse::Created().json(body.into_inner())
}
// Register with App
App::new()
.service(get_user)
.service(create_user)
提取器
| 提取器 | 用途 |
|---|---|
web::Path<T> | URL 路径参数 |
web::Query<T> | 查询字符串 |
web::Json<T> | JSON 请求体 |
web::Form<T> | 表单数据 |
web::Data<T> | 应用状态 |
应用状态
struct AppState {
db_pool: Pool<Postgres>,
}
#[get("/users")]
async fn list_users(data: web::Data<AppState>) -> impl Responder {
let users = sqlx::query_as!(User, "SELECT * FROM users")
.fetch_all(&data.db_pool)
.await?;
HttpResponse::Ok().json(users)
}
HttpServer::new(move || {
App::new()
.app_data(web::Data::new(state.clone()))
.service(list_users)
})
内置中间件
use actix_web::middleware::{Logger, Compress, NormalizePath};
App::new()
.wrap(Logger::default())
.wrap(Compress::default())
.wrap(NormalizePath::trim())
健康检查
#[get("/health")]
async fn health() -> impl Responder {
HttpResponse::Ok().json(serde_json::json!({ "status": "healthy" }))
}
#[get("/ready")]
async fn ready(data: web::Data<AppState>) -> impl Responder {
match data.db_pool.acquire().await {
Ok(_) => HttpResponse::Ok().json(serde_json::json!({
"status": "ready",
"database": "connected"
})),
Err(_) => HttpResponse::ServiceUnavailable().json(serde_json::json!({
"status": "not ready"
})),
}
}
不适用此技能的情况
- Axum 项目 - Axum 与 Tower 生态系统配合更为便捷
- Rocket 项目 - Rocket 提供更好的编译时保证
- Warp 项目 - Warp 使用过滤器进行组合
- 简单的 CLI 工具 - 不需要 Web 服务
- 嵌入式系统 - 对资源受限的设备来说过于沉重
反模式
| 反模式 | 不良影响 | 解决方案 |
|---|---|---|
每个请求都调用 .clone() | 性能开销 | 使用 web::Data<Arc<T>> 共享状态 |
| 在异步处理程序中执行阻塞 I/O | 阻塞执行器线程 | 对阻塞操作使用 web::block() |
| 不使用提取器 | 手动解析容易出错 | 使用 Json、Path、Query 提取器 |
缺少 #[actix_web::main] | 需要手动设置运行时 | 使用宏简化设置 |
| 全局可变状态 | 数据竞争 | 在 web::Data 中使用 Mutex 或 RwLock |
| 没有自定义错误类型 | 错误消息过于笼统 | 实现 ResponseError trait |
快速故障排除
| 问题 | 诊断 | 修复方法 |
|---|---|---|
| “Cannot move out of borrowed content” | 所有权问题 | 克隆数据或使用 web::Data<Arc<T>> |
| 找不到处理程序(404) | 路由未注册 | 检查 .service() 或 .route() 调用 |
| JSON 解析失败 | Content-Type 错误 | 确保客户端发送 Content-Type: application/json |
| 性能缓慢 | 阻塞 I/O | 将阻塞代码封装在 web::block() 中 |
| WebSocket 连接关闭 | 缺少 ping/pong | 实现心跳机制 |
| 无法访问状态 | 未添加到应用中 | 构建应用时使用 .app_data() |
检查清单
- 正确配置 CORS
- 身份验证中间件
- 自定义错误处理
- 请求日志记录(Logger 中间件)
- 健康检查/就绪状态端点
- 优雅关闭
- 数据库连接池
- 输入验证
- 速率限制(actix-ratelimit)
参考文档
评论
支持 Markdown