【从零开始的rust web开发之路 二】axum中间件和共享状态使用

这篇具有很好参考价值的文章主要介绍了【从零开始的rust web开发之路 二】axum中间件和共享状态使用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

系列文章目录

第一章 axum学习使用
第二章 axum中间件使用


前言

上篇文件讲了路由和参数相应相关的。axum还有个关键的地方是中间件的使用,这篇文件就来说说。

一、中间件是什么

这个概念跟gin框架的中间件概念一样,类似于springboot项目当中的请求过滤器,在请求过来的时候链式执行一些操作。例如鉴权,日志收集,接口幂等等

二、中间件使用

常用中间件

看看官方提供的中间件
TraceLayer用于高级跟踪/日志记录的跟踪层。
CorsLayer 用于处理 CORS。
CompressionLayer用于自动压缩的压缩层 反应。
RequestIdLayer 和 PropagateRequestIdLayer 设置和传播请求 IDS。
CompressionLayer超时的超时层。注意这一点 需要使用 HandleErrorLayer 将超时转换为响应。

我只看了前两个,这里只拿前两个举例。

使用中间件

使用中间件有两种方法,
一种是通过调用route的layer方法

use axum::{routing::get, Router};

async fn handler() {}

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

这样使用顺序结构如下图

requests
           |
           v
+----- layer_three -----+
| +---- layer_two ----+ |
| | +-- layer_one --+ | |
| | |               | | |
| | |    handler    | | |
| | |               | | |
| | +-- layer_one --+ | |
| +---- layer_two ----+ |
+----- layer_three -----+
           |
           v
        responses

请求将按照上图顺序执行,每一个都可以提前返回。比如在layer_three进行鉴权操作,没有权限直接就返回,不在调用下一层

还有一种方法是使用tower::ServiceBuilder构建器,例如

use tower::ServiceBuilder;
use axum::{routing::get, Router};

async fn handler() {}

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

遇上一种方法不同的是执行顺序,这种方式执行顺序是
layer_one 、layer_two 、layer_three、 handler、 layer_three、 layer_two、 layer_one
这种方式更符合方法调用直觉,更容易理解

使用TraceLayer中间件实现请求日志打印

首先需要额外引入一些库

tower = { version = "0.4.13" }
tower-http = { version = "0.4.3", features = ["trace"] }
tracing = "0.1.37"
tracing-subscriber = {version = "0.3.17", features = [
    "env-filter",
    "time",
    "local-time",
]}

然后

//设置日志级别并格式化时间
    use tracing_subscriber::{fmt::time::OffsetTime};
    let local_time = OffsetTime::new(
        UtcOffset::from_hms(8, 0, 0).unwrap(),
        format_description!("[year]-[month]-[day] [hour]:[minute]:[second].[subsecond digits:3]"),
    );
    let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("debug"))
        .add_directive("hyper::proto=off".parse().unwrap());
    // 输出到控制台中
    let formatting_layer = fmt::layer().with_timer(local_time).with_writer(std::io::stderr);
    Registry::default()
        .with(env_filter)
        .with(formatting_layer)
        .init();
///设置

async fn handler() {}


let app = Router::new()
    .route("/", get(handler))
    .layer(
        ServiceBuilder::new()
            .layer(TraceLayer::new_for_http()) ///使用日志中间件
    );

访问服务这时候就能看到请求日志了

【从零开始的rust web开发之路 二】axum中间件和共享状态使用,rust语言,云原生,rust,中间件,后端,异步

自定义中间件

想要自定义中间件,这里介绍两种axum原生的方法
一种是axum::middleware::from_fn
举个例子

use axum::{
    Router,
    http::{self, Request},
    routing::get,
    response::Response,
    middleware::{self, Next},
};
///自定义中间件方法
async fn my_middleware<B>(
    request: Request<B>,
    next: Next<B>,
) -> Response {
    // 对请求做一些处理

	//......

	//调用下一个中间价
    let response = next.run(request).await;

	//......

    // 对响应做一些处理,返回响应
    response
}

//这里使用中间件
let app = Router::new()
    .route("/", get(|| async { /* ... */ }))
    .layer(middleware::from_fn(my_middleware));

还有一种方法是axum::middleware::from_extractor
举个例子

use axum::{
    extract::FromRequestParts,
    middleware::from_extractor,
    routing::{get, post},
    Router,
    http::{header, StatusCode, request::Parts},
};
use async_trait::async_trait;

// 执行认证中间件
struct RequireAuth;

#[async_trait]
impl<S> FromRequestParts<S> for RequireAuth
where
    S: Send + Sync,
{
    type Rejection = StatusCode;

    async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
        let auth_header = parts
            .headers
            .get(header::AUTHORIZATION)
            .and_then(|value| value.to_str().ok());

        match auth_header {
            Some(auth_header) if token_is_valid(auth_header) => {
                Ok(Self)
            }
            _ => Err(StatusCode::UNAUTHORIZED),
        }
    }
}

fn token_is_valid(token: &str) -> bool {
    // token校验
}

async fn handler() {
    // 认证之后处理
}

async fn other_handler() {
    // 认证之后处理
}

let app = Router::new()
    .route("/", get(handler))
    .route("/foo", post(other_handler))
    //给上面路由设置认证中间件
    .route_layer(from_extractor::<RequireAuth>());

类似于这个就是认证中间件的简单模板

共享状态

共享状态是用于多个请求共同访问的一些数据状态。例如db连接,redis连接等等。多个请求任务共享的数据
一共有三种方式
第一种是通过状态提取,举个例子

use axum::{
    extract::State,
    routing::get,
    Router,
};
use std::sync::Arc;

struct AppState {
    // ...
}

let shared_state = Arc::new(AppState { /* ... */ });

let app = Router::new()
    .route("/", get(handler))
    .with_state(shared_state);

async fn handler(
    State(state): State<Arc<AppState>>,
) {
    // ...
}

第二种通过扩展提取

use axum::{
    extract::Extension,
    routing::get,
    Router,
};
use std::sync::Arc;

struct AppState {
    // ...
}

let shared_state = Arc::new(AppState { /* ... */ });

let app = Router::new()
    .route("/", get(handler))
    .layer(Extension(shared_state));

async fn handler(
    Extension(state): Extension<Arc<AppState>>,
) {
    // ...
}

第三种通过闭包去获取

use axum::{
    Json,
    extract::{Extension, Path},
    routing::{get, post},
    Router,
};
use std::sync::Arc;
use serde::Deserialize;

struct AppState {
    // ...
}

let shared_state = Arc::new(AppState { /* ... */ });

let app = Router::new()
    .route(
        "/users",
        post({
            let shared_state = Arc::clone(&shared_state);
            move |body| create_user(body, shared_state)
        }),
    )
    .route(
        "/users/:id",
        get({
            let shared_state = Arc::clone(&shared_state);
            move |path| get_user(path, shared_state)
        }),
    );

async fn get_user(Path(user_id): Path<String>, state: Arc<AppState>) {
    // ...
}

async fn create_user(Json(payload): Json<CreateUserPayload>, state: Arc<AppState>) {
    // ...
}

#[derive(Deserialize)]
struct CreateUserPayload {
    // ...
}

这种方式写起来比较长,但是比较直观

第二篇先说到这儿。等后续说完orm框架时候再结合说一下文章来源地址https://www.toymoban.com/news/detail-673800.html

到了这里,关于【从零开始的rust web开发之路 二】axum中间件和共享状态使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Jeecg-Boot 低代码开发平台之路(一) —— 开始从零学起

    今天开始详细学习下 Jeecg-Boot 低代码开发平台,官方网站对该平台的介绍是如下。 JeecgBoot是一款基于BPM的低代码平台!前后端分离架构 SpringBoot 2.x,SpringCloud,Ant DesignVue,Mybatis-plus,Shiro,JWT,支持微服务。强大的代码生成器让前后端代码一键生成,实现低代码开发! Jee

    2023年04月08日
    浏览(89)
  • [架构之路-239]:目标系统 - 纵向分层 - 中间件middleware

    目录 前言: 一、中间件概述 1.1 中间件在软件层次中的位置 1.2 什么是中间件 1.3 为什么需要中间件 1.4 中间件应用场合(应用程序不用的底层需求:计算、存储、通信) 1.5 中间件分类 - 按内容分 二、嵌入式系统的中间件 2.1 概述 2.2 案例 三、分布式系统的中间件 3.1 概述

    2024年02月07日
    浏览(66)
  • Web中间件常见漏洞

    Web中间件常见漏洞 我们常见的中间件有apache,tomcat,IIS,weblogic(其实就是web容器),这些中间件可以设置支持的HTTP方法。每一个HTTP方法都有其对应的功能,在这些方法中,PUT可以直接从客户机上传文件到服务器。如果中间件开放了HTTP中的PUT方法,那么恶意攻击者就可以直接上传

    2024年02月14日
    浏览(69)
  • 常见的Web应用中间件(基于Linux)

            在整理常用的Web中间件时,我发现自己对于Web服务器、Web中间件和Web容器的概念容易混淆,所以在整理常见的Web应用中间件时,我想先区别一下Web服务器、Web中间件和Web容器。          Web服务器 也可以称为网站服务器,时提供Web服务的软件或主机,Web服务器

    2024年02月06日
    浏览(44)
  • 应急响应-web后门(中间件)的排查思路

    语言,数据库,中间件,系统环境等 1.利用时间节点筛选日志行为 2.利用已知的漏洞在日志进行特征搜索,快速定位到目标ip等信息 3.后门查杀,获取后门信息,进一步定位目标信息 iis .net分析:网站被入侵,给出来被入侵时间 iis日志地址:inetput/logs/LogFiles/W3VC5(确认对网站的

    2024年02月14日
    浏览(40)
  • Python web实战之细说Django的中间件

                      🔑 :Python Web 开发、Django、中间件 今天分享Python Web开发中的一个重要成员:Django的中间件。介绍中间件的概念、作用及其在实战中的应用。 在Python Web开发中,中间件(Middleware)是指位于Web应用程序和Web服务器之间的一层软件组件。它能够拦截请

    2024年02月13日
    浏览(45)
  • Golang web 项目中实现自定义 recovery 中间件

    在 Golang 的 Web 项目中,自定义 recovery 中间件是一种常见的做法,用于捕获并处理应用程序的运行时错误,以避免整个应用程序崩溃并返回对应格式的响应数据。 很多三方 web 框架(例如 gin、echo)都提供了官方实现的 recovery 中间件,但是官方实现的中间件并不一定能满足自

    2024年02月09日
    浏览(54)
  • 【node.js从入门到精通】使用express创建web服务器,路由,进行中间件的创建链接路由及其他中间件

    目录 前言 初识express 使用express创建基本的web服务器 初识express路由 路由匹配概念 路由模块化 中间件 中间件和路由的区别 定义中间件函数 中间件作用   局部生效中间价 中间件分类  1.应用级别中间件  2.路由级别的中间件  3.错误级别中间件  4.内置中间件  5.自定义中间

    2024年02月02日
    浏览(55)
  • ASP.NET Core 的 Web Api 实现限流 中间件

    Microsoft.AspNetCore.RateLimiting  中间件提供速率限制(限流)中间件。 它是.NET 7 以上版本才支持的中间件,刚看了一下,确实挺好用,下面给大家简单介绍一下: RateLimiterOptionsExtensions 类提供下列用于限制速率的扩展方法:​​​​​ 固定窗口限制器 滑动窗口限制器 令牌桶限

    2024年01月17日
    浏览(39)
  • 33、WEB攻防——通用漏洞&文件上传&中间件解析漏洞&编辑器安全

    IIS爆过漏洞的版本:IIS6.0(windows server 2003)、IIS7.0和IIS7.5(windows server 2008) IIS6.0解析漏洞: 文件名:x.asp;x.jpg,jpg的文件后缀名,但是会被解析为asp文件; 目录名:x.asp/x.jpg, 文件目录名含有.asp后缀,x.jpg也会被解析为asp文件。 触发条件: IIS6.0这个中间件; 上传文件能不

    2024年01月24日
    浏览(81)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包