当前位置: 首页 > news >正文

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

系列文章目录

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

文章目录

  • 系列文章目录
  • 前言
  • 一、中间件是什么
  • 二、中间件使用
      • 常用中间件
      • 使用中间件
      • 使用TraceLayer中间件实现请求日志打印
      • 自定义中间件
  • 共享状态


前言

上篇文件讲了路由和参数相应相关的。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 -----+|vresponses

请求将按照上图顺序执行,每一个都可以提前返回。比如在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()) ///使用日志中间件);

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

在这里插入图片描述

自定义中间件

想要自定义中间件,这里介绍两种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
whereS: 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框架时候再结合说一下

相关文章:

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

系列文章目录 第一章 axum学习使用 第二章 axum中间件使用 文章目录 系列文章目录前言一、中间件是什么二、中间件使用常用中间件使用中间件使用TraceLayer中间件实现请求日志打印自定义中间件 共享状态 前言 上篇文件讲了路由和参数相应相关的。axum还有个关键的地方是中间件…...

Vue操作时间

一、获取现在时间 const currentTime () > {let date new Date();let year date.getFullYear(); //月份从0~11&#xff0c;所以加一let month date.getMonth();let dateArr [date.getMonth() 1,date.getDate(),date.getHours(),date.getMinutes(),date.getSeconds(),…...

数据库——Redis 常见数据结构以及使用场景分析

文章目录 1. string2. list3. hash4. set5. sorted set 你可以自己本机安装 redis 或者通过 redis 官网提供的在线 redis 环境。 1. string 介绍 &#xff1a;string 数据结构是简单的 key-value 类型。虽然 Redis 是用 C 语言写的&#xff0c;但是 Redis 并没有使用 C 的字符串…...

数学建模-规划工具箱yalmip

官网下载 实例 %% yalmip 求解 yalmip clc;clear;close all; %% %sdpvar实型变量 intvar 整形变量 binvar 0-1型变量 psdpvar(3,1); %定义变量 %目标函数 要把求最大值转化为最小值 Objective-p(1)^2p(2)^2-p(2)*p(3);%约束条件 Constraints[0<p<1,(p(1)^2p…...

[SQL挖掘机] - 窗口函数 - 计算移动平均

介绍: 在窗口函数使用时&#xff0c;计算的是累积到当前行的所有的数据的相关操作。 实际上&#xff0c;还可以指定更加详细的汇总范围。该汇总范围称为 框架 (frame)。 其实这里也可以理解成一个窗口, 这个窗口是我们可以进行设置的. 之前我们介绍的窗口函数是根据partition…...

域名和hostname

最近用git克隆远程仓库时总是超时&#xff0c;报错说是代理的问题&#xff0c;但打开和关闭代理都没能解决问题&#xff0c;后面了解到可以关闭git命令的全局代理&#xff1a; git config --global --unset http.proxy git config --global --unset https.proxy如果下次要用的…...

echarts 甘特图一组显示多组数据

<template><el-button type"primary" click"addlin">添加线</el-button><el-button type"success" click"addArea">添加区域</el-button><div ref"echart" id"echart" class&qu…...

1139. 最大的以 1 为边界的正方形;2087. 网格图中机器人回家的最小代价;1145. 二叉树着色游戏

1139. 最大的以 1 为边界的正方形 核心思想&#xff1a;枚举正方向的右下角坐标&#xff08;i&#xff0c;j&#xff09;&#xff0c;然后你只需要判断四条边的连续一的最小个数即可&#xff0c;这里是边求连续一的个数同时求解结果。 087. 网格图中机器人回家的最小代价 核心…...

css滚动条的使用

前言&#xff1a; css滚动条的使用。 1、使用案例1&#xff1a;背景不要&#xff0c;只展示一个滚动条 如果是默认整体&#xff0c;::就够用了&#xff0c;如果是某个元素&#xff0c;可以 .abc:: ,如果是scss这种的 &:: ::-webkit-scrollbar {width: 6px; } ::-webkit…...

优化Python代理爬虫的应用

当我们在资源受限的环境中使用Python代理爬虫时&#xff0c;我们需要采取一些优化措施&#xff0c;以确保程序的高效性和稳定性。在本文中&#xff0c;我将分享一些关于如何优化Python代理爬虫在资源受限环境下的应用的实用技巧。 首先我们来了解&#xff0c;哪些情况算是资源…...

[C++] STL_vector使用与常用接口的模拟实现

文章目录 1、vector的介绍2、vector的使用2.1 vector的定义2.2 vector迭代器的使用2.3 vector的空间增长问题 3、vector的增删查改3.1 push_back&#xff08;重点&#xff09;3.2 pop_back&#xff08;重点&#xff09;3.3 operator[]&#xff08;重点&#xff09;3.4 insert3.…...

【LeetCode】167. 两数之和 II - 输入有序数组 - 双指针

目录标题 2023-8-23 09:25:08 2023-8-23 09:25:08 自己写的不是常量级的额外空间&#xff0c;但是写出来了&#xff0c;记录一下。 下次写的时候&#xff0c;请用双指针。 &#xff08;其实我想了想一想&#xff0c;双指针就没感觉出来&#xff1a;因为我只想到双指针两个都…...

YOLOV1

YOU ONLY LOOK ONCE...

美团增量数仓建设新进展

摘要&#xff1a;本文整理自美团系统研发工程师汤楚熙&#xff0c;在 Flink Forward Asia 2022 实时湖仓专场的分享。本篇内容主要分为四个部分&#xff1a; 建设背景核心能力设计与优化业务实践未来展望 点击查看原文视频 & 演讲PPT 一、美团增量数仓的建设背景 美团数仓架…...

​LeetCode解法汇总2337. 移动片段得到字符串

目录链接&#xff1a; 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目&#xff1a; https://github.com/September26/java-algorithms 原题链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 描述&#xff1a; 给你两个字…...

Fpass与Fstop

在MATLAB中&#xff0c;“Fpass”、“Fstop”、"Apass"和"Astop"是数字滤波器设计中常用的参数。它们用于定义滤波器的频率响应和滤波器的性能。 "Fpass"表示通带频率&#xff0c;指的是滤波器允许通过的频率范围。在数字滤波器设计中&#xff0…...

Java快速入门体验

Java快速入门体验 一、环境信息1.1 硬件信息1.2 软件信息 二、Maven安装2.1 Maven介绍2.2 Maven安装包下载2.3 Maven安装2.4 Maven初始化 三、Java安装3.1 JDK下载3.2 JDK安装3.3 JDK初始化 四、开发环境搭建4.1 安装开发工具4.2 关联Maven环境4.2.1 新建JAVA项目4.2.2 Maven与…...

父组件传给子组件的数据是异步的,为什么会导致子组件比父组件先执行?

当父组件传递给子组件的数据是异步获取的时候&#xff0c;可能会导致子组件先执行的问题。这是因为在 Vue 的更新机制中&#xff0c;当组件的模板开始渲染时&#xff0c;会立即触发子组件的创建和挂载过程&#xff0c;而父组件的数据可能还没有完全加载完成。 具体来说&#xf…...

泛型编程 学习笔记

#include "iostream"using namespace std;template<typename T> void Print(T a) {cout << a << endl; }int main() {int a 5;double b 2.3;char c e;string d "sdfasd";Print(a);Print(b);Print(c);Print(d);return 0; } 它可以不用…...

电脑文件删除了可以找回吗?分享一种简单恢复删除电脑文件办法!

电脑文件删除了可以找回吗&#xff1f;可以。在原理上讲电脑删除的文件是有希望恢复的&#xff0c;因为操作系统在删除文件的时候并会不会立刻将文件彻底删除。当文件被删除的时候&#xff0c;其文件记录被删除&#xff0c;并且被文件占用的磁盘空间被标记为空闲。 这样对于用户…...

Qwen2.5-VL-3B视频识别实战:从环境搭建到显存优化的踩坑记录

Qwen2.5-VL-3B视频识别实战&#xff1a;从环境搭建到显存优化的全流程指南 当开发者第一次尝试用Qwen2.5-VL-3B处理视频内容时&#xff0c;往往会遇到各种预料之外的挑战。从依赖包缺失到显存爆炸&#xff0c;从环境配置到参数调试&#xff0c;每一步都可能成为阻碍项目推进的绊…...

[技术突破]obs-multi-rtmp:解决多平台直播资源浪费问题的高效分发方案

[技术突破]obs-multi-rtmp&#xff1a;解决多平台直播资源浪费问题的高效分发方案 【免费下载链接】obs-multi-rtmp OBS複数サイト同時配信プラグイン 项目地址: https://gitcode.com/gh_mirrors/ob/obs-multi-rtmp 行业痛点诊断 直播行业正面临多平台分发的严峻挑战&a…...

Avalonia预览器罢工了?别慌,手把手教你排查和修复‘无法加载axaml预览’的坑

Avalonia预览器崩溃自救指南&#xff1a;从错误日志到配置优化的全链路解决方案 当你正沉浸在Avalonia跨平台UI开发的流畅体验中&#xff0c;突然发现预览窗口变成一片空白&#xff0c;右下角弹出"无法加载axaml预览"的红色警告——这种突如其来的开发中断&#xff0…...

[具身智能-125]:RQT(Robot Qt),一个可以全方位监控ROS2系统内部节点工作状态的可视化超级终端!!!

如果说 RViz2 是机器人的“眼睛”&#xff08;看 3D 世界&#xff09;&#xff0c;那么 RQT 就是机器人的“听诊器”和“控制台”。它基于 Qt 框架开发&#xff0c;采用插件化架构&#xff0c;让你能在一个窗口里完成对 ROS2 系统内部状态的全方位监控与调试。为了让你更好地利…...

STM32duino S2-LP无线驱动库:Sub-1GHz低功耗可靠通信实现

1. 项目概述STM32duino X-NUCLEO-S2868A2 是一款面向 STM32 平台的 Arduino 兼容库&#xff0c;专为驱动意法半导体&#xff08;STMicroelectronics&#xff09;推出的 X-NUCLEO-S2868A2 扩展板而设计。该扩展板核心搭载 S2-LP 超低功耗 Sub-1GHz 射频收发器芯片&#xff08;型…...

OpenClaw极简部署:Qwen3-VL:30B镜像+飞书5分钟接入

OpenClaw极简部署&#xff1a;Qwen3-VL:30B镜像飞书5分钟接入 1. 为什么选择这个组合&#xff1f; 上周我在测试各种开源模型与自动化工具的搭配方案时&#xff0c;发现了一个效率极高的组合&#xff1a;星图平台的Qwen3-VL:30B镜像OpenClaw框架。这个方案最吸引我的地方在于…...

Linux性能调优实战:CPU与内存优化指南

Linux 性能调优实战指南1. 性能优化基础概念1.1 性能指标Linux性能优化的两个核心指标是吞吐量和延迟。从应用负载角度看&#xff0c;直接影响终端用户体验&#xff1b;从系统资源角度看&#xff0c;关注资源使用率和饱和度。性能问题的本质是系统资源已达瓶颈但请求处理不够快…...

nRF51822 RTC1深度睡眠唤醒与80μA低功耗优化

1. nRF51822低功耗唤醒系统深度解析&#xff1a;RTC1驱动的深度睡眠唤醒机制与80μA电流优化实践1.1 项目背景与工程痛点定位nRF51_WakeUp项目聚焦于nRF51822 SoC在超低功耗场景下的精准唤醒能力构建&#xff0c;其核心目标是通过RTC1&#xff08;Real-Time Counter 1&#xff…...

多项式朴素贝叶斯

多项式朴素贝叶斯&#xff08;二分类&#xff09; 题意 实现一个 Multinomial Naive Bayes 二分类器。 train&#xff1a;二维列表&#xff0c;每行最后一列为标签 y \in \{0,1\}&#xff0c;其余列为非负整数词频test&#xff1a;二维列表&#xff0c;仅包含词频特征&#xff…...

ES920 Arduino库深度解析:Sub-1GHz工业无线通信实战指南

1. ES920无线模块Arduino库深度解析&#xff1a;面向工业级Sub-1GHz通信的工程实践指南ES920系列是日本Echostar公司推出的高性能Sub-1GHz无线通信模块&#xff0c;涵盖FSK调制的ES920与LoRa调制的ES920LR两个子型号。该系列模块专为日本920MHz ISM频段&#xff08;920.6–928.…...