use crate::helpers::http_code_helper::HttpCode;
use actix_web::http::StatusCode;
use actix_web::{web, HttpRequest, HttpResponse, Responder};
use serde::Serialize;
#[derive(Debug, Serialize, Clone)]
pub struct CustomResponse {
pub http_code: HttpCode,
pub name: String,
pub data: String,
pub description: String,
}
impl CustomResponse {
pub fn new(
code: u16,
name: impl Into<String>,
data: impl Into<String>,
description: impl Into<String>,
) -> Self {
let name_str = name.into();
let data_str = data.into();
let desc_str = description.into();
let leaked_name: &'static str = Box::leak(name_str.clone().into_boxed_str());
let leaked_desc: &'static str = Box::leak(desc_str.clone().into_boxed_str());
let resolved_http_code = HttpCode::new(code, leaked_name, leaked_desc, code, leaked_name);
Self {
http_code: resolved_http_code,
name: name_str,
data: data_str,
description: desc_str,
}
}
}
impl Responder for CustomResponse {
type Body = actix_web::body::BoxBody;
fn respond_to(self, _: &HttpRequest) -> HttpResponse<Self::Body> {
let mut response =
HttpResponse::build(StatusCode::from_u16(self.http_code.standard_code).unwrap());
response.content_type("application/json");
response.body(self.data)
}
}
pub async fn custom_response_handler(
custom_response: web::Data<CustomResponse>,
req: HttpRequest,
) -> HttpResponse {
let response = custom_response.get_ref().clone(); response.respond_to(&req)
}
#[cfg(test)]
mod tests {
use super::*;
use actix_web::HttpServer;
use actix_web::{http::StatusCode, test, web, App};
async fn example_response() -> impl Responder {
CustomResponse::new(
200,
"Success",
"{\"message\": \"Request was successful\", \"data\": \"Test data\"}",
"Test response description",
)
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| App::new().default_service(web::route().to(example_response)))
.bind("127.0.0.1:8090")?
.run()
.await
}
#[actix_web::test]
async fn test_custom_response_responder() {
let custom_response = CustomResponse {
http_code: HttpCode {
standard_code: 200,
standard_name: "OK",
unified_description: "Success",
internal_code: Some(200),
internal_name: Some("OK"),
},
name: "".to_string(),
data: "Test data".to_string(),
description: "".to_string(),
};
let app = test::init_service(
App::new()
.app_data(web::Data::new(custom_response))
.default_service(web::route().to(custom_response_handler)),
)
.await;
let req = test::TestRequest::default().to_request();
let resp = test::call_service(&app, req).await;
assert_eq!(resp.status(), StatusCode::OK);
}
#[actix_web::test]
async fn test_example_response() {
let app = test::init_service(App::new().route("/", web::get().to(example_response))).await;
let req = test::TestRequest::get().uri("/").to_request();
let resp = test::call_service(&app, req).await;
assert_eq!(resp.status(), StatusCode::OK);
let body = test::read_body(resp).await;
let body_str = String::from_utf8(body.to_vec()).unwrap();
assert!(body_str.contains("Test data"));
assert!(body_str.contains("Request was successful"));
}
}