gotham/middleware/
cookie.rs

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