在自定义结构上实现 actix_web::Responder 特征

问题描述 投票:0回答:1

我正在使用 actix-web v4。

我正在尝试实现一个具有自定义结构的 Web 服务来处理错误:

pub struct ApiError {
    pub message: String,
    pub code: ErrorEnum,
    pub details: Vec<ErrorDetail>,
}

这是在失败时返回此结构的函数示例:

pub fn my_func_that_fails() -> Result<(), ApiError> {
    Err(ApiError::default())
}

我有这个函数可以将

ApiError
s 映射到
HttpResponse
s:

pub fn err_to_http(error: &ApiError) -> actix_web::HttpResponse {
    match error.code {
        ErrorEnum::NotFound => actix_web::HttpResponse::NotFound()
            .content_type("application/json; charset=utf-8")
            .json(error),
        //...
    }
}

这就是我在处理程序中使用它的方式:

pub async fn my_handler(req: actix_web::HttpRequest) -> impl actix_web::Responder {
    if let Err(e) = my_func_that_fails() {
        return err_to_http(&e);
    }
}

我希望能够这样使用它:

pub async fn my_handler(req: actix_web::HttpRequest) -> impl actix_web::Responder {
    my_func_that_fails()?;
}

为此,我需要实现特征

actix_web::Responder
,但我无法在网上找到文档来做到这一点。这是我的尝试,但我不知道要在
Body
类型中放入什么,也不知道我是否正确执行:

impl actix_web::Responder for ApiError {
    type Body = ???;

    fn respond_to(self, req: &actix_web::HttpRequest) -> actix_web::HttpResponse<Self::Body> {
        err_to_http(&self.api_error).into_future()
    }
}
rust traits actix-web
1个回答
2
投票

以下应该有效:

impl actix_web::Responder for ApiError {
    type Body = actix_web::body::BoxBody;

    fn respond_to(self, req: &actix_web::HttpRequest) -> actix_web::HttpResponse<Self::Body> {
        err_to_http(&self.api_error)
    }
}

尽管这在技术上并不准确,因为为 ApiError 实现

Responder
并不能解决你的问题。我推荐这样的东西:

pub async fn my_handler(req: actix_web::HttpRequest) -> Result<actix_web::HttpResponse, ApiError> {
    my_func_that_fails()?;
}

然后让

ApiError
实现
ResponseError
特征,如下所示:

impl actix_web::error::ResponseError for ApiError {
    fn error_response(&self) -> actix_web::HttpResponse {
        match error.code {
            ErrorEnum::NotFound => actix_web::HttpResponse::NotFound()
                .content_type("application/json; charset=utf-8")
                .json(error),
            //...
        }
    }

    fn status_code(&self) -> actix_web::http::StatusCode {
        // get status code here
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.