域名 AXUM.RS 将于2025年10月到期。我们无意再对其进行续费,我们希望你能够接续这个域名,让更多 AXUM 开发者继续受益。
  • 方案1️⃣AXUM.RS 域名 = 3000
  • 方案2️⃣方案1️⃣ + 本站所有专题原始 Markdown 文档 = 5000
  • 方案3️⃣方案2️⃣ + 本站原始数据库 = 5500
如果你有意接续这份 AXUM 情怀,请与我们取得联系。
说明:
  1. 如果有人购买 AXUM.RS 域名(方案1️⃣),或者该域名到期,本站将启用新的免费域名继续提供服务。
  2. 如果有人购买了 AXUM.RS 域名,且同时购买了内容和/或数据库(方案2️⃣/方案3️⃣),本站将关闭。届时我们或许会以另一种方式与你再相遇。

路由

axum 提供了常用的 HTTP 请求方式对应的路由,比如 get, post, put, delete 等。除此之外,axum 还提供了“嵌套路由”。路由,通常和 handler(处理函数) 结合在一起。

handler 是什么

它的返回值是什么

正如《axum 中的各种响应》所说,在 axum 中,所有实现了 IntoResponse 的数据类型都可以作为 handler 的返回值。

常用的请求方式

请求方式说明
GET该请求应该只被用于获取数据
POST用于将实体提交到指定的资源,通常导致在服务器上的状态变化或副作用
PUT用请求有效载荷替换目标资源的所有当前表示
DELETE删除指定的资源

上表节选自《HTTP 请求方法》,更多请求方法,请参照原文。

上表节选自《HTTP 请求方法》,更多请求方法,请参照原文。

在 axum 中,axum::routing 重新导出了 HTTP 请求方式的对应函数。也就是说,使用axum::routing::get() 来定义一个 GET 请求的路由。

axum 的路由支持链式操作。假设以下场景:在编辑某用户信息时,首先要使用表单显示用户当前的信息(GET),修改完成之后,还要将这个表单数据发送到服务器(POST)。在这个过程中,路由的 URL 是一样的。

由于还未学习到模板的相关内容,本例我们用直接书写 HTML 来作演示。你也可以看一下《axum 中使用模板引擎

由于还未学习到模板的相关内容,本例我们用直接书写 HTML 来作演示。你也可以看一下《axum 中使用模板引擎

定义相关的 struct:

/// 通过表单提交数据
#[derive(Deserialize)]
pub struct EditUser {
    pub id: i32,
    pub username: String,
    pub email: String,
}

/// 对应数据库的模型
pub struct UserModel {
    pub id: i32,
    pub username: String,
    pub email: String,
}

定义 handler:

/// 显示要修改的用户
async fn edit_user(Path(id): Path<i32>) -> Html<String> {
    let model = UserModel {
        id,
        username: "AXUM.RS".to_string(),
        email: "[email protected]".to_string(),
    };
    let html = format!(
        r#"
        <!DOCTYPE html>
        <html lang="zh-Hans">
          <head>
            <meta charset="utf-8" />
            <meta name="author" content="axum.rs ([email protected])" />
            <title>
              修改用户-AXUM中文网
            </title>
          </head>
          <body>
          <form method="post" action="/edit_user/{}">
          <input type="hidden" name="id" value="{}">
          <div>
            <label>用户名</label>
            <input type="text" name="username" value="{}">
          </div>
          <div>
            <label>Email</label>
            <input type="email" name="email" value="{}">
          </div>
          <div>
            <button type="submit">提交</button>
          </div>
          </form>
          </body>
          </html>
        "#,
        model.id, model.id, model.username, model.email
    );
    Html(html)
}

/// 对用户进行修改
async fn edit_user_action(Form(frm): Form<EditUser>) -> Html<String> {
    let html = format!(
        r#"
        <!DOCTYPE html>
        <html lang="zh-Hans">
          <head>
            <meta charset="utf-8" />
            <meta name="author" content="axum.rs ([email protected])" />
            <title>
              修改用户-AXUM中文网
            </title>
          </head>
          <body>
            <h1>修改成功!</h1>
            <p>修改后的用户资料:</p>
            <div>ID: {} </div>
            <div>用户名: {} </div>
            <div>Email: {} </div>
          </body>
          </html>"#,
        frm.id, frm.username, frm.email
    );
    Html(html)
}
route("/edit_user/:id", get(edit_user).post(edit_user_action))

嵌套路由

为了方便进路由进行分组,axum 提供了嵌套路由功能。比如有以下路由:

通过嵌套路由可以使其更清晰:

定义 handlers:

async fn news_index() -> &'static str {
    "new index"
}
async fn news_detail(Path(id): Path<i32>) -> String {
    format!("new detail {}", id)
}
async fn news_comments(Path(id): Path<i32>) -> String {
    format!("new comments {}", id)
}

定义子路由:

let news_router = Router::new()
        .route("/", get(news_index))
        .route("/detail/:id", get(news_detail))
        .route("/comments/:id", get(news_comments));

将子路由嵌到全局路由:

.nest("/news", news_router);

思考题:

提示:

  1. 使用 (StatusCode, HeaderMap, ()) 响应
  2. 对应的状态码可查阅这里
  3. 对应的 Header 可查阅这里

提示:

  1. 使用 (StatusCode, HeaderMap, ()) 响应
  2. 对应的状态码可查阅这里
  3. 对应的 Header 可查阅这里

参考答案:

async fn redirect() -> (StatusCode, HeaderMap, ()) {
    let mut headers = HeaderMap::new();
    headers.insert(
        axum::http::header::LOCATION,
        "https://axum.rs".parse().unwrap(),
    );
    (StatusCode::FOUND, headers, ())
}
要查看完整内容,请先登录