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}