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    ///
150    /// # Returns
151    /// - The serialized HTTP response including headers and body.
152    #[inline]
153    pub fn build(&mut self) -> ResponseData {
154        if self.reason_phrase.is_empty() {
155            self.set_reason_phrase(StatusCode::phrase(*self.get_status_code()));
156        }
157        let mut response_string: String = String::new();
158        self.push_http_response_first_line(&mut response_string);
159        let mut compress_type_opt: Option<Compress> = None;
160        let mut connection_opt: Option<&str> = None;
161        let mut content_type_opt: Option<&str> = None;
162        let headers: &ResponseHeaders = self.get_headers();
163        let mut unset_content_length: bool = false;
164        for (key, value) in headers {
165            if key.eq_ignore_ascii_case(CONTENT_LENGTH) {
166                continue;
167            } else if key.eq_ignore_ascii_case(CONTENT_ENCODING) {
168                compress_type_opt = Some(value.parse::<Compress>().unwrap_or_default());
169            } else if key.eq_ignore_ascii_case(CONNECTION) {
170                connection_opt = Some(value);
171            } else if key.eq_ignore_ascii_case(CONTENT_TYPE) {
172                content_type_opt = Some(value);
173                if value.eq_ignore_ascii_case(TEXT_EVENT_STREAM) {
174                    unset_content_length = true;
175                }
176            }
177            Self::push_header(&mut response_string, key, &value);
178        }
179        if connection_opt.is_none() {
180            Self::push_header(&mut response_string, CONNECTION, CONNECTION_KEEP_ALIVE);
181        }
182        if content_type_opt.is_none() {
183            Self::push_header(
184                &mut response_string,
185                CONTENT_TYPE,
186                &format!("{}{}{}", TEXT_HTML, SEMICOLON_SPACE, CHARSET_UTF_8),
187            );
188        }
189        let mut body: Cow<Vec<u8>> = Cow::Borrowed(self.get_body());
190        if !unset_content_length {
191            if let Some(compress_type) = compress_type_opt {
192                if !compress_type.is_unknown() {
193                    let tmp_body: Cow<'_, Vec<u8>> =
194                        compress_type.encode(&body, DEFAULT_BUFFER_SIZE);
195                    body = Cow::Owned(tmp_body.into_owned());
196                }
197            }
198            let len_string: String = body.len().to_string();
199            Self::push_header(&mut response_string, CONTENT_LENGTH, &len_string);
200        }
201        response_string.push_str(HTTP_BR);
202        let mut response_bytes: Vec<u8> = response_string.into_bytes();
203        response_bytes.extend_from_slice(&body);
204        self.set_response(response_bytes.clone());
205        response_bytes
206    }
207
208    /// Sends the HTTP response body over a TCP stream.
209    ///
210    /// # Parameters
211    /// - `stream`: A mutable reference to the `TcpStream` to send the response.
212    ///
213    /// # Returns
214    /// - `Ok`: If the response body is successfully sent.
215    /// - `Err`: If an error occurs during sending.
216    #[inline]
217    pub async fn send_body(&mut self, stream_lock: &ArcRwLockStream) -> ResponseResult {
218        let mut stream: RwLockWriteGuard<'_, TcpStream> = stream_lock.get_write_lock().await;
219        stream
220            .write_all(self.get_body())
221            .await
222            .map_err(|err| Error::ResponseError(err.to_string()))?;
223        stream
224            .flush()
225            .await
226            .map_err(|err| Error::ResponseError(err.to_string()))?;
227        Ok(())
228    }
229
230    /// Closes the stream after sending the response.
231    ///
232    /// This function is responsible for:
233    /// - Building the response using the `build()` method.
234    /// - Setting the response using the `set_response()` method.
235    /// - Shutting down the write half of the TCP stream to indicate no more data will be sent.
236    ///
237    /// # Parameters
238    /// - `stream`: A reference to the `TcpStream` that will be closed after sending the response.
239    ///
240    /// # Returns
241    /// - `CloseStreamResult`: The result of the operation, indicating whether the closure was successful or if an error occurred.
242    #[inline]
243    pub async fn close(&mut self, stream_lock: &ArcRwLockStream) -> ResponseResult {
244        let mut stream: RwLockWriteGuard<'_, TcpStream> = stream_lock.get_write_lock().await;
245        let _ = stream.shutdown();
246        Ok(())
247    }
248
249    /// Sends the HTTP response over a TCP stream.
250    ///
251    /// # Parameters
252    /// - `stream`: A mutable reference to the `TcpStream` to send the response.
253    ///
254    /// # Returns
255    /// - `Ok`: If the response is successfully sent.
256    /// - `Err`: If an error occurs during sending.
257    #[inline]
258    pub async fn send(&mut self, stream_lock: &ArcRwLockStream) -> ResponseResult {
259        self.build();
260        let mut stream: RwLockWriteGuard<'_, TcpStream> = stream_lock.get_write_lock().await;
261        stream
262            .write_all(&self.get_response())
263            .await
264            .map_err(|err| Error::ResponseError(err.to_string()))?;
265        stream
266            .flush()
267            .await
268            .map_err(|err| Error::ResponseError(err.to_string()))?;
269        Ok(())
270    }
271}