1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/*!
# Cache Response for Rocket Framework
This crate provides a response struct used for HTTP cache control.
```rust
use rocket::get;
use rocket_cache_response::CacheResponse;
#[get("/")]
fn index() -> CacheResponse<&'static str> {
CacheResponse::public("Hello world!", 3600)
}
```
Every directive is a public field of `CacheControl`, so an uncommon combination can be built with the struct update syntax.
```rust
use rocket::get;
use rocket_cache_response::{CacheControl, CacheResponse};
#[get("/")]
fn index() -> CacheResponse<&'static str> {
CacheResponse::new("Hello world!", CacheControl {
s_max_age: Some(86400),
stale_while_revalidate: Some(30),
..CacheControl::public(60)
})
}
```
A browser holding on to an old response is a nuisance during development, so `only_release` drops the `Cache-Control` header when the program is built in the debug mode.
```rust
use rocket::get;
use rocket_cache_response::CacheResponse;
#[get("/")]
fn index() -> CacheResponse<&'static str> {
CacheResponse::public("Hello world!", 3600).only_release()
}
```
## Which `Cache-Control` Should I Use?
| Situation | Directives | Shortcut |
| --------- | ---------- | -------- |
| A static file whose URL changes whenever its content changes, such as `app.9f2c1a.js` | `public, max-age=31536000, immutable` | `CacheResponse::immutable(responder)` |
| A public page or asset that only changes once in a while | `public, max-age=3600` | `CacheResponse::public(responder, 3600)` |
| A public response that a CDN should keep longer than a browser does | `public, max-age=60, s-maxage=86400` | `CacheControl { s_max_age: Some(86400), ..CacheControl::public(60) }` |
| A page or an API response that belongs to the logged-in user | `private, max-age=0` | `CacheResponse::private(responder, 0)` |
| A response that has to be checked with the server before every reuse | `no-cache` | `CacheResponse::no_cache(responder)` |
| Personal data, payment details or anything else sensitive | `no-store` | `CacheResponse::no_store(responder)` |
Things that are easy to get wrong:
* `no-cache` does not mean "do not cache". A cache may still store the response; it just has to ask the origin server whether the stored copy is still good before every reuse. Use `no-store` when the response must never be written to a cache at all.
* `no-cache` on its own still lets shared caches, such as a CDN or a company proxy, store the response. Add `private` whenever the body is meant for one user only.
* `must-revalidate` only takes effect after `max-age` has passed. It forbids a cache from serving the stale copy while the origin server is unreachable.
* `immutable` is honored even when the user presses the reload button, so only use it for URLs that get a new name whenever the content changes.
* `max-age` is counted by each cache on its own, so a CDN and a browser may hold their copies for different amounts of time. `s-maxage` is the way to give shared caches a lifetime of their own.
*/
pub extern crate rocket;
use ;
pub use crate;
/// The responder with a `Cache-Control` header.