feather_runtime/http/
response.rs

1use bytes::Bytes; 
2use http::{HeaderMap, HeaderName, HeaderValue, StatusCode};
3use serde::Serialize;
4use std::{fmt::Display, str::FromStr};
5
6#[derive(Debug, Clone, Default)]
7pub struct HttpResponse {
8    /// The HTTP status code of the response.
9    /// This is a 3-digit integer that indicates the result of the request.
10    pub status: StatusCode,
11    /// The headers of the HTTP response.
12    /// Headers are key-value pairs that provide additional information about the response.
13    pub headers: HeaderMap,
14    /// The body of the HTTP response.
15    /// This is the content that is sent back to the client.
16    /// The body is represented as a `Bytes` object for efficient handling of binary data.
17    /// But The Other Method like `json()`,`body()`can be used to get the body in different formats.
18    pub body: Option<Bytes>, 
19    /// The HTTP version of the response.
20    pub version: http::Version, 
21}
22
23impl HttpResponse {
24    /// Sets the StatusCode of the response.
25    /// The StatusCode is a 3-digit integer that indicates the result of the request.    
26    pub fn status(&mut self,status: impl Into<StatusCode>) {
27        self.status = status.into();
28    }
29    /// Adds a header to the response.
30    /// The header is a key-value pair that provides additional information about the response.
31    pub fn add_header(&mut self, key: &str, value: &str) -> Option<()> {
32        if let Ok(val) = HeaderValue::from_str(value) {
33            if let Ok(key) = HeaderName::from_str(key) {
34                self.headers.insert(key, val);
35            }
36            return None;
37        }
38        None
39    }
40    /// Converts the `HttpResponse` into a raw HTTP response string.
41    pub fn to_string(&self) -> String {
42        let mut response = format!(
43            "HTTP/1.1 {} {}\r\n",
44            self.status.as_u16(),
45            self.status.canonical_reason().unwrap_or("Unknown")
46        );
47
48        for (key, value) in &self.headers {
49            response.push_str(&format!("{}: {}\r\n", key, value.to_str().unwrap()));
50        }
51
52        response.push_str("\r\n");
53
54        if let Some(ref body) = self.body {
55            response.push_str(&String::from_utf8_lossy(body));
56        }
57        response
58    }
59
60    /// Converts the `HttpResponse` into a raw HTTP response as bytes.
61    pub fn to_bytes(&self) -> Bytes {
62        let mut response = self.to_string().into_bytes();
63        if let Some(ref body) = self.body {
64            response.extend_from_slice(body);
65        }
66
67        Bytes::from(response)
68    }
69
70    pub fn send_text(&mut self, data: impl Into<String>) {
71        let body = data.into();
72        self.body = Some(Bytes::from(body));
73        self.headers
74            .insert("Content-Type", "text/plain".parse().unwrap());
75        self.headers.insert(
76            "Content-Length",
77            self.body
78                .as_ref()
79                .unwrap()
80                .len()
81                .to_string()
82                .parse()
83                .unwrap(),
84        );
85        self.headers.insert(
86            "Date", 
87            chrono::Utc::now().to_string().parse().unwrap()
88        );
89    }
90    pub fn send_bytes(&mut self, data: impl Into<Vec<u8>>) {
91        let body = data.into();
92        self.headers.insert(
93            "Date", 
94            chrono::Utc::now().to_string().parse().unwrap()
95        );
96        self.body = Some(Bytes::from(body));
97        self.headers.insert(
98            "Content-Length",
99            self.body
100                .as_ref()
101                .unwrap()
102                .len()
103                .to_string()
104                .parse()
105                .unwrap(),
106        );
107    }
108    pub fn send_html(&mut self, data: impl Into<String>) {
109        let body = data.into();
110        self.body = Some(Bytes::from(body));
111        self.headers.insert(
112            "Date", 
113            chrono::Utc::now().to_string().parse().unwrap()
114        );
115        self.headers
116            .insert("Content-Type", "text/html".parse().unwrap());
117        self.headers.insert(
118            "Content-Length",
119            self.body
120                .as_ref()
121                .unwrap()
122                .len()
123                .to_string()
124                .parse()
125                .unwrap(),
126        );
127    }
128    pub fn send_json<T: Serialize>(&mut self, data: T) {
129        match serde_json::to_string(&data) {
130            Ok(json) => {
131                self.body = Some(Bytes::from(json));
132                self.headers.insert(
133                    "Date", 
134                    chrono::Utc::now().to_string().parse().unwrap()
135                );
136                self.headers
137                    .insert("Content-Type", HeaderValue::from_static("application/json"));
138                self.headers.insert(
139                    "Content-Length",
140                    self.body
141                        .as_ref()
142                        .unwrap()
143                        .len()
144                        .to_string()
145                        .parse()
146                        .unwrap(),
147                );
148                
149            }
150            Err(_) => {
151                self.headers.insert(
152                    "Date", 
153                    chrono::Utc::now().to_string().parse().unwrap()
154                );
155                self.status = StatusCode::INTERNAL_SERVER_ERROR;
156                self.body = Some(Bytes::from("Internal Server Error"));
157                self.headers
158                    .insert("Content-Type", HeaderValue::from_static("text/plain"));
159                self.headers.insert(
160                    "Content-Length",
161                    self.body
162                        .as_ref()
163                        .unwrap()
164                        .len()
165                        .to_string()
166                        .parse()
167                        .unwrap(),
168                );
169                
170            }
171        }
172    }
173}
174
175
176impl Display for HttpResponse {
177    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
178        write!(f,"{}", self.to_string())
179    }
180}