如何将tera::Error转换为actix_web::Error?



我正在研究rust/actix/tera,不知道如何在tera::Error上实现ResponseError特性,或者如何将tera::Error转换为actix_web::Error

使用以下代码片段:

match TEMPLATES.render("index.html", &ctx) {
Ok(s) => Ok(HttpResponse::Ok().body(s)),
Err(e) => Err(e),
}

我得到一个错误:

mismatched types
expected struct `actix_web::Error`, found struct `tera::Error`rustc(E0308)
main.rs(71, 23): expected struct `actix_web::Error`, found struct `tera::Error`

所以我尝试了以下操作:

match TEMPLATES.render("index.html", &ctx) {
Ok(s) => Ok(HttpResponse::Ok().body(s)),
Err(e) => Err(e.into()),
}

但是在这里我得到:

the trait bound `tera::Error: actix_web::ResponseError` is not satisfied
the trait `actix_web::ResponseError` is not implemented for `tera::Error`
note: required because of the requirements on the impl of `std::convert::From<tera::Error>` for `actix_web::Error`
note: required because of the requirements on the impl of `std::convert::Into<actix_web::Error>` for `tera::Error`rustc(E0277)
main.rs(71, 25): the trait `actix_web::ResponseError` is not implemented for `tera::Error`

所以最后我试了:

use actix_web::{get, post, web, error, Error, ResponseError,
HttpRequest, HttpResponse, HttpServer,
App, Responder};
use tera::{Tera, Context};
use tera;
impl ResponseError for tera::Error {}

但现在得到:

only traits defined in the current crate can be implemented for arbitrary types
impl doesn't use only types from inside the current crate
note: define and implement a trait or new type insteadrustc(E0117)
main.rs(12, 1): impl doesn't use only types from inside the current crate
main.rs(12, 24): `tera::Error` is not defined in the current crate

我拥有match块的函数签名如下:

#[get("/")]
async fn tst() -> Result<HttpResponse, Error> {}

我做错了什么?

正如您已经发现的,into()不能用于将tera::Error转换为actix_web::Error,因为没有直接定义这种转换。在这种情况下,它会给你一个稍微误导的错误-因为这个转换存在:

impl<T> From<T> for Error
where
T: 'static + ResponseError, 

编译器抛出一个错误,表示如果只有tera错误实现了ResponseError,它就可以进行转换。但是你不能让它实现那个trait,因为"trait孤儿规则",它说你不能从你自己的crate之外把一个trait实现到你自己的crate之外的一个类型上。

您可以将tera::Error包装在您自己的结构中,然后实现ResponseError,如本问题所述。

但是有一个更简单的解决方案:actix-web提供了一整套用于转换错误的辅助函数,您可以像这样使用它们:

match TEMPLATES.render("index.html", &ctx) {
Ok(s) => Ok(HttpResponse::Ok().body(s)),
Err(e) => Err(error::ErrorInternalServerError(e)),
}

提供的帮助程序将提供的错误映射到命名的HTTP响应代码中,因此您可以选择一个最能代表发生错误的代码。

请参阅actix-web文档了解错误处理。

警告:这个解决方案是未经测试的,我从来没有使用过teraactix-web,而是我从浏览他们的文档中收集到的。

最新更新