您现在的位置是:首页 > 编程 > 

【技术布局】Rust Axum 如何优雅的返回数据

2025-07-27 15:38:26
【技术布局】Rust Axum 如何优雅的返回数据 一、背景说明最近在用rust写一套web脚手架,在定义返回结果的时候发现axum自带的返回写法挺丑的,所以打算简单封装下。这一部分使用到的库主要为:axumtokioserdethiserror二、通用返回体在当前设计下,暂且假定只要服务器接收到客户端请求,统一返回状态码为200,返回的结构体中包含结果状态码、消息、内容三个部分。由于axum的返

【技术布局】Rust Axum 如何优雅的返回数据

一、背景说明

最近在用rust写一套web脚手架,在定义返回结果的时候发现axum自带的返回写法挺丑的,所以打算简单封装下。这一部分使用到的库主要为:

  • axum
  • tokio
  • serde
  • thiserror

二、通用返回体

在当前设计下,暂且假定只要服务器接收到客户端请求,统一返回状态码为200,返回的结构体中包含结果状态码、消息、内容三个部分。由于axum的返回都需要实现IntoRespe trait。同时再为它提供两个方法用于创建对象。

代码语言:rust复制
use axum::http::StatusCode;
use axum::{respe::IntoRespe, Json};
use serde::Serialize;
use serde_json::json;

// 成功响应码和信息
ct SUCCESS_CODE: i2 = StatusCode::OK.as_u16() as i2;
ct SUCCESS_MESSAGE: &str = "success";

/// 响应结构体
#[derive(Debug, Serialize)]
pub struct ApiResult<T> {
    code: i2,       // 响应码,通常用于表示请求的结果状态
    data: Option<T>, // 可选的数据部分,包含请求成功时返回的数据
    message: String, // 响应信息,描述请求的结果或错误信息
}

// 实现 `IntoRespe` trait 以将 ApiResult 转换为 Axum 响应
impl<T: Serialize> IntoRespe for ApiResult<T> {
    fn into_respe(self) -> axum::respe::Respe {
        let val = json!(self); // 将 ApiResult 转换为 JSO 格式
        Json(val).into_respe() // 将 JSO 响应转换为 Axum 的响应格式
    }
}

// 封装成功和错误响应
impl<T> ApiResult<T> {
    /// 成功响应
    /// 响应码为 200, 响应信息为 "success", data 为传入的 data 可选
    pub fn success(data: T) -> Self {
        Self {
            code: SUCCESS_CODE, // 成功状态码
            data: Some(data),                     // 包含成功时返回的数据
            message: SUCCESS__owned(),     // 成功信息
        }
    }

    /// 错误响应
    /// 指定错误码和错误信息
    pub fn error(code: i2, message: String) -> Self {
        Self {
            code: code,       // 错误状态码
            data: one,       // 不包含数据
            message: message, // 错误信息
        }
    }
}

三、通用异常

在系统中提供一个统一的全局异常,包装所有其他的异常,并且提供可扩展的异常信息。然后为它实现IntoRespe的trait,将所有异常信息匹配为ApiResult对象返回给客户端。

下面代码中的 DatabaseError 是匹配该异常,创建为ApiError异常。

同时提供一个map_db_error方法,用于在可能会抛出sea_orm::DbErr的地方通过.map_err(map_db_error)来转化成ApiErr并向上抛出。

代码语言:rust复制
use axum::{
    http::StatusCode,
    respe::{IntoRespe, Respe},
};
use thiserror::Error;

use super::api_result::ApiResult;

/// 定义 API 错误类型
#[derive(Error, Debug)]
pub enum ApiError {

    // 数据库错误,允许将 sea_orm::DbErr  转换为 ApiError
    #[error(transparent)] 
    DatabaseError(#[from] sea_orm::DbErr),

    // 其他错误,包含错误信息
    #[error("服务异常: {0}")]
    OtherError(String),
}

/// 实现 IntoRespe trait 以将 ApiError 转换为 Axum 响应
impl IntoRespe for ApiError {
    fn into_respe(self) -> Respe {
        // 根据错误类型生成相应的状态码和消息
        let (status_code, message) = match &self {
            ApiError::DatabaseError(msg) => (StatusCode::ITERAL_SERVER_ERROR, _string()),
            ApiError::OtherError(msg) => (StatusCode::ITERAL_SERVER_ERROR, _string()),
        };

        // 构建 ApiResult 错误响应并转换为 Axum 响应
        let into_respe_tuple = (
            StatusCode::OK, // 这里的状态码可以根据需要调整
            ApiResult::<()>::error(status_code.as_u16() as i2, message), // 使用 ApiResult 构建错误响应
        )
            .into_respe();

        into_respe_tuple.into_respe() // 返回最终的响应
    }
}

pub fn map_db_error(err: sea_orm::DbErr) -> ApiError {
    ApiError::DatabaseError(err)
}

四、路由handler

项目中所有的路由handler都统一返回Result<ApiResult<T>,ApiError>结构。

代码语言:rust复制
pub async fn test_handler() -> Result<ApiResult<ResStruct>, ApiError> {
    let res = ResStruct {}
    Ok(ApiResult::success(res))
}

五、请求处理

一般不会在handler中直接处理请求,所以会有一个单独的处理函数,处理函数一般情况返回Result<ResStruct,ApiError>对象,如果遇到其他可能会抛出的异常,则通过map_err函数传入对应的转化函数来转化成ApiError。如下,在发生异常时转化为ApiError返回,如果处理正常则返回实际结果。

代码语言:rust复制
let async fn test_service(db: &DatabaseConnection) 
    ->  Result<system_account::Entity, ApiError> {
    let option = system_account::Entity::find()
        .filter(system_account::Column::(login_req.()))
        .order_by_asc(system_account::Column::Id)
        .one(db)
        .await
        .map_err(map_db_error)?; // 这里转化数据库异常为ApiError

    if option.is_none() {
        // 这里返回自定义的异常信息
        return Err(ApiError::OtherError("用户不存在!".to_string()));
    }
    Ok(option.unwrap())
}

六、结果展示

附上两张请求通过和异常的截图:

成功请求
返回异常

#感谢您对电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格的认可,转载请说明来源于"电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格

本文地址:http://www.dnpztj.cn/biancheng/1174447.html

相关标签:无
上传时间: 2025-07-21 14:14:24
留言与评论(共有 18 条评论)
本站网友 温江二手房
17分钟前 发表
处理函数一般情况返回Result<ResStruct
本站网友 天津搜房网二手房
29分钟前 发表
本站网友 老牛自知夕阳晚
10分钟前 发表
// 使用 ApiResult 构建错误响应 ) .into_respe(); into_respe_tuple.into_respe() // 返回最终的响应 } } pub fn map_db_error(err
本站网友 罗汉果泡水喝的功效
27分钟前 发表
返回的结构体中包含结果状态码
本站网友 过塘蛇
3分钟前 发表
Serialize; use serde_json
本站网友 东阿房屋出租
15分钟前 发表
{0}")] OtherError(String)
本站网友 csdn登录
25分钟前 发表
error(status_code.as_u16() as i2
本站网友 真艾叶和假艾叶图片
0秒前 发表
// 错误信息 } } }三
本站网友 长期食用螺旋藻至胃癌
15分钟前 发表
本站网友 藿香的功效与作用
4分钟前 发表
ApiError> { let res = ResStruct {} Ok(ApiResult
本站网友 孙开林
6分钟前 发表
DbErr的地方通过.map_err(map_db_error)来转化成ApiErr并向上抛出
本站网友 清淡的菜
6分钟前 发表
通用异常在系统中提供一个统一的全局异常
本站网友 泉州美容培训
4分钟前 发表
如下
本站网友 我可以摸你的胸吗
23分钟前 发表
(login_req.())) .order_by_asc(system_account
本站网友 橄榄油什么作用
1分钟前 发表
// 其他错误
本站网友 无线路由器信号增强
15分钟前 发表
如果处理正常则返回实际结果
本站网友 修护霜
27分钟前 发表