actix_web_utils/extensions/
typed_response.rs

1use actix_web::{HttpResponse, http::StatusCode, web, HttpRequest, HttpResponseBuilder, body::BoxBody, Responder};
2use serde::Serialize;
3
4use crate::dtos::message::MessageResource;
5
6    /// Defines a type for actix web routes. As the current implementation of HttpResponse doesn't let you manually specify a type.
7    /// ```
8    /// 
9    /// use actix_web::{web::{Path}, http::StatusCode};
10    /// use actix_web_utils::extensions::typed_response::TypedHttpResponse;
11    /// use actix_web_utils::dtos::message::MessageResource;
12    /// 
13    /// //Sample route
14    /// pub async fn testroute(number: Path<i32>) -> TypedHttpResponse<String> {
15    ///     if(*number > 0){
16    ///         return TypedHttpResponse::return_standard_response(StatusCode::OK, String::from("This is my test response!")); 
17    ///     }
18    ///     TypedHttpResponse::return_empty_response(StatusCode::BAD_REQUEST)
19    /// }
20    /// 
21    /// ```
22pub struct TypedHttpResponse<B: Serialize = String> {
23    pub response: HttpResponse<Option<web::Json<Result<B, Vec<MessageResource>>>>>,
24}
25impl<B: Serialize> TypedHttpResponse<B> {
26    /// Returns a response with the json struct you define inside + Status code
27    /// ```
28    /// use actix_web_utils::extensions::typed_response::TypedHttpResponse;
29    /// 
30    /// TypedHttpResponse::return_standard_response(200, String::from("Anything in here")); //Instead of string you can put anything here as long as it is serializable.
31    /// 
32    /// ```
33    pub fn return_standard_response(status_code: u16, body: B) -> TypedHttpResponse<B>{
34        TypedHttpResponse { 
35            response: HttpResponse::with_body(StatusCode::from_u16(u16::from(status_code)).unwrap(), Some(web::Json(Ok(body))))
36        }
37    }
38    ///  Returns a response with the json error list inside + Status code
39    pub fn return_standard_error_list(status_code: u16, body: Vec<MessageResource>) -> TypedHttpResponse<B>{
40        TypedHttpResponse {
41            response: HttpResponse::with_body(StatusCode::from_u16(u16::from(status_code)).unwrap(), Some(web::Json(Err(body))))
42        }
43    }
44    /// This is to return a MessageResource wrapped inside an HttpResponse
45    pub fn return_standard_error(status_code: u16, body: MessageResource) -> TypedHttpResponse<B>{
46        TypedHttpResponse { 
47            response: HttpResponse::with_body(StatusCode::from_u16(u16::from(status_code)).unwrap(), Some(web::Json(Err(vec![body]))))
48        }
49    }
50    /// Returns an empty http response with a status code
51    /// This is a bad practice, but I still left it here
52    /// as it is useful for debugging & specific cases
53    pub fn return_empty_response(status_code: u16) -> TypedHttpResponse<B>{
54        TypedHttpResponse { 
55            response: HttpResponse::with_body(StatusCode::from_u16(u16::from(status_code)).unwrap(), None)
56        }
57    }
58}
59
60impl<T: Serialize> Responder for TypedHttpResponse<T>
61{
62    type Body = BoxBody;
63    #[inline]
64    fn respond_to(self, _: &HttpRequest) -> HttpResponse<Self::Body> {
65        let mut builder = HttpResponseBuilder::new(self.response.status());
66        match self.response.body() {
67            Some(body) => {match body.0.as_ref() {
68                Ok(value) => builder.json(value),
69                Err(errors) => builder.json(errors),
70            }},
71            None => {builder.finish()}
72        }
73    }
74}
75