平台网站的建设需求,大连建筑工程有限公司,wordpress安装网站吗,站长工具查询网系列文章目录
第一章 axum学习使用 第二章 axum中间件使用 文章目录 系列文章目录前言一、中间件是什么二、中间件使用常用中间件使用中间件使用TraceLayer中间件实现请求日志打印自定义中间件 共享状态 前言
上篇文件讲了路由和参数相应相关的。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::protooff.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_middlewareB(request: RequestB,next: NextB,
) - 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]
implS FromRequestPartsS for RequireAuth
whereS: Send Sync,
{type Rejection StatusCode;async fn from_request_parts(parts: mut Parts, state: S) - ResultSelf, 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): StateArcAppState,
) {// ...
}第二种通过扩展提取
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): ExtensionArcAppState,
) {// ...
}第三种通过闭包去获取
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): PathString, state: ArcAppState) {// ...
}async fn create_user(Json(payload): JsonCreateUserPayload, state: ArcAppState) {// ...
}#[derive(Deserialize)]
struct CreateUserPayload {// ...
}这种方式写起来比较长但是比较直观
第二篇先说到这儿。等后续说完orm框架时候再结合说一下