Skip to main content

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}