tower_http_cache_plus/cache/middleware/responses/
upstream.rs1use super::super::{configuration::*, hooks::*};
2
3use {
4 http::{header::*, *},
5 kutil::{http::*, transcoding::*},
6};
7
8pub trait UpstreamResponse<ResponseBodyT> {
14 fn should_skip_cache<RequestBodyT, CacheT, CacheKeyT>(
21 &self,
22 uri: &Uri,
23 configuration: &MiddlewareCachingConfiguration<CacheT, CacheKeyT, RequestBodyT>,
24 ) -> (bool, Option<usize>);
25
26 fn validate_encoding(
33 &self,
34 uri: &Uri,
35 encoding: Encoding,
36 content_length: Option<usize>,
37 configuration: &MiddlewareEncodingConfiguration,
38 ) -> (Encoding, bool);
39}
40
41impl<ResponseBodyT> UpstreamResponse<ResponseBodyT> for Response<ResponseBodyT> {
42 fn should_skip_cache<RequestBodyT, CacheT, CacheKeyT>(
43 &self,
44 uri: &Uri,
45 configuration: &MiddlewareCachingConfiguration<CacheT, CacheKeyT, RequestBodyT>,
46 ) -> (bool, Option<usize>) {
47 let headers = self.headers();
48 let status = self.status();
49
50 let mut skip_cache = if !headers.xx_cache(configuration.inner.cacheable_by_default) {
51 tracing::debug!("skip ({}=false)", XX_CACHE);
52 (true, None)
53 } else if !status.is_success() {
54 tracing::debug!("skip (status={})", status.as_u16());
55 (true, None)
56 } else if headers.contains_key(CONTENT_RANGE) {
57 tracing::debug!("skip (range)");
58 (true, None)
59 } else {
60 match headers.content_length() {
61 Some(content_length) => {
62 if content_length < configuration.inner.min_body_size {
63 tracing::debug!("skip (Content-Length too small)");
64 (true, Some(content_length))
65 } else if content_length > configuration.inner.max_body_size {
66 tracing::debug!("skip (Content-Length too big)");
67 (true, Some(content_length))
68 } else {
69 (false, Some(content_length))
70 }
71 }
72
73 None => (false, None),
74 }
75 };
76
77 if !skip_cache.0
78 && let Some(cacheable) = &configuration.cacheable_by_response
79 && !cacheable(CacheableHookContext::new(uri, headers))
80 {
81 tracing::debug!("skip (cacheable_by_response=false)");
82 skip_cache.0 = true;
83 }
84
85 skip_cache
86 }
87
88 fn validate_encoding(
89 &self,
90 uri: &Uri,
91 encoding: Encoding,
92 content_length: Option<usize>,
93 configuration: &MiddlewareEncodingConfiguration,
94 ) -> (Encoding, bool) {
95 if encoding == Encoding::Identity {
96 (encoding, false)
97 } else {
98 if let Some(content_length) = content_length {
99 let min_body_size = configuration.inner.min_body_size;
100 if min_body_size != 0 {
101 if content_length < min_body_size {
102 tracing::debug!("not encoding to {} (too small)", encoding);
103 return (Encoding::Identity, true);
104 }
105 }
106 }
107
108 match &configuration.encodable_by_response {
109 Some(encodable) => {
110 if encodable(EncodableHookContext::new(&encoding, uri, self.headers())) {
111 (encoding, false)
112 } else {
113 tracing::debug!(
114 "not encoding to {} (encodable_by_response=false)",
115 encoding
116 );
117 (Encoding::Identity, true)
118 }
119 }
120
121 None => (encoding, false),
122 }
123 }
124 }
125}