内置中间件 #

Logger 中间件 #

基本用法 #

rust
use actix_web::{middleware, App, HttpServer};

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new()
            .wrap(middleware::Logger::default())
    })
    .bind("127.0.0.1:8080")?
    .run()
    .await
}

自定义日志格式 #

rust
App::new()
    .wrap(middleware::Logger::new("%a %{User-Agent}i"))

日志格式说明 #

占位符 说明
%a 客户端 IP 地址
%t 请求时间
%r 请求行
%s 响应状态码
%b 响应大小
%D 请求处理时间(毫秒)
%T 请求处理时间(秒)
%{name}i 请求头
%{name}o 响应头

完整示例 #

rust
use actix_web::{middleware, web, App, HttpResponse, HttpServer, Responder};

async fn index() -> impl Responder {
    HttpResponse::Ok().body("Hello")
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    std::env::set_var("RUST_LOG", "actix_web=info");
    env_logger::init();
    
    HttpServer::new(|| {
        App::new()
            .wrap(middleware::Logger::new(
                "%a \"%r\" %s %b \"%{Referer}i\" \"%{User-Agent}i\" %Dms"
            ))
            .route("/", web::get().to(index))
    })
    .bind("127.0.0.1:8080")?
    .run()
    .await
}

Compress 中间件 #

基本用法 #

rust
use actix_web::middleware::Compress;

App::new()
    .wrap(Compress::default())

指定压缩级别 #

rust
App::new()
    .wrap(Compress::new(actix_web::http::header::ContentEncoding::Gzip))

支持的压缩算法 #

算法 说明
Gzip 最常用的压缩算法
Deflate 老式压缩算法
Brotli 高压缩率算法

ErrorHandlers 中间件 #

基本用法 #

rust
use actix_web::{middleware, http::StatusCode, HttpResponse};

fn error_handler<B>(res: ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>, Error> {
    // 自定义错误处理
    Ok(ErrorHandlerResponse::Response(res.map_into_left_body()))
}

App::new()
    .wrap(middleware::ErrorHandlers::new()
        .handler(StatusCode::NOT_FOUND, not_found_handler)
        .handler(StatusCode::INTERNAL_SERVER_ERROR, error_handler)
    )

自定义错误页面 #

rust
use actix_web::{
    body::EitherBody,
    dev::{ServiceResponse, ServiceRequest},
    http::StatusCode,
    middleware::{ErrorHandlerResponse, ErrorHandlers},
    web, App, HttpResponse, HttpServer, Responder,
};

fn render_404<B>(res: ServiceResponse<B>) -> actix_web::Result<ErrorHandlerResponse<B>> {
    let response = HttpResponse::build(StatusCode::NOT_FOUND)
        .content_type("text/html")
        .body("<h1>404 - Page Not Found</h1>");
    
    let res = ServiceResponse::new(res.request().clone(), response)
        .map_into_right_body();
    
    Ok(ErrorHandlerResponse::Response(res))
}

fn render_500<B>(res: ServiceResponse<B>) -> actix_web::Result<ErrorHandlerResponse<B>> {
    let response = HttpResponse::build(StatusCode::INTERNAL_SERVER_ERROR)
        .content_type("text/html")
        .body("<h1>500 - Internal Server Error</h1>");
    
    let res = ServiceResponse::new(res.request().clone(), response)
        .map_into_right_body();
    
    Ok(ErrorHandlerResponse::Response(res))
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new()
            .wrap(ErrorHandlers::new()
                .handler(StatusCode::NOT_FOUND, render_404)
                .handler(StatusCode::INTERNAL_SERVER_ERROR, render_500)
            )
    })
    .bind("127.0.0.1:8080")?
    .run()
    .await
}

DefaultHeaders 中间件 #

基本用法 #

rust
use actix_web::middleware::DefaultHeaders;

App::new()
    .wrap(DefaultHeaders::new()
        .add(("X-Version", "1.0"))
        .add(("X-Frame-Options", "DENY"))
    )

安全头部 #

rust
App::new()
    .wrap(DefaultHeaders::new()
        .add(("X-Content-Type-Options", "nosniff"))
        .add(("X-Frame-Options", "SAMEORIGIN"))
        .add(("X-XSS-Protection", "1; mode=block"))
        .add(("Strict-Transport-Security", "max-age=31536000; includeSubDomains"))
    )

Condition 中间件 #

条件启用中间件 #

rust
use actix_web::middleware::Condition;

App::new()
    .wrap(Condition::new(cfg.debug, middleware::Logger::default()))

环境相关中间件 #

rust
use std::env;

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    let is_dev = env::var("ENV").unwrap_or_default() == "development";
    
    HttpServer::new(move || {
        App::new()
            .wrap(Condition::new(is_dev, middleware::Logger::default()))
    })
    .bind("127.0.0.1:8080")?
    .run()
    .await
}

CORS 中间件 #

添加依赖 #

toml
[dependencies]
actix-cors = "0.6"

基本用法 #

rust
use actix_cors::Cors;

App::new()
    .wrap(Cors::permissive())

自定义 CORS 配置 #

rust
use actix_cors::Cors;
use actix_web::http::header;

App::new()
    .wrap(
        Cors::default()
            .allowed_origin("https://example.com")
            .allowed_origin_fn(|origin, _req| {
                origin.as_bytes().ends_with(b".example.com")
            })
            .allowed_methods(vec!["GET", "POST"])
            .allowed_headers(vec![header::AUTHORIZATION, header::ACCEPT])
            .allowed_header(header::CONTENT_TYPE)
            .max_age(3600)
    )

Identity 中间件 #

添加依赖 #

toml
[dependencies]
actix-identity = "0.6"
actix-session = "0.8"

基本配置 #

rust
use actix_identity::IdentityMiddleware;
use actix_session::{config::PersistentSession, storage::CookieSessionStore, SessionMiddleware};
use actix_web::cookie::Key;

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    let secret_key = Key::generate();
    
    HttpServer::new(move || {
        App::new()
            .wrap(IdentityMiddleware::default())
            .wrap(
                SessionMiddleware::builder(CookieSessionStore::default(), secret_key.clone())
                    .build()
            )
    })
    .bind("127.0.0.1:8080")?
    .run()
    .await
}

完整示例 #

rust
use actix_cors::Cors;
use actix_web::{
    body::EitherBody,
    dev::{ServiceResponse, ServiceRequest},
    http::StatusCode,
    middleware::{DefaultHeaders, ErrorHandlerResponse, ErrorHandlers, Logger},
    web, App, HttpResponse, HttpServer, Responder,
};

async fn index() -> impl Responder {
    HttpResponse::Ok().json(serde_json::json!({
        "message": "Hello, World!"
    }))
}

fn render_404<B>(res: ServiceResponse<B>) -> actix_web::Result<ErrorHandlerResponse<B>> {
    let response = HttpResponse::build(StatusCode::NOT_FOUND)
        .json(serde_json::json!({
            "error": "Not Found",
            "message": "The requested resource was not found"
        }));
    
    let res = ServiceResponse::new(res.request().clone(), response)
        .map_into_right_body();
    
    Ok(ErrorHandlerResponse::Response(res))
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    std::env::set_var("RUST_LOG", "info");
    env_logger::init();
    
    HttpServer::new(|| {
        App::new()
            .wrap(Logger::default())
            .wrap(
                Cors::default()
                    .allowed_origin("http://localhost:3000")
                    .allowed_methods(vec!["GET", "POST", "PUT", "DELETE"])
                    .allowed_header(actix_web::http::header::CONTENT_TYPE)
                    .max_age(3600)
            )
            .wrap(
                DefaultHeaders::new()
                    .add(("X-Content-Type-Options", "nosniff"))
                    .add(("X-Frame-Options", "DENY"))
            )
            .wrap(
                ErrorHandlers::new()
                    .handler(StatusCode::NOT_FOUND, render_404)
            )
            .route("/", web::get().to(index))
    })
    .bind("127.0.0.1:8080")?
    .run()
    .await
}

下一步 #

现在你已经掌握了内置中间件,继续学习 自定义中间件,了解如何编写自己的中间件!

最后更新:2026-03-29