actix-web
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseActix-web Core Knowledge
Actix-web 核心知识
Full Reference: See advanced.md for custom timing middleware, authentication middleware, custom error types, WebSocket actors, and graceful shutdown patterns.
Deep Knowledge: Usewith technology:mcp__documentation__fetch_docsfor comprehensive documentation.actix-web
完整参考:查看advanced.md了解自定义计时中间件、认证中间件、自定义错误类型、WebSocket actor 和平滑关闭模式。
深度知识:调用并指定技术为mcp__documentation__fetch_docs,即可获取完整文档。actix-web
Basic Setup
基础配置
toml
undefinedtoml
undefinedCargo.toml
Cargo.toml
[dependencies]
actix-web = "4"
actix-rt = "2"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
tokio = { version = "1", features = ["full"] }
```rust
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
}[dependencies]
actix-web = "4"
actix-rt = "2"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
tokio = { version = "1", features = ["full"] }
```rust
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
}Route Macros
路由宏
rust
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)rust
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())
}
// 注册到App
App::new()
.service(get_user)
.service(create_user)Extractors
提取器
| Extractor | Purpose |
|---|---|
| URL path parameters |
| Query string |
| JSON body |
| Form data |
| Application state |
| 提取器 | 用途 |
|---|---|
| URL路径参数 |
| 查询字符串 |
| JSON请求体 |
| 表单数据 |
| 应用状态 |
Application State
应用状态
rust
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)
})rust
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)
})Built-in Middleware
内置中间件
rust
use actix_web::middleware::{Logger, Compress, NormalizePath};
App::new()
.wrap(Logger::default())
.wrap(Compress::default())
.wrap(NormalizePath::trim())rust
use actix_web::middleware::{Logger, Compress, NormalizePath};
App::new()
.wrap(Logger::default())
.wrap(Compress::default())
.wrap(NormalizePath::trim())Health Checks
健康检查
rust
#[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"
})),
}
}rust
#[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"
})),
}
}When NOT to Use This Skill
本技能不适用场景
- Axum projects - Axum is more ergonomic with Tower ecosystem
- Rocket projects - Rocket has better compile-time guarantees
- Warp projects - Warp uses filters for composition
- Simple CLI tools - No web server needed
- Embedded systems - Too heavy for resource-constrained devices
- Axum项目 - Axum与Tower生态的适配更符合人体工学
- Rocket项目 - Rocket有更优的编译时校验能力
- Warp项目 - Warp采用过滤器实现逻辑组合
- 简单CLI工具 - 无需Web服务器
- 嵌入式系统 - 对资源受限设备来说过于沉重
Anti-Patterns
反模式
| Anti-Pattern | Why It's Bad | Solution |
|---|---|---|
| Performance overhead | Use |
| Blocking I/O in async handlers | Blocks executor threads | Use |
| Not using extractors | Manual parsing is error-prone | Use |
Missing | Manual runtime setup | Use macro for simple setup |
| Global mutable state | Data races | Use |
| No custom error types | Generic error messages | Implement |
| 反模式 | 弊端 | 解决方案 |
|---|---|---|
每个请求都执行 | 性能开销 | 使用 |
| 异步处理器中存在阻塞I/O | 阻塞执行器线程 | 调用 |
| 不使用提取器 | 手动解析易出错 | 使用 |
缺少 | 需手动配置运行时 | 使用宏实现简易配置 |
| 全局可变状态 | 数据竞争 | 结合 |
| 无自定义错误类型 | 错误提示泛化 | 实现 |
Quick Troubleshooting
快速故障排查
| Problem | Diagnosis | Fix |
|---|---|---|
| "Cannot move out of borrowed content" | Ownership issue | Clone data or use |
| Handler not found (404) | Route not registered | Check |
| JSON parsing fails | Wrong content-type | Ensure client sends |
| Slow performance | Blocking I/O | Wrap blocking code in |
| WebSocket connection closes | Missing ping/pong | Implement heartbeat mechanism |
| State not accessible | Not added to app | Use |
| 问题 | 诊断 | 修复方案 |
|---|---|---|
| "Cannot move out of borrowed content" | 所有权问题 | 克隆数据或使用 |
| 处理器未找到(404) | 路由未注册 | 检查 |
| JSON解析失败 | 错误的content-type | 确保客户端发送 |
| 性能低下 | 阻塞I/O | 将阻塞代码包裹在 |
| WebSocket连接断开 | 缺少ping/pong机制 | 实现心跳机制 |
| 状态无法访问 | 未添加到应用配置 | 构建App时调用 |
Checklist
检查清单
- CORS properly configured
- Authentication middleware
- Custom error handling
- Request logging (Logger middleware)
- Health/readiness endpoints
- Graceful shutdown
- Connection pooling for database
- Input validation
- Rate limiting (actix-ratelimit)
- CORS配置正确
- 认证中间件已配置
- 自定义错误处理已实现
- 请求日志(Logger中间件)已开启
- 健康/就绪端点已配置
- 平滑关闭功能已实现
- 数据库连接池已配置
- 输入校验已实现
- 限流功能(actix-ratelimit)已配置
Reference Documentation
参考文档
- Extractors
- Middleware
- 提取器
- 中间件