use std::pin::Pin;
use std::task::{Context, Poll};
use futures::Future;
use futures::ready;
use hitbox::{CacheContext, CacheStatusExt};
use hitbox_http::{BufferedBody, CacheableHttpResponse};
use http::Response;
use http::header::HeaderName;
use pin_project::pin_project;
#[pin_project]
pub struct CacheServiceFuture<F, ResBody, E>
where
F: Future<Output = (Result<CacheableHttpResponse<ResBody>, E>, CacheContext)>,
ResBody: hyper::body::Body,
{
#[pin]
inner: F,
cache_status_header: HeaderName,
}
impl<F, ResBody, E> CacheServiceFuture<F, ResBody, E>
where
F: Future<Output = (Result<CacheableHttpResponse<ResBody>, E>, CacheContext)>,
ResBody: hyper::body::Body,
{
pub fn new(inner: F, cache_status_header: HeaderName) -> Self {
Self {
inner,
cache_status_header,
}
}
}
impl<F, ResBody, E> Future for CacheServiceFuture<F, ResBody, E>
where
F: Future<Output = (Result<CacheableHttpResponse<ResBody>, E>, CacheContext)>,
ResBody: hyper::body::Body,
{
type Output = Result<Response<BufferedBody<ResBody>>, E>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project();
let (result, cache_context) = ready!(this.inner.poll(cx));
let response = result.map(|mut cacheable_response| {
cacheable_response.cache_status(cache_context.status, this.cache_status_header);
cacheable_response.into_response()
});
Poll::Ready(response)
}
}