1use super::error::{Error, HTTPBodyTooLargeError, HeaderError, HttpError, UriError};
6use super::stream::{BaseStream, ReadStream};
7use http::Uri;
8use http::{header::HeaderName, HeaderMap, Version};
9use num_derive::FromPrimitive;
10use num_traits::FromPrimitive;
11use std::str;
12use std::str::FromStr;
13use std::{collections::HashMap, convert::TryFrom};
14use url::form_urlencoded;
15
16#[link(wasm_import_module = "request")]
17extern "C" {
18 fn http_cur_req_get_method() -> i32;
19 fn http_cur_req_get_uri(err_code: *mut i32) -> i32;
20 fn http_cur_req_get_body(error_code: *mut i32) -> i32;
21 fn http_cur_req_get_read_stream(read_sd: *mut u32) -> i32;
22 fn http_cur_req_get_all_header_keys(err_code: *mut i32) -> i32;
23 fn http_cur_req_get_header_value(
24 header_ptr: *const u8,
25 header_len: i32,
26 err_code: *mut i32,
27 ) -> i32;
28}
29
30#[derive(Debug)]
33pub struct HttpRequest {
34 version: Version,
35 method: HttpMethod,
36 uri: Uri,
37 headers: HeaderMap,
38 body: Option<Vec<u8>>,
39 read_stream: Option<ReadStream>,
40}
41
42#[derive(Debug, FromPrimitive, PartialEq)]
44pub enum HttpMethod {
45 NONE = 0,
46 GET = 1,
47 HEAD = 2,
48 POST = 3,
49 PUT = 4,
50 DELETE = 5,
51 CONNECT = 6,
52 OPTIONS = 7,
53 TRACE = 8,
54 PATCH = 9,
55}
56
57impl FromStr for HttpMethod {
58 type Err = ();
59
60 fn from_str(input: &str) -> Result<HttpMethod, Self::Err> {
61 match input.to_uppercase().as_str() {
62 "GET" => Ok(HttpMethod::GET),
63 "HEAD" => Ok(HttpMethod::HEAD),
64 "POST" => Ok(HttpMethod::POST),
65 "PUT" => Ok(HttpMethod::PUT),
66 "DELETE" => Ok(HttpMethod::DELETE),
67 "CONNECT" => Ok(HttpMethod::CONNECT),
68 "OPTIONS" => Ok(HttpMethod::OPTIONS),
69 "TRACE" => Ok(HttpMethod::TRACE),
70 "PATCH" => Ok(HttpMethod::PATCH),
71 _ => Ok(HttpMethod::NONE),
72 }
73 }
74}
75
76impl HttpRequest {
77 pub fn from_client() -> Result<HttpRequest, HttpError> {
110 let mut headers = HeaderMap::new();
111 let header_keys = get_all_header_keys_from_host()?;
112 for key in header_keys {
113 headers.insert(
114 HeaderName::from_str(key.as_str()).unwrap(),
115 get_header_value_from_host(key.as_str())?.parse().unwrap(),
116 );
117 }
118
119 Ok(HttpRequest {
120 version: Version::HTTP_11,
121 method: get_method_from_host(),
122 uri: get_uri_from_host()?,
123 headers: headers,
124 body: None,
125 read_stream: None,
126 })
127 }
128
129 pub fn method(&self) -> &HttpMethod {
143 return &self.method;
144 }
145
146 pub fn uri(&self) -> &Uri {
161 return &self.uri;
162 }
163
164 pub fn query(&self) -> Option<&str> {
166 return self.uri.query();
167 }
168
169 pub fn query_param_by_name(&self, name: &str) -> Option<String> {
171 let query_params: HashMap<String, String> = self
172 .uri
173 .query()
174 .map(|v| form_urlencoded::parse(v.as_bytes()).into_owned().collect())
175 .unwrap_or_else(HashMap::new);
176
177 match query_params.get(name) {
178 Some(param_value) => Some(param_value.to_string()),
179 None => None,
180 }
181 }
182
183 pub fn path(&self) -> &str {
185 return &self.uri.path();
186 }
187
188 pub fn headers(&self) -> &HeaderMap {
204 return &self.headers;
205 }
206
207 pub fn body(&mut self) -> Result<&Option<Vec<u8>>, HttpError> {
230 if self.body.is_none() {
231 self.body = Some(get_body_from_host()?);
232 }
233 return Ok(&self.body);
234 }
235
236 pub fn get_read_stream(&mut self) -> Result<&mut ReadStream, HttpError> {
240 if self.read_stream.is_none() {
241 match get_read_stream_from_host() {
242 Ok(rs) => {
243 self.read_stream = Some(rs);
244 }
245 Err(err) => {
246 return Err(err);
247 }
248 }
249 }
250 Ok(self.read_stream.as_mut().unwrap())
251 }
252}
253
254fn get_method_from_host() -> HttpMethod {
255 let response = unsafe { http_cur_req_get_method() };
256
257 let method_enum_value: Option<HttpMethod> = FromPrimitive::from_i32(response);
258 match method_enum_value {
259 Some(v) => v,
260 None => HttpMethod::NONE,
261 }
262}
263
264fn get_uri_from_host() -> Result<Uri, UriError> {
265 let mut err = 0;
266 let response = unsafe { http_cur_req_get_uri(&mut err) };
267
268 if response > 0 {
269 let value = String::from_utf8(super::result::get_result_bytes(response).unwrap()).unwrap();
270 value.parse().map_err(|_| UriError::InvalidUri)
271 } else {
272 Err(UriError::try_from(err).unwrap())
273 }
274}
275
276fn get_body_from_host() -> Result<Vec<u8>, HTTPBodyTooLargeError> {
277 let mut err = 0;
278 let response = unsafe { http_cur_req_get_body(&mut err) };
279
280 if response > 0 {
281 let result = super::result::get_result_bytes(response);
282 Ok(result.unwrap())
283 } else if response == 0 {
284 Ok(Vec::with_capacity(0))
285 } else {
286 assert!(err == Error::HTTPTooLargeBody as i32);
287 return Err(HTTPBodyTooLargeError());
288 }
289}
290
291fn get_read_stream_from_host() -> Result<ReadStream, HttpError> {
292 let mut read_sd = 0;
293 let response = unsafe { http_cur_req_get_read_stream(&mut read_sd) };
294 if response < 0 {
295 return Err(HttpError::from(Error::from_i32(-1).unwrap()));
296 }
297
298 Ok(BaseStream::new(read_sd))
299}
300
301fn get_all_header_keys_from_host() -> Result<Vec<String>, HeaderError> {
302 let mut err = 0;
303 let response = unsafe { http_cur_req_get_all_header_keys(&mut err) };
304
305 if response > 0 {
306 let data = super::result::get_result_bytes(response).unwrap();
307
308 let keys_delimited_string = str::from_utf8(&data).unwrap();
309 let mut v = Vec::new();
310 for header_key in keys_delimited_string.split(",") {
311 if header_key.len() > 0 {
312 v.push(String::from(header_key))
313 }
314 }
315 Ok(v)
316 } else if response == 0 {
317 Ok(Vec::with_capacity(0))
318 } else {
319 assert!(err == Error::HTTPTooLargeHeaderName as i32);
320 Err(HeaderError::TooLargeName)
321 }
322}
323
324fn get_header_value_from_host(header_key: &str) -> Result<String, HeaderError> {
325 let mut key = String::from(header_key);
326 let key = key.as_mut_str();
327 let dest_length = key.len() as i32;
328 let dest_pointer = key.as_mut_ptr() as *const u8;
329 let mut err = 0;
330
331 let result_size = unsafe { http_cur_req_get_header_value(dest_pointer, dest_length, &mut err) };
332 if result_size > 0 {
333 Ok(String::from_utf8(super::result::get_result_bytes(result_size).unwrap()).unwrap())
334 } else if result_size == 0 {
335 Ok(String::with_capacity(0))
336 } else {
337 Err(HeaderError::from_i32(err).unwrap())
338 }
339}