trillium_caching_headers/
caching_conn_ext.rs1use crate::CacheControlHeader;
2use etag::EntityTag;
3use std::{str::FromStr, time::SystemTime};
4use trillium::{HeaderName, KnownHeaderName};
5
6pub trait CachingHeadersExt: Sized {
10 fn etag(&self) -> Option<EntityTag>;
12 fn set_etag(&mut self, entity_tag: &EntityTag);
14
15 fn last_modified(&self) -> Option<SystemTime>;
17 fn set_last_modified(&mut self, system_time: SystemTime);
19
20 fn cache_control(&self) -> Option<CacheControlHeader>;
25 fn set_cache_control(&mut self, cache_control: impl Into<CacheControlHeader>);
29
30 fn if_modified_since(&self) -> Option<SystemTime>;
32 fn if_none_match(&self) -> Option<EntityTag>;
34
35 fn set_vary<I, N>(&mut self, vary: I)
37 where
38 I: IntoIterator<Item = N>,
39 N: Into<HeaderName<'static>>;
40
41 fn with_cache_control(mut self, cache_control: impl Into<CacheControlHeader>) -> Self {
43 self.set_cache_control(cache_control);
44 self
45 }
46
47 fn with_last_modified(mut self, system_time: SystemTime) -> Self {
49 self.set_last_modified(system_time);
50 self
51 }
52
53 fn with_etag(mut self, entity_tag: &EntityTag) -> Self {
55 self.set_etag(entity_tag);
56 self
57 }
58
59 fn with_vary<I, N>(mut self, vary: I) -> Self
61 where
62 I: IntoIterator<Item = N>,
63 N: Into<HeaderName<'static>>,
64 {
65 self.set_vary(vary);
66 self
67 }
68}
69
70impl CachingHeadersExt for trillium::Conn {
71 fn etag(&self) -> Option<EntityTag> {
72 self.inner().response_headers().etag()
73 }
74
75 fn set_etag(&mut self, entity_tag: &EntityTag) {
76 self.inner_mut().response_headers_mut().set_etag(entity_tag)
77 }
78
79 fn last_modified(&self) -> Option<SystemTime> {
80 self.inner().response_headers().last_modified()
81 }
82
83 fn set_last_modified(&mut self, system_time: SystemTime) {
84 self.inner_mut()
85 .response_headers_mut()
86 .set_last_modified(system_time)
87 }
88
89 fn cache_control(&self) -> Option<CacheControlHeader> {
90 self.inner().request_headers().cache_control()
91 }
92
93 fn set_cache_control(&mut self, cache_control: impl Into<CacheControlHeader>) {
94 self.inner_mut()
95 .response_headers_mut()
96 .set_cache_control(cache_control)
97 }
98
99 fn if_modified_since(&self) -> Option<SystemTime> {
100 self.inner().request_headers().if_modified_since()
101 }
102
103 fn if_none_match(&self) -> Option<EntityTag> {
104 self.inner().request_headers().if_none_match()
105 }
106
107 fn set_vary<I, N>(&mut self, vary: I)
108 where
109 I: IntoIterator<Item = N>,
110 N: Into<HeaderName<'static>>,
111 {
112 self.inner_mut().response_headers_mut().set_vary(vary)
113 }
114}
115
116impl CachingHeadersExt for trillium::Headers {
117 fn etag(&self) -> Option<EntityTag> {
118 self.get_str(KnownHeaderName::Etag)
119 .and_then(|etag| etag.parse().ok())
120 }
121
122 fn set_etag(&mut self, entity_tag: &EntityTag) {
123 let string = entity_tag.to_string();
124 self.insert(KnownHeaderName::Etag, string);
125 }
126
127 fn last_modified(&self) -> Option<SystemTime> {
128 self.get_str(KnownHeaderName::LastModified)
129 .and_then(|x| httpdate::parse_http_date(x).ok())
130 }
131
132 fn set_last_modified(&mut self, system_time: SystemTime) {
133 self.insert(
134 KnownHeaderName::LastModified,
135 httpdate::fmt_http_date(system_time),
136 );
137 }
138
139 fn cache_control(&self) -> Option<CacheControlHeader> {
140 self.get_str(KnownHeaderName::CacheControl)
141 .and_then(|cc| cc.parse().ok())
142 }
143
144 fn set_cache_control(&mut self, cache_control: impl Into<CacheControlHeader>) {
145 self.insert(
146 KnownHeaderName::CacheControl,
147 cache_control.into().to_string(),
148 );
149 }
150
151 fn if_modified_since(&self) -> Option<SystemTime> {
152 self.get_str(KnownHeaderName::IfModifiedSince)
153 .and_then(|h| httpdate::parse_http_date(h).ok())
154 }
155
156 fn if_none_match(&self) -> Option<EntityTag> {
157 self.get_str(KnownHeaderName::IfNoneMatch)
158 .and_then(|etag| EntityTag::from_str(etag).ok())
159 }
160
161 fn set_vary<I, N>(&mut self, vary: I)
162 where
163 I: IntoIterator<Item = N>,
164 N: Into<HeaderName<'static>>,
165 {
166 self.insert(
167 KnownHeaderName::Vary,
168 vary.into_iter()
169 .map(|n| n.into().to_string())
170 .collect::<Vec<_>>()
171 .join(","),
172 );
173 }
174}