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()
;
}
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,
})))
}
Most helpful comment
Oh!, I've not see that, thanks!