1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
//! Defines a cookie parsing middleware to be attach cookies on requests.
use std::pin::Pin;
use cookie::{Cookie, CookieJar};
use hyper::header::{HeaderMap, HeaderValue, COOKIE};
use super::{Middleware, NewMiddleware};
use crate::handler::HandlerFuture;
use crate::state::{FromState, State};
/// A struct that can act as a cookie parsing middleware for Gotham.
///
/// We implement `NewMiddleware` here for Gotham to allow us to work with the request
/// lifecycle correctly. This trait requires `Clone`, so that is also included. Cookies
/// become availabe on the request state as the `CookieJar` type.
#[derive(Copy, Clone)]
pub struct CookieParser;
/// Public API for external re-use.
impl CookieParser {
/// Parses a `CookieJar` from a `State`.
pub fn from_state(state: &State) -> CookieJar {
HeaderMap::borrow_from(state)
.get_all(COOKIE)
.iter()
.flat_map(HeaderValue::to_str)
.flat_map(|cs| cs.split("; "))
.flat_map(|cs| Cookie::parse(cs.to_owned()))
.fold(CookieJar::new(), |mut jar, cookie| {
jar.add_original(cookie);
jar
})
}
}
/// `Middleware` trait implementation.
impl Middleware for CookieParser {
/// Attaches a set of parsed cookies to the request state.
fn call<Chain>(self, mut state: State, chain: Chain) -> Pin<Box<HandlerFuture>>
where
Chain: FnOnce(State) -> Pin<Box<HandlerFuture>>,
{
let cookies = { CookieParser::from_state(&state) };
state.put(cookies);
chain(state)
}
}
/// `NewMiddleware` trait implementation.
impl NewMiddleware for CookieParser {
type Instance = Self;
/// Clones the current middleware to a new instance.
fn new_middleware(&self) -> anyhow::Result<Self::Instance> {
Ok(*self)
}
}