use axum::{
extract::FromRequestParts,
http::{request::Parts, HeaderMap, Method, Uri},
};
use std::collections::HashMap;
#[derive(Debug, Clone)]
pub struct Req {
pub headers: HeaderMap,
pub cookies: Cookies,
pub method: Method,
pub uri: Uri,
}
#[derive(Debug, Clone, Default)]
pub struct Cookies {
cookies: HashMap<String, String>,
}
impl Cookies {
pub fn from_header(header: Option<&str>) -> Self {
let mut cookies = HashMap::new();
if let Some(header) = header {
for part in header.split(';') {
let part = part.trim();
if let Some((name, value)) = part.split_once('=') {
cookies.insert(name.trim().to_string(), value.trim().to_string());
}
}
}
Self { cookies }
}
pub fn get(&self, name: &str) -> Option<&str> {
self.cookies.get(name).map(|s| s.as_str())
}
pub fn has(&self, name: &str) -> bool {
self.cookies.contains_key(name)
}
pub fn iter(&self) -> impl Iterator<Item = (&str, &str)> {
self.cookies.iter().map(|(k, v)| (k.as_str(), v.as_str()))
}
}
impl<S> FromRequestParts<S> for Req
where
S: Send + Sync,
{
type Rejection = std::convert::Infallible;
async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<Self, Self::Rejection> {
let headers = parts.headers.clone();
let cookies = Cookies::from_header(
headers
.get(axum::http::header::COOKIE)
.and_then(|v| v.to_str().ok()),
);
let method = parts.method.clone();
let uri = parts.uri.clone();
Ok(Req {
headers,
cookies,
method,
uri,
})
}
}