use actix_web::body::BoxBody; use actix_web::http::StatusCode; use actix_web::{HttpRequest, HttpResponse, Responder}; use serde::{Deserialize, Serialize}; use std::fmt; use utoipa::ToSchema; #[derive(Debug, Clone, Serialize, Deserialize, ToSchema)] pub struct NoData; #[derive(Serialize, Deserialize, Debug, Clone, ToSchema)] pub struct AppResponseData { pub code: i32, pub message: String, pub data: Option, pub error: Option, pub error_code: Option, pub request_id: String, pub log_id: String, } impl AppResponseData where T: Serialize, { pub fn ok(data: T) -> Self { AppResponseData { code: 200, message: "success".to_string(), data: Some(data), error: None, error_code: None, request_id: String::new(), log_id: String::new(), } } pub fn err(code: i32, message: impl Into) -> Self { AppResponseData { code, message: message.into(), data: None, error: None, error_code: None, request_id: String::new(), log_id: String::new(), } } pub fn err_with_detail( code: i32, message: impl Into, detail: impl Into, ) -> Self { AppResponseData { code, message: message.into(), data: None, error: Some(detail.into()), error_code: None, request_id: String::new(), log_id: String::new(), } } pub fn with_code(mut self, code: i32) -> Self { self.code = code; self } pub fn with_message(mut self, message: impl Into) -> Self { self.message = message.into(); self } pub fn with_error(mut self, error: impl Into) -> Self { self.error = Some(error.into()); self } pub fn with_error_code(mut self, code: impl Into) -> Self { self.error_code = Some(code.into()); self } pub fn with_request_id(mut self, request_id: impl Into) -> Self { self.request_id = request_id.into(); self } pub fn with_log_id(mut self, log_id: impl Into) -> Self { self.log_id = log_id.into(); self } } impl AppResponseData { pub fn empty() -> Self { AppResponseData { code: 200, message: "success".to_string(), data: None, error: None, error_code: None, request_id: String::new(), log_id: String::new(), } } } impl fmt::Display for AppResponseData<()> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "API error: code={}, message={}", self.code, self.message) } } impl Responder for AppResponseData { type Body = BoxBody; fn respond_to(mut self, _request: &HttpRequest) -> HttpResponse { let status = StatusCode::from_u16(self.code as u16).unwrap_or(StatusCode::INTERNAL_SERVER_ERROR); if self.request_id.is_empty() { self.request_id = crate::middleware::request_id().unwrap_or_default(); } if self.log_id.is_empty() { self.log_id = crate::middleware::log_id().unwrap_or_default(); } HttpResponse::build(status).json(self) } }