awpak_rs/io/request/request_data.rs
1use std::collections::HashMap;
2
3use crate::{body::body::BodyData, io::{cookies::cookies::Cookies, headers::headers::Headers}};
4
5/// Represents an incoming HTTP request.
6///
7/// This struct contains all the relevant information about an HTTP request, including the request
8/// method, URI, headers, body, and cookies. It can be accessed in an endpoint or middleware
9/// function to inspect or modify the request before generating a response.
10pub struct RequestData
11{
12 /// The URI of the request, including host, path, query parameters, and scheme.
13 ///
14 /// This contains detailed information about the requested resource.
15 ///
16 /// # Example
17 /// A request to `http://example.org:3000/hello/world?name=John` will have:
18 /// - `uri.host = Some("example.org".to_string())`
19 /// - `uri.path = "/hello/world".to_string()`
20 /// - `uri.query = Some("name=John".to_string())`
21 /// - `uri.query_map = Some(HashMap::from([("name".to_string(), "John".to_string())]))`
22 /// - `uri.port = Some(3000)`
23 /// - `uri.scheme = Some("http".to_string())`
24 pub uri : Uri,
25
26 /// The HTTP method of the request (e.g., `"get"`, `"post"`, `"put"`, etc.).
27 ///
28 /// This indicates the action the client wants to perform on the requested resource.
29 ///
30 /// # Example
31 /// ```rust
32 /// use awpak_rs::io::request::request_data::RequestData;
33 ///
34 /// let request_data = RequestData::default();
35 ///
36 /// if request_data.method == "post" {
37 /// println!("Handling a POST request");
38 /// }
39 /// ```
40 pub method : String,
41
42 /// The headers included in the request.
43 ///
44 /// Headers provide metadata about the request, such as content type, authentication tokens,
45 /// or caching information.
46 ///
47 /// # Example: Checking for an Authorization header
48 /// ```rust
49 /// use awpak_rs::io::request::request_data::RequestData;
50 ///
51 /// let request_data = RequestData::default();
52 ///
53 /// if let Some(auth_header) = request_data.headers.get_value("Authorization") {
54 /// println!("Authorization: {}", auth_header);
55 /// }
56 /// ```
57 pub headers : Headers,
58
59 /// The body of the request.
60 ///
61 /// The request body will be stored in `body.value`.
62 /// If the request is a `multipart/form-data` upload, the files will be
63 /// available in `body.files`.
64 ///
65 /// # Example: Accessing JSON data
66 /// ```rust
67 /// use awpak_rs::io::request::request_data::RequestData;
68 ///
69 /// let request_data = RequestData::default();
70 ///
71 /// if let Some(json_body) = &request_data.body.value {
72 /// println!("Received JSON: {}", json_body);
73 /// }
74 /// ```
75 ///
76 /// # Example: Handling file uploads
77 /// ```ignore
78 /// for file in &request_data.body.files {
79 /// println!("Received file: {}", file.filename);
80 /// }
81 /// ```
82 pub body : BodyData,
83
84 /// The cookies included in the request.
85 ///
86 /// Cookies are stored as key-value pairs and can be used for session management,
87 /// authentication, or storing user preferences.
88 ///
89 /// # Example: Retrieving a cookie by name
90 /// ```rust
91 /// use awpak_rs::io::request::request_data::RequestData;
92 ///
93 /// let request_data = RequestData::default();
94 ///
95 /// if let Some(cookie) = request_data.cookies.find_first_by_name("session_id") {
96 /// println!("Session ID: {}", cookie.value());
97 /// }
98 /// ```
99 pub cookies : Cookies
100}
101
102/// Represents a parsed URI from an incoming HTTP request.
103///
104/// This struct provides access to different parts of the URI, such as the host, path, query parameters, and scheme.
105///
106/// # Example
107///
108/// Given the URL:
109/// `http://example.org:3000/hello/world?name=John`
110///
111/// The `Uri` struct will contain:
112/// ```text
113/// host = Some("example.org".to_string())
114/// path = "/hello/world".to_string()
115/// query = Some("name=John".to_string())
116/// query_map = Some({ "name" => "John" })
117/// port = Some(3000)
118/// scheme = Some("http".to_string())
119/// ```
120///
121/// # Fields
122///
123/// - `host` *(optional)* – The hostname of the request (e.g., `"example.org"`).
124/// - `path` – The request path (e.g., `"/hello/world"`).
125/// - `query` *(optional)* – The raw query string (e.g., `"name=John"`).
126/// - `query_map` *(optional)* – A parsed key-value map of query parameters.
127/// - `port` *(optional)* – The port number if specified (e.g., `3000`).
128/// - `scheme` *(optional)* – The URI scheme (e.g., `"http"` or `"https"`).
129pub struct Uri
130{
131 pub host : Option<String>,
132 pub path : String,
133 pub query : Option<String>,
134 pub query_map : Option<HashMap<String, String>>,
135 pub port : Option<u16>,
136 pub scheme : Option<String>
137}
138
139impl Uri
140{
141 pub fn new(
142 host : Option<String>,
143 path : String,
144 query : Option<String>,
145 port : Option<u16>,
146 scheme : Option<String>
147 ) -> Self
148 {
149 let query = match query {
150 Some( v ) => if v.trim() == ""
151 {
152 None
153 }
154 else
155 {
156 Some( v )
157 },
158 _ => None
159 };
160
161 let query_map = Self::get_query_map( &query );
162
163 Self
164 {
165 host,
166 path,
167 query,
168 query_map,
169 port,
170 scheme
171 }
172 }
173
174 fn get_query_map( query : &Option<String> ) -> Option<HashMap<String, String>>
175 {
176 match query {
177 Some( s ) => match serde_qs::from_str::<HashMap<String, String>>( s.as_str() )
178 {
179 Ok( v ) => if v.len() > 0 {
180 Some( v )
181 }
182 else
183 {
184 None
185 },
186 _ => None
187 },
188 _ => None
189 }
190 }
191}
192
193impl Default for Uri
194{
195 fn default() -> Self
196 {
197 Self
198 {
199 host : None,
200 path : "/".to_string(),
201 query : None,
202 query_map : None,
203 port : None,
204 scheme : None
205 }
206 }
207}
208
209impl RequestData
210{
211 pub fn new( uri : Uri, method : String, headers : Headers, cookies : Cookies, body : BodyData ) -> Self
212 {
213 Self
214 {
215 uri,
216 method,
217 headers,
218 body,
219 cookies
220 }
221 }
222
223 pub fn get_headers( &self ) -> Headers
224 {
225 self.headers.clone()
226 }
227
228 pub fn get_cookies( &self ) -> Cookies
229 {
230 self.cookies.clone()
231 }
232}
233
234impl Default for RequestData
235{
236 fn default() -> Self
237 {
238 Self
239 {
240 uri : Uri::default(),
241 method : "get".to_string(),
242 headers : Headers::new(),
243 body : BodyData { value : None, files : vec![] },
244 cookies : Cookies::new()
245 }
246 }
247}