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