feather_runtime/http/
request.rs1use super::ConnectionState;
2use crate::utils::error::Error;
3use bytes::Bytes;
4use http::{Extensions, HeaderMap, Method, Uri, Version};
5use std::str::FromStr;
6use std::{borrow::Cow, collections::HashMap, fmt};
7use std::net::TcpStream;
8use urlencoding::decode;
9
10#[derive(Debug)]
12pub struct Request {
13 stream: Option<TcpStream>,
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 params: HashMap<String, String>,
29 pub(crate) connection: Option<ConnectionState>,
31}
32
33
34impl Request {
35 pub fn parse(raw: &[u8]) -> Result<Request, Error> {
38 let mut headers = [httparse::EMPTY_HEADER; 16];
39 let mut request = httparse::Request::new(&mut headers);
40 let mut connection = None;
41 request.parse(raw).map_err(|e| Error::ParseError(format!("Failed to parse request: {}", e)))?;
42 let method = match Method::from_str(request.method.unwrap_or("nil")) {
43 Ok(m) => m,
44 Err(e) => return Err(Error::ParseError(format!("Failed to parse method: {}", e))),
45 };
46 let uri: Uri = request.path.ok_or_else(|| Error::ParseError("Failed to parse URI".to_string()))?.parse().map_err(|e| Error::ParseError(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::ParseError(format!("Failed to parse header name: {}", e)))?;
56 let value = http::header::HeaderValue::from_bytes(header.value).map_err(|e| Error::ParseError(format!("Failed to parse header value: {}", e)))?;
57
58 if name.as_str().eq_ignore_ascii_case("connection") {
59 connection = ConnectionState::parse(value.to_str().unwrap_or(""));
60 }
61
62 header_map.insert(name, value);
63 }
64 let body_start = raw.windows(4).position(|w| w == b"\r\n\r\n").map(|pos| pos + 4).unwrap_or(raw.len());
65 let body = Bytes::copy_from_slice(&raw[body_start..]);
66 let extensions = Extensions::new();
67 Ok(Request {
68 stream: None,
69 method,
70 uri,
71 version,
72 headers: header_map,
73 body,
74 extensions,
75 connection,
76 params: HashMap::new(),
77 })
78 }
79
80 pub(crate) fn set_stream(&mut self, stream: TcpStream) {
81 self.stream = Some(stream);
82 }
83 pub fn take_stream(mut self) -> Option<TcpStream> {
96 self.stream.take()
97 }
98 pub fn has_stream(&self) -> bool {
100 self.stream.is_some()
101 }
102
103 #[cfg(feature = "json")]
106 pub fn json(&self) -> Result<serde_json::Value, Error> {
107 serde_json::from_slice(&self.body).map_err(|e| Error::ParseError(format!("Failed to parse JSON body: {}", e)))
108 }
109 pub fn query(&self) -> Result<HashMap<String, String>, Error> {
112 if let Some(query) = self.uri.query() {
113 serde_urlencoded::from_str(query).map_err(|e| Error::ParseError(format!("Failed to Parse Query parameters {}", e)))
114 } else {
115 Ok(HashMap::new())
116 }
117 }
118
119 pub fn set_params(&mut self, params: HashMap<String, String>) {
120 self.params = params;
121 }
122
123 pub fn param(&self, key: &str) -> Option<&str> {
124 self.params.get(key).map(|v| &**v)
125 }
126
127 pub fn path(&self) -> Cow<'_, str> {
129 decode(self.uri.path()).unwrap()
130 }
131}
132
133impl fmt::Display for Request {
134 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
135 write!(f, "{} for {}: Body Data: {} ", self.method, self.uri.path(), String::from_utf8_lossy(&self.body))
136 }
137}