feather_runtime/http/
request.rs1use std::io;
2pub type Error = Box<dyn std::error::Error>;
5use bytes::Bytes;
6use http::{Extensions, HeaderMap, Method, Uri, Version};
7use std::str::FromStr;
8use std::{borrow::Cow, collections::HashMap, fmt};
9use urlencoding::decode;
10
11#[derive(Debug)]
13pub struct Request {
14 pub method: Method,
17 pub uri: Uri,
19 pub version: Version,
21 pub headers: HeaderMap,
23 pub body: Bytes,
25 pub extensions: Extensions,
27
28 params: HashMap<String, String>,
30}
31
32impl Request {
33 pub fn parse(raw: &[u8]) -> Result<Request, Error> {
35 let mut headers = [httparse::EMPTY_HEADER; 64];
36 let mut request = httparse::Request::new(&mut headers);
37
38 request.parse(raw).map_err(|e| -> Error { Box::new(io::Error::new(io::ErrorKind::InvalidData, format!("Failed to parse request: {}", e))) })?;
39
40 let method_str = request.method.ok_or_else(|| -> Error { Box::new(io::Error::new(io::ErrorKind::InvalidData, "Missing HTTP method")) })?;
42
43 let method = Method::from_str(method_str).map_err(|_| -> Error { Box::new(io::Error::new(io::ErrorKind::InvalidData, format!("Invalid HTTP method: {}", method_str))) })?;
45 let path = request.path.ok_or_else(|| -> Error { Box::new(io::Error::new(io::ErrorKind::InvalidData, "Failed to parse URI")) })?;
46 let uri: Uri = path.parse().map_err(|e| -> Error { Box::new(io::Error::new(io::ErrorKind::InvalidData, format!("Failed to parse URI: {}", e))) })?;
47
48 let version = match request.version {
49 Some(0) => Version::HTTP_10,
50 Some(1) => Version::HTTP_11,
51 _ => Version::HTTP_11,
52 };
53 let mut header_map = HeaderMap::new();
54 for header in request.headers.iter() {
55 let name = http::header::HeaderName::from_bytes(header.name.as_bytes()).map_err(|e| -> Error { Box::new(io::Error::new(io::ErrorKind::InvalidData, format!("Failed to parse header name: {}", e))) })?;
56 let value = http::header::HeaderValue::from_bytes(header.value).map_err(|e| -> Error { Box::new(io::Error::new(io::ErrorKind::InvalidData, format!("Failed to parse header value: {}", e))) })?;
57
58 header_map.insert(name, value);
59 }
60 let body_start = raw.windows(4).position(|w| w == b"\r\n\r\n").map(|pos| pos + 4).unwrap_or(raw.len());
61 let body = Bytes::copy_from_slice(&raw[body_start..]);
62 let extensions = Extensions::new();
63 Ok(Request {
64 method,
65 uri,
66 version,
67 headers: header_map,
68 body,
69 extensions,
70 params: HashMap::new(),
71 })
72 }
73
74 #[cfg(feature = "json")]
77 pub fn json(&self) -> Result<serde_json::Value, Error> {
78 serde_json::from_slice(&self.body).map_err(|e| -> Error { Box::new(io::Error::new(io::ErrorKind::InvalidData, format!("Failed to parse JSON body: {}", e))) })
79 }
80 pub fn query(&self) -> Result<HashMap<String, String>, Error> {
83 if let Some(query) = self.uri.query() {
84 serde_urlencoded::from_str(query).map_err(|e| -> Error { Box::new(io::Error::new(io::ErrorKind::InvalidData, format!("Failed to Parse Query parameters {}", e))) })
85 } else {
86 Ok(HashMap::new())
87 }
88 }
89
90 pub fn set_params(&mut self, params: HashMap<String, String>) {
91 self.params = params;
92 }
93
94 pub fn param(&self, key: &str) -> Option<&str> {
95 self.params.get(key).map(|v| &**v)
96 }
97
98 pub fn path(&self) -> Cow<'_, str> {
100 decode(self.uri.path()).unwrap()
101 }
102}
103
104impl fmt::Display for Request {
105 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
106 write!(f, "{} {}", self.method, self.uri.path())
107 }
108}