上一篇文章,我简要概述了 Axum 框架的基本组成。这篇文章,我将详细展开讲讲路由和中间件。
路由(routing)是分发请求的中枢。所有发往服务器的请求都要先过路由这一关,它负责将请求按照其 URL 路径和请求方法进行匹配,匹配成功就让对应的中间件(如果有的话)和处理器去处理,否则就返回 404 Not Found。
Axum 中,路由由 Router 实现。一个 Router 能使用 .route 方法注册多个路由,这个方法接收一条 &str 路径和一个 MethodRouter 实例。
路径可以是静态的(例如 /、/foo、/users/123),也可以是捕获性的,还可以是通配符。
捕获性的路径需使用花括号包裹路径段,它可以将对应的路径参数捕获为一个同名变量,后续可以使用提取器在处理器中使用这个变量。
比如 /{key} 会匹配像 /mykey、/1234 这样的路径,并将字符串 mykey、1234 存储在变量 key 当中;同理,/users/{id}/tweets 会匹配路径 /users/1104/tweets 并将 1104 存储在变量 id 当中。
通配符路径只需要在捕获性路径的捕获变量前加 * 即可,它会匹配剩余所有路径段,但不会匹配空路径段。相比捕获性路径,它只能出现在路径末尾;它和前者一样有捕获功能。
比如 /{*key} 会匹配 /a、/a/ 等路径,但不匹配 /;/assets/{*path} 不匹配 /assets/,但匹配 /assets/styles.css、/assets/image/img.jpg 等。
MethodRouter 实例通常是借助方法路由函数构造的。
方法路由是一系列在 axum::routing::method_routing 中定义的函数,它们都接收一个处理器并返回一个 MethodRouter 实例。
use axum::{
routing::any,
Router,
};
/// 这是一个处理器
async fn handler() {}
// 创建路由,匹配 `/` 路径
//
// 这里的 `any` 函数就是方法路由
// 它接收一个处理器并构造出 `MethodRouter`
let app = Router::new().route("/", any(handler));
以下是常用的方法路由:
| 函数名 | 含义 |
|---|---|
any |
匹配任意请求方法 |
get |
只匹配 GET 请求 |
post |
只匹配 POST 请求 |
方法路由还允许进行链式调用。
async fn handler() {}
async fn other_handler() {}
// `POST /` 请求交给 `other_handler`,其它则都由 `handler` 处理
let app = Router::new().route("/", any(handler).post(other_handler));