rocketjson_data/api/
response_err.rs

1//!# ApiResponseErr
2//! [`ApiResponseErr`] is returned by enpoints to achieve a Json response success or failure
3
4use crate::error;
5
6///Is returned by enpoints to achieve a Json response success or failure
7///Returned can be errors in [`ApiErrors`]. with `ApiResponseErr.err(...)`.
8///To forward Errors as [`ApiResponseErr`] [`rjtry`] can be used.
9///# Example
10///```
11///pub async fn db_get_users() -> Result<String, diesel::result::Error> {
12///    ...
13///}
14///
15///pub async fn is_admin() -> ApiResponseErr<bool> {
16///    let user = rjtry!(db_get_users().await);
17///    user == "admin"
18///}
19///```
20///```
21///#[derive(serde::Deserialize, validator::Validate, rocketjson::JsonBody)]
22///pub struct LoginRequest {
23///    #[validate(length(min = 1))]
24///    username: String,
25///    #[validate(length(min = 1))]
26///    password: String
27///}
28///
29///#[derive(serde::Serialize)]
30///pub struct LoginResponse {
31///    message: String
32///}
33///
34///#[post("/login", data="<data>")]
35///pub fn login(data: LoginRequest) -> rocketjson::ApiResponseErr<LoginResponse> {
36///    if data.username == "admin" && data.password == "admin" {
37///        return rocketjson::ApiResponseErr::ok(
38///            rocket::http::Status::Ok,
39///            LoginResponse{ message: "logged in" }
40///        );
41///    }
42///
43///    return rocketjson::ApiResponseErr::api_err(rocket::http::Status::InternalServerError, String::from("login failed"))
44///}
45///```
46///- Input
47///```
48///{
49///    "username": "admin",
50///    "password": "admin"
51///}
52///```
53///- Output (200 OK)
54///```
55///{
56///    "message": "logged in"
57///}
58///```
59///- Input
60///```
61///{
62///    "username": "test",
63///    "password": "test"
64///}
65///```
66///- Output (500 Internal Server Error)
67///```
68///{
69///    "error": "login failed"
70///}
71///```
72#[derive(Debug)]
73pub struct ApiResponseErr<T> {
74    /// This is the Json-data sent to the client
75    pub json: Result<rocket::serde::json::Json<T>, error::ApiErrors>,
76    /// This is the Statuscode sent to the client, it is not included in the Json
77    pub status: Option<rocket::http::Status>,
78}
79
80impl<T> ApiResponseErr<T> {
81    pub fn ok(status: rocket::http::Status, json_data: T) -> Self {
82        Self {
83            status: Some(status),
84            json: Ok(rocket::serde::json::Json::from(json_data))
85        }
86    }
87
88    pub fn api_err(status: rocket::http::Status, error: String) -> Self {
89        Self {
90            status: Some(status),
91            json: Err(error::ApiErrors::ApiError(error::ApiError::new(status, error)))
92        }
93    }
94
95    pub fn err(error: error::ApiErrors) -> Self {
96        Self {
97            status: None,
98            json: Err(error)
99        }
100    }
101
102    pub fn get_status(&self) -> rocket::http::Status {
103        if self.status.is_none() {
104            return rocket::http::Status::InternalServerError
105        }
106
107        return self.status.unwrap();
108    }
109}
110
111impl<'r, T> rocket::response::Responder<'r, 'static> for ApiResponseErr<T> where T: serde::Serialize {
112    fn respond_to(self, req: &'r rocket::request::Request<'_>) -> rocket::response::Result<'static> {
113        let status = self.get_status();
114        rocket::response::Response::build_from(self.json.respond_to(req).unwrap())
115            .status(status)
116            .header(rocket::http::ContentType::JSON)
117            .ok()
118    }
119}