结论先行
Hello World
先来看看 Axum 的 Hello World:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| use axum::Router; use axum::routing::get;
#[tokio::main] async fn main() { let app = Router::new() .route("/", get(|| async { "Hello World!" }));
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, app).await.unwrap(); }
|
通过上面这个例子,可以得到的第一个信息就是:Axum
是
tokic
生态下的一员。
本文默认读者对 tokio
具有基本的了解。
所以这里我们需要引入两个组件:
1 2
| cargo add tokio --features macros,rt-multi-thread cargo add axum
|
这个例子我们定义了一个路由,下面我们就先从 Axum 的路由开始介绍。
Routing 路由
单个路由
1
| Router::new().route("/", get(|| async { "Hello World!" }));
|
实际上它等价于:
1 2 3 4 5 6 7 8 9 10
| #[tokio::main] async fn main() { let app = Router::new() .route("/", get(handler_hello_world)); ... }
async fn handler_hello_world () -> impl IntoResponse { "Hello World" }
|
路由注册部分为为 path
、method
和
handler
三个部分。
其中 get
可以替换为
post
、patch
、delete
、head
和 options
等 http method。
其中 handler
的返回值需要满足:impl IntoResponse
,常用的
字符串
、json
和 html
都已经实现了
IntoResponse
,所以都是可以直接返回的。
路由分组
你可以使用 merge()
和 nest()
来进行路由分组,其中 nest()
可以指定统一路由前缀:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| #[tokio::main] async fn main() { let app = Router::new() .merge(todo_routers()) .nest("/v2/todo", todo_routers_v2()); ... }
fn todo_routers() -> Router { Router::new() .route("/todo/delete/:id", delete(handler_todo_delete)) .route("/todo/list", get(handler_todo_list)) .route("/todo/create", post(handler_todo_create)) .route("/todo/update", put(handler_todo_update)) }
fn todo_routers_v2() -> Router { Router::new() .route("/delete/:id", delete(handler_todo_delete)) .route("/list", get(handler_todo_list)) .route("/create", post(handler_todo_create)) .route("/update", put(handler_todo_update)) }
|
静态路由
可以使用同 tokio
生态下的 tower-http
来实现静态路由:
1 2 3
| fn static_routers() -> Router { Router::new().nest_service("/", get_service(ServeDir::new("./"))) }
|
这里你需要添加 tower-http
组件,至少需要载入
fs
特性:
1
| cargo add tower-http --features fs
|
参考