use std::io;
use std::net::SocketAddr;
pub type Error = Box<dyn std::error::Error>;
use bytes::Bytes;
use http::{Extensions, HeaderMap, Method, Uri, Version};
use std::str::FromStr;
use std::{borrow::Cow, collections::HashMap, fmt};
use urlencoding::decode;
#[derive(Debug)]
pub struct Request {
pub method: Method,
pub uri: Uri,
pub version: Version,
pub headers: HeaderMap,
pub body: Bytes,
pub extensions: Extensions,
addr: SocketAddr,
params: HashMap<String, String>,
}
impl Request {
pub fn parse(headers_raw: &[u8], body: Bytes, incoming_addr: SocketAddr) -> Result<Request, Error> {
let mut headers = [httparse::EMPTY_HEADER; 64];
let mut request = httparse::Request::new(&mut headers);
request.parse(headers_raw).map_err(|e| -> Error { Box::new(io::Error::new(io::ErrorKind::InvalidData, format!("Failed to parse request: {}", e))) })?;
let method_str = request.method.ok_or_else(|| -> Error { Box::new(io::Error::new(io::ErrorKind::InvalidData, "Missing HTTP method")) })?;
let method = Method::from_str(method_str).map_err(|_| -> Error { Box::new(io::Error::new(io::ErrorKind::InvalidData, format!("Invalid HTTP method: {}", method_str))) })?;
let path = request.path.ok_or_else(|| -> Error { Box::new(io::Error::new(io::ErrorKind::InvalidData, "Failed to parse URI")) })?;
let uri: Uri = path.parse().map_err(|e| -> Error { Box::new(io::Error::new(io::ErrorKind::InvalidData, format!("Failed to parse URI: {}", e))) })?;
let version = match request.version {
Some(0) => Version::HTTP_10,
Some(1) => Version::HTTP_11,
_ => Version::HTTP_11,
};
let mut header_map = HeaderMap::new();
for header in request.headers.iter() {
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))) })?;
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))) })?;
header_map.insert(name, value);
}
let extensions = Extensions::new();
Ok(Request {
method,
uri,
version,
headers: header_map,
body,
addr: incoming_addr,
extensions,
params: HashMap::new(),
})
}
#[cfg(feature = "json")]
pub fn json(&self) -> Result<serde_json::Value, Error> {
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))) })
}
pub fn query(&self) -> Result<HashMap<String, String>, Error> {
if let Some(query) = self.uri.query() {
serde_urlencoded::from_str(query).map_err(|e| -> Error { Box::new(io::Error::new(io::ErrorKind::InvalidData, format!("Failed to Parse Query parameters {}", e))) })
} else {
Ok(HashMap::new())
}
}
pub fn set_params(&mut self, params: HashMap<String, String>) {
self.params = params;
}
pub fn param(&self, key: &str) -> Option<&str> {
self.params.get(key).map(|v| &**v)
}
pub fn path(&self) -> Cow<'_, str> {
decode(self.uri.path()).unwrap()
}
pub fn remote_addr(&self) -> SocketAddr {
self.addr
}
}
impl fmt::Display for Request {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{} {}", self.method, self.uri.path())
}
}