#actix-web #api #return #arguments #error-response #procedural #struct

actix-type-handler

actix-type-handler 是为 Actix-web 设计的进程宏 crate,旨在简化 API 创建。它通过允许直接传递结构体参数、使用 Result 进行错误处理以及为每个 API 提供独特的参数和返回类型来增强代码的可读性,同时提供了定义自定义错误响应的灵活性。

1 个不稳定版本

0.1.0 2023 年 6 月 22 日

#739过程宏

MIT 许可证

10KB
62 行代码(不含注释)

目录

  1. 这是什么?
  2. 动机
  3. 优势
  4. 用法
    1. 创建 ApiResponse
    2. 使用 Thiserror 创建 ApiError
    3. 创建您的参数和返回类型
    4. 编写您的 API 逻辑
      1. 查询
      2. 路径
      3. 主体
    5. 添加到您的路由器

这是什么?

api_type_handler 是一个进程宏,旨在简化使用 Actix-web 创建 API 的过程,使您的代码更简洁、更易于维护。

动机

通常,在用 Actix-web 创建 API 时,函数的参数和返回值如下所示

pub async fn register(
query: actix_web::web::Json<MyQuery>, 
path: actix_web::web::Path<MyPath>,
body: actix_web::web::Form<MyForm>,
db_pool: actix_web::web::Data<Pool<MySql>>) -> impl Responder;

然而,这种方法有一些局限性。首先,您必须频繁使用 into_inner 方法来访问路径或查询的底层结构体。其次,由于返回类型不是 Result,您必须编写大量的错误分支代码。

此 crate 的开发是为了克服这些障碍。使用此宏,您现在可以像这样编写您的函数

pub async fn register(
query: MyQuery, 
path: MyPath,
body: MyForm,
db_pool: actix_web::web::Data<Pool<MySql>>) -> Result<MyResponse, ApiError>;

优势

  • 更简单的参数:参数直接作为结构体传递,使代码更简洁、更易于阅读。
  • 错误处理:返回类型是 Result,这使得在函数内部使用 ? 运算符进行更简单的错误处理成为可能。
  • 自定义错误响应:您可以通过为 ApiError 实现 actix_web::error::ResponseError 来控制错误情况的行为。
  • 灵活的类型:函数接受 MyStruct 作为参数,并返回包装在 Result 中的 MyResponse,这使您可以为每个 API 创建独特的参数和返回类型。

使用此 crate,您可以实现更简洁、易于维护的代码结构,减少冗余,并提高您 Actix-web 应用程序的整体可读性和可维护性。

用法

创建 ApiResponse

#[derive(Serialize, Deserialize)]
pub struct ApiResponse<T> {
    pub message: String,
    pub data: T,
}

这将成为您的响应类型。

使用 Thiserror 创建 ApiError

#[derive(Error, Debug)]
pub enum ApiError {
    #[error("Invalid credentials")]
    InvalidCredentials,
// and so on
}



impl actix_web::error::ResponseError for ApiError {
    fn error_response(&self) -> actix_web::HttpResponse {
        use actix_web::http::StatusCode;

        let status_code = match self {
            ApiError::InvalidCredentials(_) => StatusCode::UNAUTHORIZED,
        };

        actix_web::HttpResponse::build(status_code).json(ApiResponse {
            message: self.to_string(),
            data: (),
        })
    }
}

在此处定义在发生错误时返回给用户的信息。由于错误类型是枚举,因此可以定义错误消息和状态而不会遗漏。

创建您的参数和返回类型

#[derive(Deserialize, Serialize)]
pub struct MyOwnQuery {
    user_name: String,
}

#[derive(Deserialize, Serialize)]
pub struct MyResponse {
    id: String,
}

请注意,Serialize 和 Deserialize 是必需的。虽然可以省略参数类型,但返回类型是必需的。

编写您的 API 逻辑

#[actix_type_handler::type_handler]
pub async fn get_user_id(
    query: MyOwnQuery,
    db_pool: web::Data<Pool<MySql>>,
    req: HttpRequest,
) -> Result<MyResponse, ApiError> {
    let user= get_user(&db_pool, &req).await?;
    Ok(MyResponse{id:user.id})
// any logic
}

特殊参数包括 query、path 和 body。

查询

query 是一个保留参数名,用于接收查询参数。例如,它对应于如 /api/search?s=123 这样的 URL。

路径

path 是一个保留参数名,用于接收路径参数。例如,它对应于如 /user/{user_id}/email 这样的 URL。

主体

body 是一个保留参数名,用于通过 POST 等接收体。

请注意,这些不是必需的参数,但如果将它们作为参数传递,它们必须命名为 query、path 或 body 才能被接受。类型名可以自由定义。

添加到您的路由器

请将 _api 添加到您定义的函数名后缀。

.route("/api/auth/register", web::post().to(auth::register_api))

依赖项

~315–780KB
~19K SLoC