RUST web框架axum快速入门教程5之中间件

本文主要讨论axum的中间件,这也是axum与其他rust web框架极大的不同点,其他框架都定义了自己的接口,而axum直接使用towerServvicelayer的概念, 而tower已经存在一大堆通用的中间件了,所以axum也就自带了一大堆开箱即用的中间件。

往期文章:

本节的Cargo.toml文件依赖如下

toml 复制代码
[dependencies]
axum = { version="0.6.20", features=["default", "headers"] }
axum-extra = { version = "0.8" }
tokio = { version = "1.0", features = ["full"] }
reqwest = { version="0.11.22", features=["json", "multipart"]}
serde = { version = "1.0", features = ["derive"] }
tower = { version = "0.4", features = ["util"] }
tower-http = { version = "0.4.0", features = ["full"] }
serde_json = "1.0.107"
askama = "0.12"
sqlx = { version = "0.7", features = [ "runtime-tokio", "postgres"] }
matchit = "0.7.3"
rand = "0.8.5"
http = "1.0.0"
hyper = "0.14.27"

快速入门

rust 复制代码
// https://youerning.top/post/axum/quickstart-5
use std::time::Duration;
use axum::http::HeaderName;
use axum::{
    body::Body,
    routing::get,
    Router,
    http::Request,
};
use tokio::time::sleep;
use tower_http::trace::TraceLayer;
use tower_http::compression::CompressionLayer;
use tower_http::timeout::TimeoutLayer;
use tower_http::cors::{CorsLayer, Any};
use tower_http::request_id::{MakeRequestUuid, SetRequestIdLayer};
use tower::ServiceBuilder;



#[tokio::main]
async fn main() {
    let app = Router::new()
        .route("/", get(index_handler))
        .layer(
            // 官方推荐在ServiceBuilder上一次性载入
            ServiceBuilder::new()
                .layer(TraceLayer::new_for_http())
                .layer(CompressionLayer::new())
            	// 超时时间是200ms
                .layer(TimeoutLayer::new(Duration::new(0, 200000)))
            	// 需要设置一个请求头的键名,一般叫x-request-id
                .layer(SetRequestIdLayer::new(HeaderName::from_static("x-request-id"), MakeRequestUuid))
                // 默认情况下不放行,所以需要根据自己需求设置必要的允许规则。
               .layer(CorsLayer::new().allow_methods(axum::http::Method::GET).allow_origin(Any))
                
        );

    let addr = "0.0.0.0:8080";
    axum::Server::bind(&addr.parse().unwrap())
      .serve(app.into_make_service())
      .await
      .unwrap();
}

async fn index_handler(req: Request<Body>) -> String {
    if rand::random() {
        sleep(Duration::new(0, 300000)).await;
    }

    if let Some(req_id) = req.headers().get("x-request-id") {
        // CompressionLayer只有当长度大于32时才会压缩
        format!("request[{:?}] {} with method {} ; make the body length longer than 32", req_id ,req.uri(), req.method())
    } else {
        format!("request[none] {} with method {} ; make the body length longer than 32", req.uri(), req.method())
    }
    
}

上面使用了五个比较常用的中间件。

  • TraceLayer trace中间件, 用于追踪各种事件,在不发送给远端的情况的话,跟日志差不多
  • CompressionLayer 压缩中间件,默认情况下,只有内容长度大于32的时候才会进行压缩
  • TimeoutLayer 超时中间件 如果服务端响应超时就返回408状态码
  • SetRequestIdLayer 为服务端设置请求ID,如果还需要为客户端生成对应的请求ID,那么需要PropagateRequestIdLayer
  • CorsLayer 设置CORS请求头,做过前后端分离的项目应该不陌生

除此之外,tower_http还有超级多的中间件可以使用,有兴趣的可以查看: docs.rs/tower-http/...

顺序

tower_http的中间件嵌套其实就像洋葱一层包一层

rust 复制代码
use axum::{routing::get, Router};

async fn handler() {}

let app = Router::new()
    .route("/", get(handler))
    .layer(layer_one)
    .layer(layer_two)
    .layer(layer_three);

上面的代码的请求顺序如下

rust 复制代码
        requests
           |
           v
+----- layer_three -----+
| +---- layer_two ----+ |
| | +-- layer_one --+ | |
| | |               | | |
| | |    handler    | | |
| | |               | | |
| | +-- layer_one --+ | |
| +---- layer_two ----+ |
+----- layer_three -----+
           |
           v
        responses

小结

这一节主要了解了一下axum或者说tower的一些常见中间件的使用,如果tower的中间件列表没有自己需要的,可以自己写,虽然会写的不会太难,但是对于没有接触过tower的人来说还是有点难以理解,所以作为快速入门,这里就省略了自己写中间件的内容了, 当然了,也是觉得解释towerService概念需要花很多时间,以后有机会在写相关文章吧。

参考链接

相关推荐
程序员爱钓鱼29 分钟前
Go语言实战案例-创建模型并自动迁移
后端·google·go
javachen__34 分钟前
SpringBoot整合P6Spy实现全链路SQL监控
spring boot·后端·sql
uzong6 小时前
技术故障复盘模版
后端
GetcharZp6 小时前
基于 Dify + 通义千问的多模态大模型 搭建发票识别 Agent
后端·llm·agent
桦说编程7 小时前
Java 中如何创建不可变类型
java·后端·函数式编程
IT毕设实战小研7 小时前
基于Spring Boot 4s店车辆管理系统 租车管理系统 停车位管理系统 智慧车辆管理系统
java·开发语言·spring boot·后端·spring·毕业设计·课程设计
wyiyiyi7 小时前
【Web后端】Django、flask及其场景——以构建系统原型为例
前端·数据库·后端·python·django·flask
阿华的代码王国8 小时前
【Android】RecyclerView复用CheckBox的异常状态
android·xml·java·前端·后端
Jimmy8 小时前
AI 代理是什么,其有助于我们实现更智能编程
前端·后端·ai编程
AntBlack9 小时前
不当韭菜V1.1 :增强能力 ,辅助构建自己的交易规则
后端·python·pyqt