1use crate::abi;
4use std::collections::HashMap;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8pub enum Method {
9 Get,
10 Post,
11 Put,
12 Delete,
13 Patch,
14 Head,
15 Options,
16 Other,
17}
18
19impl Method {
20 pub fn from_str(s: &str) -> Self {
22 match s.to_uppercase().as_str() {
23 "GET" => Method::Get,
24 "POST" => Method::Post,
25 "PUT" => Method::Put,
26 "DELETE" => Method::Delete,
27 "PATCH" => Method::Patch,
28 "HEAD" => Method::Head,
29 "OPTIONS" => Method::Options,
30 _ => Method::Other,
31 }
32 }
33
34 pub fn has_body(&self) -> bool {
36 matches!(self, Method::Post | Method::Put | Method::Patch)
37 }
38}
39
40impl std::fmt::Display for Method {
41 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42 let s = match self {
43 Method::Get => "GET",
44 Method::Post => "POST",
45 Method::Put => "PUT",
46 Method::Delete => "DELETE",
47 Method::Patch => "PATCH",
48 Method::Head => "HEAD",
49 Method::Options => "OPTIONS",
50 Method::Other => "OTHER",
51 };
52 write!(f, "{}", s)
53 }
54}
55
56pub struct Request {
61 method: Option<Method>,
62 method_str: Option<String>,
63 path: Option<String>,
64 path_segments: Option<Vec<String>>,
65 query: Option<HashMap<String, String>>,
66 query_all: Option<Vec<(String, String)>>,
67 headers: Option<HashMap<String, String>>,
68 headers_all: Option<Vec<(String, String)>>,
69 cookies: Option<HashMap<String, String>>,
70 body: Option<Vec<u8>>,
71}
72
73impl Request {
74 pub(crate) fn new() -> Self {
76 unsafe { abi::accept_request() };
78
79 Self {
80 method: None,
81 method_str: None,
82 path: None,
83 path_segments: None,
84 query: None,
85 query_all: None,
86 headers: None,
87 headers_all: None,
88 cookies: None,
89 body: None,
90 }
91 }
92
93 pub fn method(&mut self) -> Method {
95 if self.method.is_none() {
96 let method_str = self.method_str();
97 self.method = Some(Method::from_str(&method_str));
98 }
99 self.method.unwrap()
100 }
101
102 pub fn method_str(&mut self) -> String {
104 if self.method_str.is_none() {
105 self.method_str = Some(abi::read_string_from_host(|ptr, len| unsafe {
106 abi::request_get_method(ptr, len)
107 }));
108 }
109 self.method_str.clone().unwrap_or_default()
110 }
111
112 pub fn path(&mut self) -> &str {
114 if self.path.is_none() {
115 self.path = Some(abi::read_string_from_host(|ptr, len| unsafe {
116 abi::request_get_path(ptr, len)
117 }));
118 }
119 self.path.as_deref().unwrap_or("/")
120 }
121
122 pub fn path_segments(&mut self) -> &[String] {
125 if self.path_segments.is_none() {
126 let count = unsafe { abi::request_path_segment_count() };
127 let mut segments = Vec::with_capacity(count.max(0) as usize);
128
129 for i in 0..count {
130 let segment = abi::read_string_from_host(|ptr, len| unsafe {
131 abi::request_path_segment(i, ptr, len)
132 });
133 if !segment.is_empty() {
134 segments.push(segment);
135 }
136 }
137
138 self.path_segments = Some(segments);
139 }
140 self.path_segments.as_deref().unwrap_or(&[])
141 }
142
143 pub fn path_segment(&mut self, index: usize) -> Option<&str> {
146 self.path_segments().get(index).map(|s| s.as_str())
147 }
148
149 pub fn query(&mut self) -> &HashMap<String, String> {
152 if self.query.is_none() {
153 let pairs = self.query_all();
154 let mut map = HashMap::new();
155 for (k, v) in pairs {
156 map.insert(k.clone(), v.clone());
157 }
158 self.query = Some(map);
159 }
160 self.query.as_ref().unwrap()
161 }
162
163 pub fn query_all(&mut self) -> &[(String, String)] {
166 if self.query_all.is_none() {
167 let data = abi::read_bytes_from_host(|ptr, len| unsafe {
168 abi::request_query_all(ptr, len)
169 });
170 self.query_all = Some(abi::deserialize_pairs(&data));
171 }
172 self.query_all.as_deref().unwrap_or(&[])
173 }
174
175 pub fn query_param(&mut self, name: &str) -> Option<&str> {
177 self.query().get(name).map(|s| s.as_str())
178 }
179
180 pub fn headers(&mut self) -> &HashMap<String, String> {
183 if self.headers.is_none() {
184 let pairs = self.headers_all();
185 let mut map = HashMap::new();
186 for (k, v) in pairs {
187 map.insert(k.clone(), v.clone());
188 }
189 self.headers = Some(map);
190 }
191 self.headers.as_ref().unwrap()
192 }
193
194 pub fn headers_all(&mut self) -> &[(String, String)] {
196 if self.headers_all.is_none() {
197 let data = abi::read_bytes_from_host(|ptr, len| unsafe {
198 abi::request_header_all(ptr, len)
199 });
200 self.headers_all = Some(abi::deserialize_pairs(&data));
201 }
202 self.headers_all.as_deref().unwrap_or(&[])
203 }
204
205 pub fn header(&mut self, name: &str) -> Option<&str> {
207 let name_lower = name.to_lowercase();
208 self.headers().get(&name_lower).map(|s| s.as_str())
209 }
210
211 pub fn content_type(&mut self) -> Option<&str> {
213 self.header("content-type")
214 }
215
216 pub fn cookies(&mut self) -> &HashMap<String, String> {
218 if self.cookies.is_none() {
219 let data = abi::read_bytes_from_host(|ptr, len| unsafe {
220 abi::request_cookie_all(ptr, len)
221 });
222 let pairs = abi::deserialize_pairs(&data);
223 let mut map = HashMap::new();
224 for (k, v) in pairs {
225 map.insert(k, v);
226 }
227 self.cookies = Some(map);
228 }
229 self.cookies.as_ref().unwrap()
230 }
231
232 pub fn cookie(&mut self, name: &str) -> Option<&str> {
234 self.cookies().get(name).map(|s| s.as_str())
235 }
236
237 pub fn body(&mut self) -> &[u8] {
239 if self.body.is_none() {
240 let mut body = Vec::new();
242 let mut offset = 0i32;
243 let chunk_size = 4096i32;
244
245 loop {
246 let mut chunk = vec![0u8; chunk_size as usize];
247 let read = unsafe {
248 abi::request_read_body(offset, chunk.as_mut_ptr(), chunk_size)
249 };
250
251 if read <= 0 {
252 break;
253 }
254
255 chunk.truncate(read as usize);
256 body.extend_from_slice(&chunk);
257 offset += read;
258
259 if read < chunk_size {
260 break;
261 }
262 }
263
264 self.body = Some(body);
265 }
266 self.body.as_deref().unwrap_or(&[])
267 }
268
269 pub fn body_string(&mut self) -> Result<String, std::string::FromUtf8Error> {
272 String::from_utf8(self.body().to_vec())
273 }
274
275 pub fn body_json<T: serde::de::DeserializeOwned>(&mut self) -> Result<T, serde_json::Error> {
277 serde_json::from_slice(self.body())
278 }
279}
280
281impl Default for Request {
282 fn default() -> Self {
283 Self::new()
284 }
285}