kutil_http/cache/middleware/responses/
upstream.rs1use super::super::{super::super::headers::*, configuration::*, hooks::*};
2
3use {
4 http::{header::*, *},
5 kutil_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 if let Some(cacheable) = &configuration.cacheable_by_response {
79 if !cacheable(CacheableHookContext::new(uri, headers)) {
80 tracing::debug!("skip (cacheable_by_response=false)");
81 skip_cache.0 = true;
82 }
83 }
84 }
85
86 skip_cache
87 }
88
89 fn validate_encoding(
90 &self,
91 uri: &Uri,
92 encoding: Encoding,
93 content_length: Option<usize>,
94 configuration: &MiddlewareEncodingConfiguration,
95 ) -> (Encoding, bool) {
96 if encoding == Encoding::Identity {
97 (encoding, false)
98 } else {
99 if let Some(content_length) = content_length {
100 let min_body_size = configuration.inner.min_body_size;
101 if min_body_size != 0 {
102 if content_length < min_body_size {
103 tracing::debug!("not encoding to {} (too small)", encoding);
104 return (Encoding::Identity, true);
105 }
106 }
107 }
108
109 match &configuration.encodable_by_response {
110 Some(encodable) => {
111 if encodable(EncodableHookContext::new(&encoding, uri, self.headers())) {
112 (encoding, false)
113 } else {
114 tracing::debug!("not encoding to {} (encodable_by_response=false)", encoding);
115 (Encoding::Identity, true)
116 }
117 }
118
119 None => (encoding, false),
120 }
121 }
122 }
123}