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概念需要花很多时间,以后有机会在写相关文章吧。

参考链接

相关推荐
一弓虽8 分钟前
SpringBoot 学习
java·spring boot·后端·学习
姑苏洛言17 分钟前
扫码小程序实现仓库进销存管理中遇到的问题 setStorageSync 存储大小限制错误解决方案
前端·后端
光而不耀@lgy32 分钟前
C++初登门槛
linux·开发语言·网络·c++·后端
方圆想当图灵1 小时前
由 Mybatis 源码畅谈软件设计(七):SQL “染色” 拦截器实战
后端·mybatis·代码规范
毅航1 小时前
MyBatis 事务管理:一文掌握Mybatis事务管理核心逻辑
java·后端·mybatis
我的golang之路果然有问题2 小时前
速成GO访问sql,个人笔记
经验分享·笔记·后端·sql·golang·go·database
柏油2 小时前
MySql InnoDB 事务实现之 undo log 日志
数据库·后端·mysql
写bug写bug3 小时前
Java Streams 中的7个常见错误
java·后端
Luck小吕4 小时前
两天两夜!这个 GB28181 的坑让我差点卸载 VSCode
后端·网络协议
M1A14 小时前
全栈开发必备:Windows安装VS Code全流程
前端·后端·全栈