I'm studying rust/actix/tera and cannot figure out how to implement ResponseError trait on the tera::Error, or alternatively how to convert tera::Error to actix_web::Error.
With the following code snippet:
match TEMPLATES.render("index.html", &ctx) {
Ok(s) => Ok(HttpResponse::Ok().body(s)),
Err(e) => Err(e),
}
I'm getting an error:
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`
So I tried the following:
match TEMPLATES.render("index.html", &ctx) {
Ok(s) => Ok(HttpResponse::Ok().body(s)),
Err(e) => Err(e.into()),
}
But in this case I get:
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`
So finally I've tried:
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 {}
But now getting:
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
Function signature in which I have the match block is the following:
#[get("/")]
async fn tst() -> Result<HttpResponse, Error> {}
What am I doing wrong?
As you have already discovered,
into()cannot be used to convert thetera::Errorto anactix_web::Errorbecause no such conversion is directly defined. In this case it gives you a slightly misleading error - because this conversion exists:The compiler throws an error saying that if only the tera error implemented
ResponseError, it could do the conversion. But you cannot make it implement that trait, because of the 'trait orphan rule', which says that you cannot implement a trait from outside your own crate onto a type from outside your own crate.You could wrap the
tera::Errorin your own struct, and then implementResponseErrorfor that, as outlined in this question.But there is a simpler solution: actix-web provides a whole swathe of helper functions for converting errors, which you can use like so:
The provided helpers map the supplied error into the named HTTP response code, so you can pick one that most closely represents the error that occurred.
See also the actix-web documentation for error handling.
Caveat Emptor: this solution is untested and I have never used
teranoractix-web, rather I gleaned this from skimming their documentation.