1use std::collections::HashMap;
2use std::any::{Any, TypeId};
3use std::sync::Arc;
4use http::{HeaderMap, Method, Uri, Version};
5use http_body_util::BodyExt;
6use hyper::body::Incoming;
7use crate::extractors::state::StateMap;
8
9#[derive(Debug)]
11pub struct Request {
12 method: Method,
13 uri: Uri,
14 version: Version,
15 headers: HeaderMap,
16 body: Vec<u8>,
17 params: HashMap<String, String>,
18 query: HashMap<String, String>,
19 extensions: HashMap<TypeId, Box<dyn Any + Send + Sync>>,
20}
21
22impl Request {
23 pub fn new() -> Self {
25 Self {
26 method: Method::GET,
27 uri: "/".parse().unwrap(),
28 version: Version::HTTP_11,
29 headers: HeaderMap::new(),
30 body: Vec::new(),
31 params: HashMap::new(),
32 query: HashMap::new(),
33 extensions: HashMap::new(),
34 }
35 }
36
37 pub async fn from_hyper(
39 parts: http::request::Parts,
40 body: Incoming,
41 ) -> Result<Self, Box<dyn std::error::Error + Send + Sync>> {
42 let body_bytes = body.collect().await?.to_bytes().to_vec();
43
44 let query = Self::parse_query_string(parts.uri.query().unwrap_or(""));
45
46 Ok(Request {
47 method: parts.method,
48 uri: parts.uri,
49 version: parts.version,
50 headers: parts.headers,
51 body: body_bytes,
52 params: HashMap::new(),
53 query,
54 extensions: HashMap::new(),
55 })
56 }
57
58 pub fn method(&self) -> &Method {
60 &self.method
61 }
62
63 pub fn uri(&self) -> &Uri {
65 &self.uri
66 }
67
68 pub fn path(&self) -> &str {
70 self.uri.path()
71 }
72
73 pub fn version(&self) -> Version {
75 self.version
76 }
77
78 pub fn headers(&self) -> &HeaderMap {
80 &self.headers
81 }
82
83 pub fn header(&self, name: &str) -> Option<&str> {
85 self.headers.get(name)?.to_str().ok()
86 }
87
88 pub fn body(&self) -> &[u8] {
90 &self.body
91 }
92
93 pub fn body_string(&self) -> Result<String, std::string::FromUtf8Error> {
95 String::from_utf8(self.body.clone())
96 }
97
98 #[cfg(feature = "json")]
100 pub async fn json<T>(&self) -> Result<T, serde_json::Error>
101 where
102 T: serde::de::DeserializeOwned,
103 {
104 serde_json::from_slice(&self.body)
105 }
106
107 pub fn param(&self, name: &str) -> Option<&str> {
109 self.params.get(name).map(|s| s.as_str())
110 }
111
112 pub fn params(&self) -> &HashMap<String, String> {
114 &self.params
115 }
116
117 pub fn path_params(&self) -> &HashMap<String, String> {
119 &self.params
120 }
121
122 pub(crate) fn set_param(&mut self, name: String, value: String) {
124 self.params.insert(name, value);
125 }
126
127 pub fn extensions(&self) -> &HashMap<TypeId, Box<dyn Any + Send + Sync>> {
129 &self.extensions
130 }
131
132 pub fn extensions_mut(&mut self) -> &mut HashMap<TypeId, Box<dyn Any + Send + Sync>> {
134 &mut self.extensions
135 }
136
137 pub fn insert_extension<T: Send + Sync + 'static>(&mut self, value: T) {
139 self.extensions.insert(TypeId::of::<T>(), Box::new(value));
140 }
141
142 pub fn get_extension<T: Send + Sync + 'static>(&self) -> Option<&T> {
144 self.extensions
145 .get(&TypeId::of::<T>())
146 .and_then(|boxed| boxed.downcast_ref())
147 }
148
149 pub fn query(&self, name: &str) -> Option<&str> {
151 self.query.get(name).map(|s| s.as_str())
152 }
153
154 pub fn query_params(&self) -> &HashMap<String, String> {
156 &self.query
157 }
158
159 pub fn query_string(&self) -> Option<&str> {
161 self.uri.query()
162 }
163
164 pub fn body_bytes(&self) -> &[u8] {
166 &self.body
167 }
168
169 #[cfg(test)]
171 pub fn set_body(&mut self, body: Vec<u8>) {
172 self.body = body;
173 }
174
175 pub fn headers_mut(&mut self) -> &mut HeaderMap {
177 &mut self.headers
178 }
179
180 fn parse_query_string(query: &str) -> HashMap<String, String> {
182 let mut params = HashMap::new();
183
184 for pair in query.split('&') {
185 if let Some((key, value)) = pair.split_once('=') {
186 let key = urlencoding::decode(key).unwrap_or_else(|_| key.into()).into_owned();
187 let value = urlencoding::decode(value).unwrap_or_else(|_| value.into()).into_owned();
188 params.insert(key, value);
189 } else if !pair.is_empty() {
190 let key = urlencoding::decode(pair).unwrap_or_else(|_| pair.into()).into_owned();
191 params.insert(key, String::new());
192 }
193 }
194
195 params
196 }
197}
198
199impl crate::extractors::state::RequestStateExt for Request {
201 fn get_state(&self, type_id: TypeId) -> Option<&Arc<dyn Any + Send + Sync>> {
202 if let Some(state_map_any) = self.extensions.get(&TypeId::of::<StateMap>()) {
204 if let Some(state_map) = state_map_any.downcast_ref::<StateMap>() {
205 return state_map.get_by_type_id(type_id);
206 }
207 }
208 None
209 }
210
211 fn set_state_map(&mut self, state_map: StateMap) {
212 self.extensions.insert(TypeId::of::<StateMap>(), Box::new(state_map));
213 }
214
215 fn state_map(&self) -> Option<&StateMap> {
216 self.extensions
217 .get(&TypeId::of::<StateMap>())
218 .and_then(|state_map_any| state_map_any.downcast_ref::<StateMap>())
219 }
220}
221
222#[cfg(test)]
223mod tests {
224 use super::*;
225 #[test]
228 fn test_parse_query_string() {
229 let query = "name=John&age=30&city=New%20York";
230 let params = Request::parse_query_string(query);
231
232 assert_eq!(params.get("name"), Some(&"John".to_string()));
233 assert_eq!(params.get("age"), Some(&"30".to_string()));
234 assert_eq!(params.get("city"), Some(&"New York".to_string()));
235 }
236
237 #[test]
238 fn test_parse_empty_query_string() {
239 let params = Request::parse_query_string("");
240 assert!(params.is_empty());
241 }
242}