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