Rocket: Custom Responder with Result error[E0117]

Created on 16 Jun 2019  路  2Comments  路  Source: SergioBenitez/Rocket

Hello,

I'm struggling to implement custom Error object with Result either using impl or derive I can use exclusively a custom responder using derive.
But I rather prefer to use Result giving me more flexibility on the error struct for implementing status directly.

#![feature(proc_macro_hygiene, decl_macro)]

#[macro_use] extern crate rocket;
extern crate rocket_contrib;

use serde::Serialize;
use rocket::http::Status;
use rocket::request::Request;
use rocket::response::{Response, Responder};
use rocket_contrib::json::{Json, JsonValue};
use rocket::http::ContentType;
use std::io::Cursor;

#[derive(Serialize)]
pub struct Error {
    pub message: String,
    pub error: String,
    pub code: usize,
}

#[derive(Responder)]
enum CustomResponder {
    #[response(status = 400, content_type = "json")]
    UserError(Json<Error>),

    #[response(status = 500, content_type = "json")]
    FatalError(Json<Error>),

    #[response(status = 200, content_type = "json")]
    Success(JsonValue),
}

#[get("/error")]
fn error() -> CustomResponder {
    CustomResponder::UserError(Json(Error {
        message: String::from("The code send seems wrong or expires."),
        error: String::from("Bad Authorization Code"),
        code: 10034,
    }))
}


/*#[get("/error-result-custom-responder")]
fn error_result_crs() -> Result<JsonValue, CustomResponder> {
    Err(CustomResponder::FatalError(Json(Error {
        message: String::from("The code send seems wrong or expires."),
        error: String::from("Bad Authorization Code men"),
        code: 10034,
    })))
}*/
/// Compiler fail on
/// the trait `rocket::response::Responder<'_>` is not implemented for `std::result::Result<rocket_contrib::json::JsonValue, CustomResponder>`

impl<'r> Responder<'r> for Result<JsonValue, Error> {
    fn respond_to(self, _: &Request) -> rocket::response::Result<'r> {
        match &self {
            Ok(result) => Response::build()
                .header(ContentType::JSON)
                .sized_body(Cursor::new(result.to_string()))
                .status(Status::Ok)
                .ok(),

            Err(error) => Response::build()
                .header(ContentType::JSON)
                .sized_body(Cursor::new(serde_json::to_string(&self).unwrap()))
                .status(self.status)
                .ok(),
        }
    }
}

// error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
// --> src/main.rs:54:1
//54 | impl<'r> Responder<'r> for Result<JsonValue, Error> {
//   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
//   |
//   = note: the impl does not reference only types defined in this crate
//   = note: define and implement a trait or new type instead
//
// error: aborting due to previous error

#[get("/error-result")]
fn error_result() -> Result<JsonValue, Error> {
    Err(Error {
        message: String::from("The code send seems wrong or expires."),
        error: String::from("Bad Authorization Code men"),
        code: 10034,
    })
}

fn main() {
    rocket::ignite()
        .mount("/", routes![error, error_result/*, error_result_crs*/])
        .launch()
    ;
}

duplicate question

Most helpful comment

Oh!, I've not see that, thanks!

#[derive(Serialize, Debug)]
pub struct Error {
    pub message: String,
    pub error: String,
    pub code: usize,
}

#[derive(Responder, Debug)]
enum CustomResponder {
    #[response(status = 400, content_type = "json")]
    UserError(Json<Error>),

    #[response(status = 500, content_type = "json")]
    FatalError(Json<Error>),
}

#[get("/error-result")]
fn error_result() -> Result<JsonValue, CustomResponder> {
    Err(CustomResponder::FatalError(Json(Error {
        message: String::from("The code send seems wrong or expires."),
        error: String::from("Bad Authorization Code men"),
        code: 10034,
    })))
}

All 2 comments

This looks like a duplicate of https://github.com/SergioBenitez/Rocket/issues/856#issuecomment-446260161 -- CustomResponder and Error need to implement Debug if you want to use them as error types. You don't need to implement Responder for Result; that implementation is provided by rocket.

Oh!, I've not see that, thanks!

#[derive(Serialize, Debug)]
pub struct Error {
    pub message: String,
    pub error: String,
    pub code: usize,
}

#[derive(Responder, Debug)]
enum CustomResponder {
    #[response(status = 400, content_type = "json")]
    UserError(Json<Error>),

    #[response(status = 500, content_type = "json")]
    FatalError(Json<Error>),
}

#[get("/error-result")]
fn error_result() -> Result<JsonValue, CustomResponder> {
    Err(CustomResponder::FatalError(Json(Error {
        message: String::from("The code send seems wrong or expires."),
        error: String::from("Bad Authorization Code men"),
        code: 10034,
    })))
}
Was this page helpful?
0 / 5 - 0 ratings