Skip to main content

tower_http_cache_plus/cache/middleware/
request.rs

1use super::{super::key::*, configuration::*, hooks::*};
2
3use {
4    http::*,
5    kutil::{http::*, transcoding::*},
6};
7
8//
9// CacheableEncodableRequest
10//
11
12/// Cacheable and/or encodable request.
13pub trait CacheableEncodableRequest<RequestBodyT> {
14    /// May call `cacheable_by_request` hook.
15    fn should_skip_cache<CacheT, CacheKeyT>(
16        &self,
17        configuration: &MiddlewareCachingConfiguration<RequestBodyT, CacheT, CacheKeyT>,
18    ) -> bool;
19
20    /// May call `cache_key` hook.
21    fn cache_key_with_hook<CacheT, CacheKeyT>(
22        &self,
23        configuration: &MiddlewareCachingConfiguration<RequestBodyT, CacheT, CacheKeyT>,
24    ) -> CacheKeyT
25    where
26        CacheKeyT: CacheKey;
27
28    /// May call `encodable_by_request` hook.
29    fn select_encoding(&self, configuration: &MiddlewareEncodingConfiguration) -> Encoding;
30}
31
32impl<RequestBodyT> CacheableEncodableRequest<RequestBodyT> for Request<RequestBodyT> {
33    fn should_skip_cache<CacheT, CacheKeyT>(
34        &self,
35        configuration: &MiddlewareCachingConfiguration<RequestBodyT, CacheT, CacheKeyT>,
36    ) -> bool {
37        let mut skip_cache = if !configuration.cache.is_none() {
38            let method = self.method();
39            if method.is_idempotent() {
40                false
41            } else {
42                tracing::debug!("skip (non-idempotent {})", method);
43                true
44            }
45        } else {
46            tracing::debug!("skip (disabled)");
47            true
48        };
49
50        if !skip_cache
51            && let Some(cacheable) = &configuration.cacheable_by_request
52            && !cacheable(CacheableHookContext::new(self.uri(), self.headers()))
53        {
54            tracing::debug!("skip (cacheable_by_request=false)");
55            skip_cache = true;
56        }
57
58        skip_cache
59    }
60
61    fn cache_key_with_hook<CacheT, CacheKeyT>(
62        &self,
63        configuration: &MiddlewareCachingConfiguration<RequestBodyT, CacheT, CacheKeyT>,
64    ) -> CacheKeyT
65    where
66        CacheKeyT: CacheKey,
67    {
68        let mut cache_key = self.cache_key();
69
70        if let Some(cache_key_hook) = &configuration.cache_key {
71            cache_key_hook(CacheKeyHookContext::new(&mut cache_key, self));
72        }
73
74        cache_key
75    }
76
77    fn select_encoding(&self, configuration: &MiddlewareEncodingConfiguration) -> Encoding {
78        let encoding = match &configuration.enabled_encodings_by_preference {
79            Some(enabled_encodings) => {
80                if !enabled_encodings.is_empty() {
81                    self.headers()
82                        .accept_encoding()
83                        .best(enabled_encodings)
84                        .cloned()
85                        .unwrap_or_default()
86                        .into()
87                } else {
88                    return Encoding::Identity;
89                }
90            }
91
92            None => return Encoding::Identity,
93        };
94
95        if encoding != Encoding::Identity
96            && let Some(encodable) = &configuration.encodable_by_request
97            && !encodable(EncodableHookContext::new(
98                &encoding,
99                self.uri(),
100                self.headers(),
101            ))
102        {
103            tracing::debug!("not encoding to {} (encodable_by_request=false)", encoding);
104            return Encoding::Identity;
105        }
106
107        encoding
108    }
109}