trillium_caching_headers/
caching_conn_ext.rs1use crate::CacheControlHeader;
2use etag::EntityTag;
3use std::{str::FromStr, time::SystemTime};
4use trillium::{Conn, HeaderName, KnownHeaderName};
5
6pub trait CachingHeadersExt: Sized {
10 fn etag(&self) -> Option<EntityTag>;
12
13 fn set_etag(&mut self, entity_tag: &EntityTag);
15
16 fn last_modified(&self) -> Option<SystemTime>;
18
19 fn set_last_modified(&mut self, system_time: SystemTime);
21
22 fn cache_control(&self) -> Option<CacheControlHeader>;
26
27 fn set_cache_control(&mut self, cache_control: impl Into<CacheControlHeader>);
31
32 fn cdn_cache_control(&self) -> Option<CacheControlHeader>;
36
37 fn set_cdn_cache_control(&mut self, cache_control: impl Into<CacheControlHeader>);
40
41 fn if_modified_since(&self) -> Option<SystemTime>;
43
44 fn if_none_match(&self) -> Option<EntityTag>;
46
47 fn set_vary<I, N>(&mut self, vary: I)
49 where
50 I: IntoIterator<Item = N>,
51 N: Into<HeaderName<'static>>;
52
53 fn with_cache_control(mut self, cache_control: impl Into<CacheControlHeader>) -> Self {
55 self.set_cache_control(cache_control);
56 self
57 }
58
59 fn with_last_modified(mut self, system_time: SystemTime) -> Self {
61 self.set_last_modified(system_time);
62 self
63 }
64
65 fn with_etag(mut self, entity_tag: &EntityTag) -> Self {
67 self.set_etag(entity_tag);
68 self
69 }
70
71 fn with_vary<I, N>(mut self, vary: I) -> Self
73 where
74 I: IntoIterator<Item = N>,
75 N: Into<HeaderName<'static>>,
76 {
77 self.set_vary(vary);
78 self
79 }
80
81 fn with_cdn_cache_control(mut self, cache_control: impl Into<CacheControlHeader>) -> Self {
83 self.set_cdn_cache_control(cache_control);
84 self
85 }
86}
87
88impl CachingHeadersExt for Conn {
89 fn etag(&self) -> Option<EntityTag> {
90 self.response_headers().etag()
91 }
92
93 fn set_etag(&mut self, entity_tag: &EntityTag) {
94 self.response_headers_mut().set_etag(entity_tag)
95 }
96
97 fn last_modified(&self) -> Option<SystemTime> {
98 self.response_headers().last_modified()
99 }
100
101 fn set_last_modified(&mut self, system_time: SystemTime) {
102 self.response_headers_mut().set_last_modified(system_time)
103 }
104
105 fn cache_control(&self) -> Option<CacheControlHeader> {
106 self.request_headers().cache_control()
107 }
108
109 fn set_cache_control(&mut self, cache_control: impl Into<CacheControlHeader>) {
110 self.response_headers_mut().set_cache_control(cache_control)
111 }
112
113 fn cdn_cache_control(&self) -> Option<CacheControlHeader> {
116 self.response_headers().cdn_cache_control()
117 }
118
119 fn set_cdn_cache_control(&mut self, cache_control: impl Into<CacheControlHeader>) {
120 self.response_headers_mut()
121 .set_cdn_cache_control(cache_control)
122 }
123
124 fn if_modified_since(&self) -> Option<SystemTime> {
125 self.request_headers().if_modified_since()
126 }
127
128 fn if_none_match(&self) -> Option<EntityTag> {
129 self.request_headers().if_none_match()
130 }
131
132 fn set_vary<I, N>(&mut self, vary: I)
133 where
134 I: IntoIterator<Item = N>,
135 N: Into<HeaderName<'static>>,
136 {
137 self.response_headers_mut().set_vary(vary)
138 }
139}
140
141impl CachingHeadersExt for trillium::Headers {
142 fn etag(&self) -> Option<EntityTag> {
143 self.get_str(KnownHeaderName::Etag)
144 .and_then(|etag| etag.parse().ok())
145 }
146
147 fn set_etag(&mut self, entity_tag: &EntityTag) {
148 let string = entity_tag.to_string();
149 self.insert(KnownHeaderName::Etag, string);
150 }
151
152 fn last_modified(&self) -> Option<SystemTime> {
153 self.get_str(KnownHeaderName::LastModified)
154 .and_then(|x| httpdate::parse_http_date(x).ok())
155 }
156
157 fn set_last_modified(&mut self, system_time: SystemTime) {
158 self.insert(
159 KnownHeaderName::LastModified,
160 httpdate::fmt_http_date(system_time),
161 );
162 }
163
164 fn cache_control(&self) -> Option<CacheControlHeader> {
165 self.get_str(KnownHeaderName::CacheControl)
166 .map(CacheControlHeader::parse)
167 }
168
169 fn set_cache_control(&mut self, cache_control: impl Into<CacheControlHeader>) {
170 self.insert(
171 KnownHeaderName::CacheControl,
172 cache_control.into().to_string(),
173 );
174 }
175
176 fn cdn_cache_control(&self) -> Option<CacheControlHeader> {
177 self.get_str(KnownHeaderName::CdnCacheControl)
178 .map(CacheControlHeader::parse)
179 }
180
181 fn set_cdn_cache_control(&mut self, cache_control: impl Into<CacheControlHeader>) {
182 self.insert(
183 KnownHeaderName::CdnCacheControl,
184 cache_control.into().to_string(),
185 );
186 }
187
188 fn if_modified_since(&self) -> Option<SystemTime> {
189 self.get_str(KnownHeaderName::IfModifiedSince)
190 .and_then(|h| httpdate::parse_http_date(h).ok())
191 }
192
193 fn if_none_match(&self) -> Option<EntityTag> {
194 self.get_str(KnownHeaderName::IfNoneMatch)
195 .and_then(|etag| EntityTag::from_str(etag).ok())
196 }
197
198 fn set_vary<I, N>(&mut self, vary: I)
199 where
200 I: IntoIterator<Item = N>,
201 N: Into<HeaderName<'static>>,
202 {
203 self.insert(
204 KnownHeaderName::Vary,
205 vary.into_iter()
206 .map(|n| n.into().to_string())
207 .collect::<Vec<_>>()
208 .join(","),
209 );
210 }
211}