actix-web

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Actix-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: Use
mcp__documentation__fetch_docs
with technology:
actix-web
for comprehensive documentation.
完整参考:查看advanced.md了解自定义计时中间件、认证中间件、自定义错误类型、WebSocket actor 和平滑关闭模式。
深度知识:调用
mcp__documentation__fetch_docs
并指定技术为
actix-web
,即可获取完整文档。

Basic Setup

基础配置

toml
undefined
toml
undefined

Cargo.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

提取器

ExtractorPurpose
web::Path<T>
URL path parameters
web::Query<T>
Query string
web::Json<T>
JSON body
web::Form<T>
Form data
web::Data<T>
Application state
提取器用途
web::Path<T>
URL路径参数
web::Query<T>
查询字符串
web::Json<T>
JSON请求体
web::Form<T>
表单数据
web::Data<T>
应用状态

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-PatternWhy It's BadSolution
.clone()
on every request
Performance overheadUse
web::Data<Arc<T>>
for shared state
Blocking I/O in async handlersBlocks executor threadsUse
web::block()
for blocking operations
Not using extractorsManual parsing is error-proneUse
Json
,
Path
,
Query
extractors
Missing
#[actix_web::main]
Manual runtime setupUse macro for simple setup
Global mutable stateData racesUse
Mutex
or
RwLock
with
web::Data
No custom error typesGeneric error messagesImplement
ResponseError
trait
反模式弊端解决方案
每个请求都执行
.clone()
性能开销使用
web::Data<Arc<T>>
管理共享状态
异步处理器中存在阻塞I/O阻塞执行器线程调用
web::block()
处理阻塞操作
不使用提取器手动解析易出错使用
Json
Path
Query
等提取器
缺少
#[actix_web::main]
注解
需手动配置运行时使用宏实现简易配置
全局可变状态数据竞争结合
web::Data
使用
Mutex
RwLock
无自定义错误类型错误提示泛化实现
ResponseError
trait

Quick Troubleshooting

快速故障排查

ProblemDiagnosisFix
"Cannot move out of borrowed content"Ownership issueClone data or use
web::Data<Arc<T>>
Handler not found (404)Route not registeredCheck
.service()
or
.route()
calls
JSON parsing failsWrong content-typeEnsure client sends
Content-Type: application/json
Slow performanceBlocking I/OWrap blocking code in
web::block()
WebSocket connection closesMissing ping/pongImplement heartbeat mechanism
State not accessibleNot added to appUse
.app_data()
when building app
问题诊断修复方案
"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时调用
.app_data()
注册状态

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
  • 提取器
  • 中间件