1 个不稳定版本
0.1.0 | 2023 年 6 月 22 日 |
---|
#739 在 过程宏 中
10KB
62 行代码(不含注释)
目录
这是什么?
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