cookie-monster 0.2.2

A Cookie library for managing HTTP Cookies, with Axum integration.
Documentation
use std::convert::Infallible;

use axum_core::{
    extract::FromRequestParts,
    response::{IntoResponse, IntoResponseParts, Response, ResponseParts},
};
use http::request::Parts;

use crate::{Cookie, CookieJar};

impl<S> FromRequestParts<S> for CookieJar
where
    S: Send + Sync,
{
    type Rejection = Infallible;

    async fn from_request_parts(parts: &mut Parts, _: &S) -> Result<Self, Self::Rejection> {
        Ok(CookieJar::from_headers(&parts.headers))
    }
}

impl IntoResponseParts for CookieJar {
    type Error = Infallible;

    fn into_response_parts(self, mut res: ResponseParts) -> Result<ResponseParts, Self::Error> {
        self.write_cookies(res.headers_mut());
        Ok(res)
    }
}

impl IntoResponse for CookieJar {
    fn into_response(self) -> Response {
        (self, ()).into_response()
    }
}

impl IntoResponseParts for Cookie {
    type Error = Infallible;

    fn into_response_parts(self, mut res: ResponseParts) -> Result<ResponseParts, Self::Error> {
        if let Some(cookie) = self
            .serialize_encoded()
            .ok()
            .and_then(|string| string.parse().ok())
        {
            res.headers_mut().append("set-cookie", cookie);
        }
        Ok(res)
    }
}

impl IntoResponse for Cookie {
    fn into_response(self) -> Response {
        (self, ()).into_response()
    }
}

#[cfg(test)]
mod axum_tests {
    use axum::response::IntoResponse;

    use crate::Cookie;

    #[test]
    fn set_multiple_cookies() {
        let first = Cookie::build("foo", "bar").build();
        let second = Cookie::build("baz", "qux").build();

        let response = (first, ()).into_response();

        assert!(response.headers().get_all("set-cookie").iter().count() == 1);

        let response = (second, response).into_response();
        assert!(response.headers().get_all("set-cookie").iter().count() == 2);
    }
}