Rust的Axum入门教程

在本文中,我们将全面了解如何使用 Axum 编写 Web 服务。这也将包括0.7 的更改。

1、路由
Axum 遵循 REST 风格的 API(例如 Express)的风格,您可以在其中创建处理函数并将它们附加到 axum 的axum::Router类型。

async fn hello_world() -> &'static str {
    "Hello world!"
}

然后我们可以将它添加到我们的路由器中,如下所示:

use axum::{Router, routing::get};

fn init_router() -> Router {
    Router::new()
        .route("/", get(hello_world))
}

要使处理函数有效,它必须是 axum::response::Response 类型或实现 axum::response::IntoResponse。
大多数原始类型和所有 Axum 自己的类型都已实现了这一点--例如,如果我们想向用户发送一些 JSON 数据,我们可以使用 Axum 的 JSON 类型来轻松实现,方法是使用它作为返回类型,并用 axum::Json 类型封装我们要发送的任何内容。
如上所示,我们还可以单独返回一个字符串(片段)。

我们还可以直接使用 impl IntoResponse,乍一看,这立即解决了我们需要确定返回类型的问题;但是,直接使用它也意味着要确保所有返回类型都是相同的!这意味着我们可能会遇到不必要的错误。相反,我们可以为一个枚举或结构体实现 IntoResponse,然后将其用作返回类型。请参见下文:

use axum::{response::{Response, IntoResponse}, Json};

// 在这里,我们展示了一个实现序列化 + 发送的类型
#[derive(Serialize)]
struct Message {
    message: String
}

enum ApiResponse {
    Ok,
    Created,
    JsonData(Vec<Message>),
}

impl IntoResponse for ApiResponse {
    fn into_response(&self) -> Response {
        match self {
            Response::OK => (StatusCode::OK).into_response(),
            Response::Created => (StatusCode::CREATED).into_response(),
            Response::JsonData(data) => (StatusCode::OK, Json(data)).into_response()
        }
    }
}

然后,您可以在处理函数中这样实现枚举:

async fn my_function() -> ApiResponse {
    // ... rest of your code
}

当然,我们也可以为返回使用结果类型!虽然从技术上讲,错误类型也可以接受任何可以转化为 HTTP 响应的内容,但我们也可以实现一种错误类型,以说明 HTTP 请求在应用程序中失败的几种不同方式,就像我们在成功 HTTP 请求枚举中所做的那样。请看下面:

enum ApiError {
    BadRequest,
    Forbidden,
    Unauthorised,
    InternalServerError
}

// ... 在这里实现 IntoResponse

async fn my_function() -> Result<ApiResponse, ApiError> {
   
// ... your code
}

这样,我们在编写 Axum 路由时就能区分错误和成功请求。

2、在 Axum 中添加数据库
通常,在设置数据库时,您可能需要设置数据库连接:

use axum::{Router, Extension};
use sqlx::PgPoolOptions;

#[tokio::main]
async fn main() {
    let dbconnection = PgPoolOptions::new()
        .max_connections(5)
        .connect(<db-connection-string-here>).await;

    let router = Router::new().route("/", get(hello_world)).layer(Extension::new(dbconnection));

   
//... rest of your code
}

然后,您需要配置自己的 Postgres 实例,无论是安装在本地计算机上,还是通过 Docker 或其他方式配置。