// StarKingdoms.IO, a browser game about drifting through space // Copyright (C) 2023 ghostly_zsh, TerraMaster85, core // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . use crate::error::APIErrorsResponse; use actix_web::body::BoxBody; use actix_web::error::JsonPayloadError; use actix_web::http::StatusCode; use actix_web::{HttpRequest, HttpResponse, Responder}; use serde::Serialize; use std::fmt::{Debug, Display, Formatter}; #[derive(Debug)] pub enum JsonAPIResponse { Error(StatusCode, APIErrorsResponse), Success(StatusCode, T), } impl Display for JsonAPIResponse { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "{:?}", self) } } impl Responder for JsonAPIResponse { type Body = BoxBody; fn respond_to(self, _: &HttpRequest) -> HttpResponse { match self { JsonAPIResponse::Error(c, r) => match serde_json::to_string(&r) { Ok(body) => HttpResponse::build(c).body(body), Err(err) => HttpResponse::from_error(JsonPayloadError::Serialize(err)), }, JsonAPIResponse::Success(c, b) => match serde_json::to_string(&b) { Ok(body) => HttpResponse::build(c).body(body), Err(err) => HttpResponse::from_error(JsonPayloadError::Serialize(err)), }, } } } #[macro_export] macro_rules! err { ($c:expr,$e:expr) => { return $crate::response::JsonAPIResponse::Error($c, $e) }; } #[macro_export] macro_rules! ok { ($c:expr,$e:expr) => { return $crate::response::JsonAPIResponse::Success($c, $e) }; ($e:expr) => { return $crate::response::JsonAPIResponse::Success(actix_web::http::StatusCode::OK, $e) }; } #[macro_export] macro_rules! internal_error { ($e:expr) => {{ log::error!("internal error: {}", $e); $crate::err!( actix_web::http::StatusCode::INTERNAL_SERVER_ERROR, $crate::make_err!("ERR_INTERNAL_ERROR", $e) ); }}; } #[macro_export] macro_rules! handle_error { ($e:expr,$c:expr,$r:expr) => { match $e { Ok(r) => r, Err(e) => { log::error!("error: {}", e); $crate::err!($c, $r) } } }; ($e:expr) => { match $e { Ok(r) => r, Err(e) => { $crate::internal_error!(e) } } }; } #[macro_export] macro_rules! make_err { ($c:expr,$m:expr,$p:expr) => { $crate::error::APIErrorsResponse { errors: vec![$crate::error::APIErrorResponse { code: $c.to_string(), message: $m.to_string(), path: Some($p.to_string()), }], } }; ($c:expr,$m:expr) => { $crate::error::APIErrorsResponse { errors: vec![$crate::error::APIErrorResponse { code: $c.to_string(), message: $m.to_string(), path: None, }], } }; }