我的学习笔记

土猛的员外

axum中文简述

以下文档基于axum Version 0.6.17

axum是一个专注于极简高效和模块化的web应用程序框架。

高级特性

  • 使用无宏API将请求路由到处理程序。
  • 使用提取器声明性地解析请求。
  • 简单和可预测的错误处理模型。
  • 用最少的样板文件生成响应。
  • 充分利用中间件、服务和实用程序的towertower-http生态系统。

最后一点是“axum”区别于其他框架的地方。axum没有自己的中间件系统,而是使用tower::Service。这意味着“axum”可以免费获得超时、跟踪、压缩、授权等。它还允许您与使用‘ hyper ‘‘ tonic ‘编写的应用程序共享中间件。

兼容性

axum是为配合tokiohyper设计的,运行时层和传输层的独立性不是目标,至少目前不是。

示例

axum的 “Hello, World!” :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
use axum::{
routing::get,
Router,
};

#[tokio::main]
async fn main() {
// build our application with a single route
let app = Router::new().route("/", get(|| async { "Hello, World!" }));

// run it with hyper on localhost:3000
axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
.serve(app.into_make_service())
.await
.unwrap();
}

注意使用#[tokio::main]需要启用tokio的macrosrt-multi-thread功能,或者只启用full来启用所有功能(cargo add tokio—features macros,rt-multi-thread)。

路由(ROUTING)

Router 用于设置哪些路径指向哪些服务:

1
2
3
4
5
6
7
8
9
10
11
12
13
use axum::{Router, routing::get};

// our router
let app = Router::new()
.route("/", get(root))
.route("/foo", get(get_foo).post(post_foo))
.route("/foo/bar", get(foo_bar));

// which calls one of these handlers
async fn root() {}
async fn get_foo() {}
async fn post_foo() {}
async fn foo_bar() {}

细节可以查看 Router 

处理器(Handlers)

在axum中,处理器(“handler”)是一个异步函数,它接受零个或多个“extractors”作为参数,并返回可以转换为response的内容

处理器是应用程序逻辑存在的地方,而axum应用程序是通过处理器之间的路由构建的。

请参见‘ handler ‘了解处理程序的更多详细信息。

提取器(Extractors)

提取器是一种实现FromRequestFromRequestParts的类型。提取器是您如何分离传入请求以获得处理程序所需的部分。

1
2
3
4
5
6
7
8
9
10
11
12
13
use axum::extract::{Path, Query, Json};
use std::collections::HashMap;

// `Path` gives you the path parameters and deserializes them.
async fn path(Path(user_id): Path<u32>) {}

// `Query` gives you the query parameters and deserializes them.
async fn query(Query(params): Query<HashMap<String, String>>) {}

// Buffer the request body and deserialize it as JSON into a
// `serde_json::Value`. `Json` supports any type that implements
// `serde::Deserialize`.
async fn json(Json(payload): Json<serde_json::Value>) {}

更多细节可以参看 extract .

响应(Responses)

任何实现IntoResponse的东西都可以从处理器返回。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
use axum::{
body::Body,
routing::get,
response::Json,
Router,
};
use serde_json::{Value, json};

// `&'static str` becomes a `200 OK` with `content-type: text/plain; charset=utf-8`
async fn plain_text() -> &'static str {
"foo"
}

// `Json` gives a content-type of `application/json` and works with any type
// that implements `serde::Serialize`
async fn json() -> Json<Value> {
Json(json!({ "data": 42 }))
}

let app = Router::new()
.route("/plain_text", get(plain_text))
.route("/json", get(json));

更多细节参看 response 。

错误处理(Error handling)

axum旨在提供一个简单且可预测的错误处理模型,这意味着将错误转换为响应很简单,并且可以保证所有错误都得到处理。

参见error_handling了解更多关于axum错误处理模型以及如何优雅地处理错误的详细信息。

中间件(Middleware)

为axum编写中间件有几种不同的方法。详见‘中间件’

与处理器共享状态(Sharing state with handlers)

在处理程序之间共享某些状态是很常见的。例如,可能需要共享到其他服务的数据库连接或客户端池。

最常见的三种方法是:

  • 使用State提取器
  • 使用请求扩展
  • 使用闭包捕获

使用 State extractor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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>>,
) {
// ...
}

如果可能的话,您应该更喜欢使用State,因为它更类型安全。缺点是它不如Request extensions 具有动态性。

有关访问状态的更多细节,请参见State

使用 request extensions

在处理器中提取状态的另一种方法是使用Extension 作为层和提取器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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>>,
) {
// ...
}

这种方法的缺点是,如果您尝试提取一个不存在的扩展,可能是因为您忘记添加中间件,或者因为您提取了错误的类型,那么您将得到运行时错误(特别是500 Internal Server Error 响应)。

使用闭包捕获(closure captures)

State也可以使用闭包捕获直接传递给处理器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
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 {
// ...
}

这种方法的缺点是它比使用‘ State ‘或extensions更冗长。

为axum构建集成

想要为FromRequestFromRequestParts,或IntoResponse提供实现的lib作者应该依赖于axum-corecrate,而不是axum axum-core 包含核心类型和特征,不太可能收到破坏性更改。

需要的依赖

为了使用axum,你还需要引入一些依赖项

1
2
3
4
5
[dependencies]
axum = "<latest-version>"
hyper = { version = "<latest-version>", features = ["full"] }
tokio = { version = "<latest-version>", features = ["full"] }
tower = "<latest-version>"

hyper和tokio的“full”功能并不是必须的,但这是最简单的入门方法。

注意hyper::Server 是由axum重新导出的,所以只需要这个,那么你不必显式地依赖hyper。

Tower也不是严格必要的,但有助于测试。请参阅回购中的测试示例,以了解有关测试axum应用程序的更多信息。

更多示例

axum repo包含许多示例,展示了如何将所有部分组合在一起。

功能标志

axum使用一组feature flags来减少已编译和可选依赖项的数量。

可选特性包括:

Name Description Default?
headers 通过TypedHeader使得提取已输入标题成为可能 No
http1 启用 Hyper 的 HTTP1 功能 Yes
http2 启用 Hyper 的 HTTP2 功能 No
json 启用Json类型和一些类似的便利功能。 Yes
macros 启用可选实用宏 No
matched-path 使得能够捕获每个请求的路由路径和MatchedPath提取器。 Yes
multipart 使用Multipart使得解析multipart/form-data请求成为可能 No
original-uri 使得能够捕获每个请求的原始URI和OriginalUri提取器。 Yes
tokio 使得Tokio成为依赖项,并提供axum::ServerSSEextract::connect_info类型。 Yes
tower-log Enables tower’s log feature Yes
tracing 记录内置提取器的拒绝。 No
ws 通过extract::ws启用WebSockets支持 No
form 启用Form提取器 Yes
query 启用Query提取器 Yes





关注我的微信公众号,可收到实时更新通知

公众号:土猛的员外


TorchV AI支持试用!

如您有大模型应用方面的企业需求,欢迎咨询!