I'm using actix-web v4.
I'm trying to implement a web service with a custom structure for handling errors:
pub struct ApiError {
pub message: String,
pub code: ErrorEnum,
pub details: Vec<ErrorDetail>,
}
This is an example of function that returns this structure on a failure:
pub fn my_func_that_fails() -> Result<(), ApiError> {
Err(ApiError::default())
}
I have this function to map ApiError
s to 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),
//...
}
}
This is how I use it in a handler:
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);
}
}
I would like to be able to use it this way:
pub async fn my_handler(req: actix_web::HttpRequest) -> impl actix_web::Responder {
my_func_that_fails()?;
}
For this I need to implement the trait actix_web::Responder
, but I can't find documentation online to do that. This is my attempt at doing it, but I don't know what to put in the Body
type, nor if I'm doing it correctly:
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()
}
}
The following should work:
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)
}
}
Although, this technically isn't accurate because implementing Responder
for ApiError will not solve your problem. I recommend something like this instead:
pub async fn my_handler(req: actix_web::HttpRequest) -> Result<actix_web::HttpResponse, ApiError> {
my_func_that_fails()?;
}
and then have ApiError
implement the ResponseError
trait, like so:
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
}
}