http_type/response/impl.rs
1use crate::*;
2
3impl Default for Response {
4 fn default() -> Self {
5 Self::new()
6 }
7}
8
9impl Response {
10 /// Creates a new instance of `Response`.
11 ///
12 /// # Returns
13 /// - An initialized `Response` with default values.
14 pub fn new() -> Self {
15 Response {
16 version: HTTP_VERSION_1_1.to_owned(),
17 status_code: 200,
18 reason_phrase: EMPTY_STR.to_owned(),
19 headers: hash_map_xxhash3_64(),
20 body: Vec::new(),
21 }
22 }
23
24 /// Retrieves the value of a response header by its key.
25 ///
26 /// # Parameters
27 /// - `key`: The header's key, which can be of any type that implements `Into<ResponseHeadersKey>`.
28 ///
29 /// # Returns
30 /// - `OptionResponseHeadersValue`: Returns `Some(value)` if the key exists in the response headers,
31 /// or `None` if the key does not exist.
32 pub fn get_header<K>(&self, key: K) -> OptionResponseHeadersValue
33 where
34 K: Into<ResponseHeadersKey>,
35 {
36 self.headers
37 .get(&key.into())
38 .and_then(|data| Some(data.clone()))
39 }
40
41 /// Adds a header to the response.
42 ///
43 /// This function inserts a key-value pair into the response headers.
44 /// The key and value are converted into `ResponseHeadersKey`, allowing for efficient handling of both owned and borrowed string data.
45 ///
46 /// # Parameters
47 /// - `key`: The header key, which will be converted into a `ResponseHeadersKey`.
48 /// - `value`: The value of the header, which will be converted into a `ResponseHeadersValue`.
49 ///
50 /// # Returns
51 /// - Returns a mutable reference to the current instance (`&mut Self`), allowing for method chaining.
52 pub fn set_header<K, V>(&mut self, key: K, value: V) -> &mut Self
53 where
54 K: Into<ResponseHeadersKey>,
55 V: Into<ResponseHeadersValue>,
56 {
57 self.headers.insert(key.into(), value.into());
58 self
59 }
60
61 /// Set the body of the response.
62 ///
63 /// This method allows you to set the body of the response by converting the provided
64 /// value into a `ResponseBody` type. The `body` is updated with the converted value,
65 /// and the method returns a mutable reference to the current instance for method chaining.
66 ///
67 /// # Parameters
68 /// - `body`: The body of the response to be set. It can be any type that can be converted
69 /// into a `ResponseBody` using the `Into` trait.
70 ///
71 /// # Return Value
72 /// - Returns a mutable reference to the current instance of the struct, enabling method chaining.
73 /// Set the body of the response.
74 ///
75 /// This method allows you to set the body of the response by converting the provided
76 /// value into a `ResponseBody` type. The `body` is updated with the converted value,
77 /// and the method returns a mutable reference to the current instance for method chaining.
78 ///
79 /// # Parameters
80 /// - `body`: The body of the response to be set. It can be any type that can be converted
81 /// into a `ResponseBody` using the `Into` trait.
82 ///
83 /// # Return Value
84 /// - Returns a mutable reference to the current instance of the struct, enabling method chaining.
85 pub fn set_body<T: Into<ResponseBody>>(&mut self, body: T) -> &mut Self {
86 self.body = body.into();
87 self
88 }
89
90 /// Set the reason phrase of the response.
91 ///
92 /// This method allows you to set the reason phrase of the response by converting the
93 /// provided value into a `ResponseReasonPhrase` type. The `reason_phrase` is updated
94 /// with the converted value, and the method returns a mutable reference to the current
95 /// instance for method chaining.
96 ///
97 /// # Parameters
98 /// - `reason_phrase`: The reason phrase to be set for the response. It can be any type
99 /// that can be converted into a `ResponseReasonPhrase` using the `Into` trait.
100 ///
101 /// # Return Value
102 /// - Returns a mutable reference to the current instance of the struct, enabling method chaining.
103 pub fn set_reason_phrase<T: Into<ResponseReasonPhrase>>(
104 &mut self,
105 reason_phrase: T,
106 ) -> &mut Self {
107 self.reason_phrase = reason_phrase.into();
108 self
109 }
110
111 /// Pushes a header with a key and value into the response string.
112 ///
113 /// # Parameters
114 /// - `response_string`: A mutable reference to the string where the header will be added.
115 /// - `key`: The header key as a string slice (`&str`).
116 /// - `value`: The header value as a string slice (`&str`).
117 pub(super) fn push_header(response_string: &mut String, key: &str, value: &str) {
118 response_string.push_str(&format!("{}{}{}{}", key, COLON_SPACE, value, HTTP_BR));
119 }
120
121 /// Pushes the first line of an HTTP response (version, status code, and reason phrase) into the response string.
122 /// This corresponds to the status line of the HTTP response.
123 ///
124 /// # Parameters
125 /// - `response_string`: A mutable reference to the string where the first line will be added.
126 pub(super) fn push_http_response_first_line(&self, response_string: &mut String) {
127 response_string.push_str(&format!(
128 "{}{}{}{}{}{}",
129 self.get_version(),
130 SPACE,
131 self.get_status_code(),
132 SPACE,
133 self.get_reason_phrase(),
134 HTTP_BR
135 ));
136 }
137
138 /// Builds the full HTTP response as a byte vector.
139 /// # Returns
140 /// - `ResponseData`: response data
141 pub(super) fn build(&mut self) -> ResponseData {
142 if self.reason_phrase.is_empty() {
143 self.set_reason_phrase(HttpStatus::phrase(*self.get_status_code()));
144 }
145 let mut response_string: String = String::new();
146 self.push_http_response_first_line(&mut response_string);
147 let mut compress_type_opt: OptionCompress = None;
148 let mut connection_opt: OptionString = None;
149 let mut content_type_opt: OptionString = None;
150 let headers: ResponseHeaders = self
151 .get_mut_headers()
152 .drain()
153 .map(|(key, value)| (key.to_lowercase(), value))
154 .collect();
155 let mut unset_content_length: bool = false;
156 for (key, value) in headers.iter() {
157 if key == CONTENT_LENGTH {
158 continue;
159 } else if key == CONTENT_ENCODING {
160 compress_type_opt = Some(value.parse::<Compress>().unwrap_or_default());
161 } else if key == CONNECTION {
162 connection_opt = Some(value.to_owned());
163 } else if key == CONTENT_TYPE {
164 content_type_opt = Some(value.to_owned());
165 if value.to_ascii_lowercase() == TEXT_EVENT_STREAM {
166 unset_content_length = true;
167 }
168 }
169 Self::push_header(&mut response_string, key, value);
170 }
171 if connection_opt.is_none() {
172 Self::push_header(&mut response_string, CONNECTION, CONNECTION_KEEP_ALIVE);
173 }
174 if content_type_opt.is_none() {
175 Self::push_header(
176 &mut response_string,
177 CONTENT_TYPE,
178 &format!("{}{}{}", TEXT_HTML, SEMICOLON_SPACE, CHARSET_UTF_8),
179 );
180 }
181 let mut body: Cow<Vec<u8>> = Cow::Borrowed(self.get_body());
182 if !unset_content_length {
183 if let Some(compress_type) = compress_type_opt {
184 if !compress_type.is_unknown() {
185 let tmp_body: Cow<'_, Vec<u8>> =
186 compress_type.encode(&body, DEFAULT_BUFFER_SIZE);
187 body = Cow::Owned(tmp_body.into_owned());
188 }
189 }
190 let len_string: String = body.len().to_string();
191 Self::push_header(&mut response_string, CONTENT_LENGTH, &len_string);
192 }
193 response_string.push_str(HTTP_BR);
194 let mut response_bytes: Vec<u8> = response_string.into_bytes();
195 response_bytes.extend_from_slice(&body);
196 response_bytes
197 }
198
199 /// Sends the HTTP response body over a TCP stream.
200 ///
201 /// # Parameters
202 /// - `stream`: A mutable reference to the `TcpStream` to send the response.
203 /// - `is_websocket`: Is websocket
204 ///
205 /// # Returns
206 /// - `Ok`: If the response body is successfully sent.
207 /// - `Err`: If an error occurs during sending.
208 pub async fn send_body(
209 &mut self,
210 stream_lock: &ArcRwLockStream,
211 is_websocket: bool,
212 ) -> ResponseResult {
213 stream_lock.send_body(self.get_body(), is_websocket).await
214 }
215
216 /// Sends the HTTP response over a TCP stream.
217 ///
218 /// # Parameters
219 /// - `stream`: A mutable reference to the `TcpStream` to send the response.
220 ///
221 /// # Returns
222 /// - `Ok`: If the response is successfully sent.
223 /// - `Err`: If an error occurs during sending.
224 pub async fn send(&mut self, stream_lock: &ArcRwLockStream) -> ResponseResult {
225 stream_lock.send(&self.build()).await
226 }
227
228 /// Flush the TCP stream.
229 ///
230 /// - `stream_lock`: A reference to an `ArcRwLockStream` that manages the TCP stream.
231 ///
232 /// - Returns: A `ResponseResult` indicating success or failure.
233 pub async fn flush(&mut self, stream_lock: &ArcRwLockStream) -> ResponseResult {
234 stream_lock.flush().await
235 }
236
237 /// Closes the stream after sending the response.
238 ///
239 /// This function is responsible for:
240 /// - Building the response using the `build()` method.
241 /// - Setting the response using the `set_response()` method.
242 /// - Shutting down the write half of the TCP stream to indicate no more data will be sent.
243 ///
244 /// # Parameters
245 /// - `stream`: A reference to the `TcpStream` that will be closed after sending the response.
246 ///
247 /// # Returns
248 /// - `ResponseResult`: The result of the operation, indicating whether the closure was successful or if an error occurred.
249 pub async fn close(&mut self, stream_lock: &ArcRwLockStream) -> ResponseResult {
250 stream_lock.close().await
251 }
252
253 /// Converts the response to a formatted string representation.
254 ///
255 /// - Returns: A `String` containing formatted response details.
256 pub fn get_string(&self) -> String {
257 let body: &Vec<u8> = self.get_body();
258 format!(
259 "[Response] => [Version]: {}; [Status Code]: {}; [Reason]: {}; [Headers]: {:?}; [Body]: {};",
260 self.get_version(),
261 self.get_status_code(),
262 self.get_reason_phrase(),
263 self.get_headers(),
264 body_to_string(body),
265 )
266 }
267}