http_type/response/
impl.rs

1use super::error::Error;
2use crate::*;
3
4impl Default for Response {
5    #[inline]
6    fn default() -> Self {
7        Self::new()
8    }
9}
10
11impl Response {
12    /// Creates a new instance of `Response`.
13    ///
14    /// # Returns
15    /// - An initialized `Response` with default values.
16    #[inline]
17    pub fn new() -> Self {
18        Response {
19            version: HTTP_VERSION_1_1.to_owned(),
20            status_code: 200,
21            reason_phrase: EMPTY_STR.to_owned(),
22            headers: HashMap::new(),
23            body: Vec::new(),
24            response: Vec::new(),
25        }
26    }
27
28    /// Retrieves the value of a response header by its key.
29    ///
30    /// # Parameters
31    /// - `key`: The header's key, which can be of any type that implements `Into<ResponseHeadersKey>`.
32    ///
33    /// # Returns
34    /// - `Option<ResponseHeadersValue>`: Returns `Some(value)` if the key exists in the response headers,
35    ///   or `None` if the key does not exist.
36    #[inline]
37    pub fn get_header<K>(&self, key: K) -> Option<ResponseHeadersValue>
38    where
39        K: Into<ResponseHeadersKey>,
40    {
41        self.headers
42            .get(&key.into())
43            .and_then(|data| Some(data.clone()))
44    }
45
46    /// Adds a header to the response.
47    ///
48    /// This function inserts a key-value pair into the response headers.
49    /// The key and value are converted into `ResponseHeadersKey`, allowing for efficient handling of both owned and borrowed string data.
50    ///
51    /// # Parameters
52    /// - `key`: The header key, which will be converted into a `ResponseHeadersKey`.
53    /// - `value`: The value of the header, which will be converted into a `ResponseHeadersValue`.
54    ///
55    /// # Returns
56    /// - Returns a mutable reference to the current instance (`&mut Self`), allowing for method chaining.
57    #[inline]
58    pub fn set_header<K, V>(&mut self, key: K, value: V) -> &mut Self
59    where
60        K: Into<ResponseHeadersKey>,
61        V: Into<ResponseHeadersValue>,
62    {
63        self.headers.insert(key.into(), value.into());
64        self
65    }
66
67    /// Set the body of the response.
68    ///
69    /// This method allows you to set the body of the response by converting the provided
70    /// value into a `ResponseBody` type. The `body` is updated with the converted value,
71    /// and the method returns a mutable reference to the current instance for method chaining.
72    ///
73    /// # Parameters
74    /// - `body`: The body of the response to be set. It can be any type that can be converted
75    ///   into a `ResponseBody` using the `Into` trait.
76    ///
77    /// # Return Value
78    /// - Returns a mutable reference to the current instance of the struct, enabling method chaining.
79    /// Set the body of the response.
80    ///
81    /// This method allows you to set the body of the response by converting the provided
82    /// value into a `ResponseBody` type. The `body` is updated with the converted value,
83    /// and the method returns a mutable reference to the current instance for method chaining.
84    ///
85    /// # Parameters
86    /// - `body`: The body of the response to be set. It can be any type that can be converted
87    ///   into a `ResponseBody` using the `Into` trait.
88    ///
89    /// # Return Value
90    /// - Returns a mutable reference to the current instance of the struct, enabling method chaining.
91    #[inline]
92    pub fn set_body<T: Into<ResponseBody>>(&mut self, body: T) -> &mut Self {
93        self.body = body.into();
94        self
95    }
96
97    /// Set the reason phrase of the response.
98    ///
99    /// This method allows you to set the reason phrase of the response by converting the
100    /// provided value into a `ResponseReasonPhrase` type. The `reason_phrase` is updated
101    /// with the converted value, and the method returns a mutable reference to the current
102    /// instance for method chaining.
103    ///
104    /// # Parameters
105    /// - `reason_phrase`: The reason phrase to be set for the response. It can be any type
106    ///   that can be converted into a `ResponseReasonPhrase` using the `Into` trait.
107    ///
108    /// # Return Value
109    /// - Returns a mutable reference to the current instance of the struct, enabling method chaining.
110    #[inline]
111    pub fn set_reason_phrase<T: Into<ResponseReasonPhrase>>(
112        &mut self,
113        reason_phrase: T,
114    ) -> &mut Self {
115        self.reason_phrase = reason_phrase.into();
116        self
117    }
118
119    /// Pushes a header with a key and value into the response string.
120    ///
121    /// # Parameters
122    /// - `response_string`: A mutable reference to the string where the header will be added.
123    /// - `key`: The header key as a string slice (`&str`).
124    /// - `value`: The header value as a string slice (`&str`).
125    #[inline]
126    pub(super) fn push_header(response_string: &mut String, key: &str, value: &str) {
127        response_string.push_str(&format!("{}{}{}{}", key, COLON_SPACE, value, HTTP_BR));
128    }
129
130    /// Pushes the first line of an HTTP response (version, status code, and reason phrase) into the response string.
131    /// This corresponds to the status line of the HTTP response.
132    ///
133    /// # Parameters
134    /// - `response_string`: A mutable reference to the string where the first line will be added.
135    #[inline]
136    pub(super) fn push_http_response_first_line(&self, response_string: &mut String) {
137        response_string.push_str(&format!(
138            "{}{}{}{}{}{}",
139            self.get_version(),
140            SPACE,
141            self.get_status_code(),
142            SPACE,
143            self.get_reason_phrase(),
144            HTTP_BR
145        ));
146    }
147
148    /// Builds the full HTTP response as a byte vector.
149    #[inline]
150    pub(super) fn build(&mut self) {
151        if self.reason_phrase.is_empty() {
152            self.set_reason_phrase(StatusCode::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<&str> = None;
158        let mut content_type_opt: Option<&str> = None;
159        let headers: &ResponseHeaders = self.get_headers();
160        let mut unset_content_length: bool = false;
161        for (key, value) in headers {
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);
168            } else if key.eq_ignore_ascii_case(CONTENT_TYPE) {
169                content_type_opt = Some(value);
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        self.set_response(response_bytes);
202    }
203
204    /// Builds the full HTTP response body as a byte vector.
205    #[inline]
206    pub(super) fn build_body(&mut self) {
207        self.set_response(self.get_body().clone());
208    }
209
210    /// Sends the HTTP response body over a TCP stream.
211    ///
212    /// # Parameters
213    /// - `stream`: A mutable reference to the `TcpStream` to send the response.
214    /// - `is_websocket`: Is websocket
215    ///
216    /// # Returns
217    /// - `Ok`: If the response body is successfully sent.
218    /// - `Err`: If an error occurs during sending.
219    #[inline]
220    pub async fn send_body(
221        &mut self,
222        stream_lock: &ArcRwLockStream,
223        is_websocket: bool,
224    ) -> ResponseResult {
225        self.build_body();
226        let body: &ResponseBody = self.get_body();
227        let mut stream: RwLockWriteGuardTcpStream = stream_lock.get_write_lock().await;
228        let body_list: Vec<ResponseBody> = if is_websocket {
229            WebSocketFrame::create_response_frame_list(body)
230        } else {
231            vec![body.clone()]
232        };
233        for tmp_body in body_list {
234            stream
235                .write_all(&tmp_body)
236                .await
237                .map_err(|err| Error::ResponseError(err.to_string()))?;
238        }
239        Ok(())
240    }
241
242    /// Closes the stream after sending the response.
243    ///
244    /// This function is responsible for:
245    /// - Building the response using the `build()` method.
246    /// - Setting the response using the `set_response()` method.
247    /// - Shutting down the write half of the TCP stream to indicate no more data will be sent.
248    ///
249    /// # Parameters
250    /// - `stream`: A reference to the `TcpStream` that will be closed after sending the response.
251    ///
252    /// # Returns
253    /// - `ResponseResult`: The result of the operation, indicating whether the closure was successful or if an error occurred.
254    #[inline]
255    pub async fn close(&mut self, stream_lock: &ArcRwLockStream) -> ResponseResult {
256        let mut stream: RwLockWriteGuardTcpStream = stream_lock.get_write_lock().await;
257        stream
258            .shutdown()
259            .await
260            .map_err(|err| ResponseError::CloseError(err.to_string()))
261    }
262
263    /// Sends the HTTP response over a TCP stream.
264    ///
265    /// # Parameters
266    /// - `stream`: A mutable reference to the `TcpStream` to send the response.
267    ///
268    /// # Returns
269    /// - `Ok`: If the response is successfully sent.
270    /// - `Err`: If an error occurs during sending.
271    #[inline]
272    pub async fn send(&mut self, stream_lock: &ArcRwLockStream) -> ResponseResult {
273        self.build();
274        let mut stream: RwLockWriteGuardTcpStream = stream_lock.get_write_lock().await;
275        stream
276            .write_all(&self.get_response())
277            .await
278            .map_err(|err| Error::ResponseError(err.to_string()))?;
279        Ok(())
280    }
281
282    /// Flush the TCP stream.
283    ///
284    /// - `stream_lock`: A reference to an `ArcRwLockStream` that manages the TCP stream.
285    ///
286    /// - Returns: A `ResponseResult` indicating success or failure.
287    #[inline]
288    pub async fn flush(&mut self, stream_lock: &ArcRwLockStream) -> ResponseResult {
289        let mut stream: RwLockWriteGuardTcpStream = stream_lock.get_write_lock().await;
290        stream
291            .flush()
292            .await
293            .map_err(|err| Error::ResponseError(err.to_string()))?;
294        Ok(())
295    }
296}