Skip to main content

tower_cookies/service/
future.rs

1//! [`Future`] types.
2
3use crate::Cookies;
4use futures_util::ready;
5use http::{header, HeaderValue, Response};
6use pin_project_lite::pin_project;
7use std::{
8    future::Future,
9    pin::Pin,
10    task::{Context, Poll},
11};
12
13pin_project! {
14    /// Response future for [`CookieManager`].
15    #[derive(Debug)]
16    pub struct ResponseFuture<F> {
17        #[pin]
18        pub(crate) future: F,
19        pub(crate) cookies: Cookies,
20    }
21}
22
23impl<F, ResBody, E> Future for ResponseFuture<F>
24where
25    F: Future<Output = Result<Response<ResBody>, E>>,
26{
27    type Output = F::Output;
28
29    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
30        let this = self.project();
31        let mut res = ready!(this.future.poll(cx)?);
32
33        let mut cookies = this.cookies.inner.lock();
34        if cookies.changed {
35            let values: Vec<_> = cookies
36                .jar()
37                .delta()
38                .filter_map(|c| HeaderValue::from_str(&c.to_string()).ok())
39                .collect();
40            let headers = res.headers_mut();
41            for value in values {
42                headers.append(header::SET_COOKIE, value);
43            }
44        }
45
46        Poll::Ready(Ok(res))
47    }
48}