http_type/request/impl.rs
1use super::error::Error;
2use crate::*;
3
4impl Default for Request {
5 #[inline]
6 fn default() -> Self {
7 Self {
8 method: Methods::default(),
9 host: String::new(),
10 version: HttpVersion::default(),
11 path: String::new(),
12 querys: HashMap::new(),
13 headers: HashMap::new(),
14 body: Vec::new(),
15 upgrade_type: UpgradeType::default(),
16 }
17 }
18}
19
20impl fmt::Display for Request {
21 #[inline]
22 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
23 write!(f, "{:?}", self)
24 }
25}
26
27impl Request {
28 /// Creates a new `Request` object from a TCP stream.
29 ///
30 /// # Parameters
31 /// - `reader`: A mut reference to a `&mut BufReader<&mut TcpStream>`
32 ///
33 /// # Returns
34 /// - `Ok`: A `Request` object populated with the HTTP request data.
35 /// - `Err`: An `Error` if the request is invalid or cannot be read.
36 #[inline]
37 pub async fn from_reader(reader: &mut BufReader<&mut TcpStream>) -> RequestNewResult {
38 let mut request_line: String = String::new();
39 let _ = AsyncBufReadExt::read_line(reader, &mut request_line).await;
40 let parts: Vec<&str> = request_line.split_whitespace().collect();
41 if parts.len() < 3 {
42 return Err(Error::InvalidHttpRequest);
43 }
44 let method: RequestMethod = parts[0]
45 .to_string()
46 .parse::<RequestMethod>()
47 .unwrap_or_default();
48 let full_path: RequestPath = parts[1].to_string();
49 let version: RequestVersion = parts[2]
50 .to_string()
51 .parse::<RequestVersion>()
52 .unwrap_or_default();
53 let hash_index: Option<usize> = full_path.find(HASH_SYMBOL);
54 let query_index: Option<usize> = full_path.find(QUERY_SYMBOL);
55 let query_string: String = query_index.map_or(EMPTY_STR.to_owned(), |i| {
56 let temp: String = full_path[i + 1..].to_string();
57 if hash_index.is_none() || hash_index.unwrap() <= i {
58 return temp.into();
59 }
60 let data: String = temp
61 .split(HASH_SYMBOL)
62 .next()
63 .unwrap_or_default()
64 .to_string();
65 data.into()
66 });
67 let querys: RequestQuerys = Self::parse_querys(&query_string);
68 let path: RequestPath = if let Some(i) = query_index.or(hash_index) {
69 full_path[..i].to_string()
70 } else {
71 full_path
72 };
73 let mut headers: RequestHeaders = HashMap::new();
74 let mut host: RequestHost = EMPTY_STR.to_owned();
75 let mut content_length: usize = 0;
76 loop {
77 let mut header_line: String = String::new();
78 let _ = AsyncBufReadExt::read_line(reader, &mut header_line).await;
79 let header_line: &str = header_line.trim();
80 if header_line.is_empty() {
81 break;
82 }
83 let parts: Vec<&str> = header_line.splitn(2, COLON_SPACE_SYMBOL).collect();
84 if parts.len() != 2 {
85 continue;
86 }
87 let key: String = parts[0].trim().to_string();
88 let value: String = parts[1].trim().to_string();
89 if key.eq_ignore_ascii_case(HOST) {
90 host = value.to_string();
91 }
92 if key.eq_ignore_ascii_case(CONTENT_LENGTH) {
93 content_length = value.parse().unwrap_or(0);
94 }
95 headers.insert(key, value);
96 }
97 let mut body: RequestBody = Vec::new();
98 if content_length > 0 {
99 body.resize(content_length, 0);
100 let _ = AsyncReadExt::read_exact(reader, &mut body).await;
101 }
102 let upgrade_type: UpgradeType = headers
103 .get(UPGRADE)
104 .and_then(|data| data.parse::<UpgradeType>().ok())
105 .unwrap_or_default();
106 Ok(Request {
107 method,
108 host,
109 version,
110 path,
111 querys,
112 headers,
113 body,
114 upgrade_type,
115 })
116 }
117
118 /// Creates a new `Request` object from a TCP stream.
119 ///
120 /// # Parameters
121 /// - `stream`: A reference to a `&ArcRwLockStream` representing the incoming connection.
122 /// - `is_websocket`: Is websocket
123 ///
124 /// # Returns
125 /// - `Ok`: A `Request` object populated with the HTTP request data.
126 /// - `Err`: An `Error` if the request is invalid or cannot be read.
127 #[inline]
128 pub async fn from_stream(stream: &ArcRwLockStream, is_websocket: bool) -> RequestNewResult {
129 let mut buf_stream: RwLockWriteGuard<'_, TcpStream> = stream.get_write_lock().await;
130 let mut reader: BufReader<&mut TcpStream> = BufReader::new(&mut buf_stream);
131 if is_websocket {
132 Self::from_ws_reader(&mut reader).await
133 } else {
134 Self::from_reader(&mut reader).await
135 }
136 }
137
138 /// Reads a WebSocket request from a TCP stream and constructs a `Request` object.
139 ///
140 /// This function reads data from the provided `BufReader` wrapped around a `TcpStream`.
141 /// It attempts to read up to 1024 bytes into a buffer and constructs a `Request` object
142 /// based on the received data. The request body is set using the received bytes.
143 ///
144 /// # Arguments
145 /// - `reader` - A mutable reference to a `BufReader` wrapping a `TcpStream`.
146 /// This reader is used to read the incoming WebSocket request data.
147 ///
148 /// # Returns
149 /// - `Ok(Request)` - A `Request` object constructed from the received data.
150 /// - If no data is read (`Ok(0)`), an empty `Request` object is returned.
151 /// - If data is successfully read, the request body is set with the received bytes.
152 /// - `Err(RequestError::InvalidWebSocketRequest)` - If an error occurs while reading from the stream.
153 #[inline]
154 pub async fn from_ws_reader(reader: &mut BufReader<&mut TcpStream>) -> RequestNewResult {
155 let mut buffer = [0; 1024];
156 let mut request: Request = Request::default();
157 match reader.read(&mut buffer).await {
158 Ok(0) => Ok(request),
159 Ok(n) => {
160 request.set_body(&mut buffer[..n]);
161 return Ok(request);
162 }
163 Err(_) => Err(RequestError::InvalidWebSocketRequest),
164 }
165 }
166
167 /// Parse querys
168 ///
169 /// # Parameters
170 /// - `query`: &str
171 ///
172 /// # Returns
173 /// - RequestQuerys
174 #[inline]
175 fn parse_querys(query: &str) -> RequestQuerys {
176 let mut query_map: RequestQuerys = HashMap::new();
177 for pair in query.split(AND) {
178 let mut parts: SplitN<'_, &str> = pair.splitn(2, EQUAL);
179 let key: String = parts.next().unwrap_or_default().to_string();
180 let value: String = parts.next().unwrap_or_default().to_string();
181 if !key.is_empty() {
182 query_map.insert(key, value);
183 }
184 }
185 query_map
186 }
187
188 /// Retrieves the value of a query parameter by its key.
189 ///
190 /// # Parameters
191 /// - `key`: The query parameter's key, which can be of any type that implements `Into<RequestQuerysKey>`.
192 ///
193 /// # Returns
194 /// - `Option<RequestQuerysValue>`: Returns `Some(value)` if the key exists in the query parameters,
195 /// or `None` if the key does not exist.
196 #[inline]
197 pub fn get_query<K>(&self, key: K) -> Option<RequestQuerysValue>
198 where
199 K: Into<RequestQuerysKey>,
200 {
201 self.querys
202 .get(&key.into())
203 .and_then(|data| Some(data.clone()))
204 }
205
206 /// Retrieves the value of a request header by its key.
207 ///
208 /// # Parameters
209 /// - `key`: The header's key, which can be of any type that implements `Into<RequestHeadersKey>`.
210 ///
211 /// # Returns
212 /// - `Option<RequestHeadersValue>`: Returns `Some(value)` if the key exists in the request headers,
213 /// or `None` if the key does not exist.
214 #[inline]
215 pub fn get_header<K>(&self, key: K) -> Option<RequestHeadersValue>
216 where
217 K: Into<RequestHeadersKey>,
218 {
219 self.headers
220 .get(&key.into())
221 .and_then(|data| Some(data.clone()))
222 }
223
224 /// Adds a header to the request.
225 ///
226 /// This function inserts a key-value pair into the request headers.
227 /// The key and value are converted into `String`, allowing for efficient handling of both owned and borrowed string data.
228 ///
229 /// # Parameters
230 /// - `key`: The header key, which will be converted into a `String`.
231 /// - `value`: The value of the header, which will be converted into a `String`.
232 ///
233 /// # Returns
234 /// - Returns a mutable reference to the current instance (`&mut Self`), allowing for method chaining.
235 #[inline]
236 pub fn set_header<K, V>(&mut self, key: K, value: V) -> &mut Self
237 where
238 K: Into<String>,
239 V: Into<String>,
240 {
241 self.headers.insert(key.into(), value.into());
242 self
243 }
244
245 /// Set the body of the response.
246 ///
247 /// This method allows you to set the body of the response by converting the provided
248 /// value into a `RequestBody` type. The `body` is updated with the converted value,
249 /// and the method returns a mutable reference to the current instance for method chaining.
250 ///
251 /// # Parameters
252 /// - `body`: The body of the response to be set. It can be any type that can be converted
253 /// into a `RequestBody` using the `Into` trait.
254 ///
255 /// # Return Value
256 /// - Returns a mutable reference to the current instance of the struct, enabling method chaining.
257 /// Set the body of the response.
258 ///
259 /// This method allows you to set the body of the response by converting the provided
260 /// value into a `RequestBody` type. The `body` is updated with the converted value,
261 /// and the method returns a mutable reference to the current instance for method chaining.
262 ///
263 /// # Parameters
264 /// - `body`: The body of the response to be set. It can be any type that can be converted
265 /// into a `RequestBody` using the `Into` trait.
266 ///
267 /// # Return Value
268 /// - Returns a mutable reference to the current instance of the struct, enabling method chaining.
269 #[inline]
270 pub fn set_body<T: Into<RequestBody>>(&mut self, body: T) -> &mut Self {
271 self.body = body.into();
272 self
273 }
274
275 /// Set the HTTP method of the request.
276 ///
277 /// This method allows you to set the HTTP method (e.g., GET, POST) of the request
278 /// by converting the provided value into a `RequestMethod` type. The `method` is updated
279 /// with the converted value, and the method returns a mutable reference to the current
280 /// instance for method chaining.
281 ///
282 /// # Parameters
283 /// - `method`: The HTTP method to be set for the request. It can be any type that can
284 /// be converted into a `RequestMethod` using the `Into` trait.
285 ///
286 /// # Return Value
287 /// - Returns a mutable reference to the current instance of the struct, enabling method chaining.
288 #[inline]
289 pub fn set_method<T: Into<RequestMethod>>(&mut self, method: T) -> &mut Self {
290 self.method = method.into();
291 self
292 }
293
294 /// Set the host of the request.
295 ///
296 /// This method allows you to set the host (e.g., www.example.com) for the request
297 /// by converting the provided value into a `RequestHost` type. The `host` is updated
298 /// with the converted value, and the method returns a mutable reference to the current
299 /// instance for method chaining.
300 ///
301 /// # Parameters
302 /// - `host`: The host to be set for the request. It can be any type that can be converted
303 /// into a `RequestHost` using the `Into` trait.
304 ///
305 /// # Return Value
306 /// - Returns a mutable reference to the current instance of the struct, enabling method chaining.
307 #[inline]
308 pub fn set_host<T: Into<RequestHost>>(&mut self, host: T) -> &mut Self {
309 self.host = host.into();
310 self
311 }
312
313 /// Set the path of the request.
314 ///
315 /// This method allows you to set the path (e.g., /api/v1/resource) for the request
316 /// by converting the provided value into a `RequestPath` type. The `path` is updated
317 /// with the converted value, and the method returns a mutable reference to the current
318 /// instance for method chaining.
319 ///
320 /// # Parameters
321 /// - `path`: The path to be set for the request. It can be any type that can be converted
322 /// into a `RequestPath` using the `Into` trait.
323 ///
324 /// # Return Value
325 /// - Returns a mutable reference to the current instance of the struct, enabling method chaining.
326 #[inline]
327 pub fn set_path<T: Into<RequestPath>>(&mut self, path: T) -> &mut Self {
328 self.path = path.into();
329 self
330 }
331
332 /// Sets a query parameter for the request.
333 ///
334 /// # Parameters
335 /// - `key`: The query parameter's key, which can be of any type that implements `Into<RequestQuerysKey>`.
336 /// - `value`: The query parameter's value, which can be of any type that implements `Into<RequestQuerysValue>`.
337 ///
338 /// # Returns
339 /// - Returns a mutable reference to the current instance (`Self`), allowing for method chaining.
340 #[inline]
341 pub fn set_query<K: Into<RequestQuerysKey>, V: Into<RequestQuerysValue>>(
342 &mut self,
343 key: K,
344 value: V,
345 ) -> &mut Self {
346 self.querys.insert(key.into(), value.into());
347 self
348 }
349}