1
1
/*
2
- * Copyright 2002-2023 the original author or authors.
2
+ * Copyright 2002-2024 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
23
23
import org .springframework .util .StringUtils ;
24
24
25
25
/**
26
- * A builder for creating "Cache-Control" HTTP response headers.
26
+ * A builder for creating "Cache-Control" HTTP response headers. As of Spring
27
+ * Framework 6.2, this class is immutable.
27
28
*
28
29
* <p>Adding Cache-Control directives to HTTP responses can significantly improve the client
29
30
* experience when interacting with a web application. This builder creates opinionated
51
52
*/
52
53
public class CacheControl {
53
54
54
- private static final CacheControl EMPTY = new CacheControl (null , false , false , false ,
55
- false , false , false , false , null , null ,
56
- null , false );
55
+ private static final CacheControl EMPTY = new CacheControl ();
57
56
58
57
@ Nullable
59
58
private final Duration maxAge ;
@@ -83,10 +82,18 @@ public class CacheControl {
83
82
84
83
private final boolean immutable ;
85
84
85
+ /**
86
+ * Create an empty CacheControl instance.
87
+ * @see #empty()
88
+ */
89
+ protected CacheControl () {
90
+ this (null , false , false , false , false , false , false , false , null , null , null , false );
91
+ }
92
+
86
93
private CacheControl (@ Nullable Duration maxAge , boolean noCache , boolean noStore ,
87
- boolean mustRevalidate , boolean noTransform , boolean cachePublic ,
88
- boolean cachePrivate , boolean proxyRevalidate , @ Nullable Duration staleWhileRevalidate ,
89
- @ Nullable Duration staleIfError , @ Nullable Duration sMaxAge , boolean immutable ) {
94
+ boolean mustRevalidate , boolean noTransform , boolean cachePublic ,
95
+ boolean cachePrivate , boolean proxyRevalidate , @ Nullable Duration staleWhileRevalidate ,
96
+ @ Nullable Duration staleIfError , @ Nullable Duration sMaxAge , boolean immutable ) {
90
97
this .maxAge = maxAge ;
91
98
this .noCache = noCache ;
92
99
this .noStore = noStore ;
@@ -105,14 +112,14 @@ private CacheControl(@Nullable Duration maxAge, boolean noCache, boolean noStore
105
112
* Return an empty directive.
106
113
* <p>This is well suited for using other optional directives without "max-age",
107
114
* "no-cache" or "no-store".
108
- * @return {@code this}, to facilitate method chaining
115
+ * @return en empty directive
109
116
*/
110
117
public static CacheControl empty () {
111
118
return EMPTY ;
112
119
}
113
120
114
121
/**
115
- * Add a "max-age=" directive.
122
+ * Return a "max-age=" directive.
116
123
* <p>This directive is well suited for publicly caching resources, knowing that
117
124
* they won't change within the configured amount of time. Additional directives
118
125
* can be also used, in case resources shouldn't be cached ({@link #cachePrivate()})
@@ -122,7 +129,7 @@ public static CacheControl empty() {
122
129
* directive should be set ({@link #mustRevalidate()}
123
130
* @param maxAge the maximum time the response should be cached
124
131
* @param unit the time unit of the {@code maxAge} argument
125
- * @return {@code this}, to facilitate method chaining
132
+ * @return a CacheControl instance with a "max-age" directive
126
133
* @see #maxAge(Duration)
127
134
* @see <a href="https://tools.ietf.org/html/rfc7234#section-5.2.2.8">rfc7234 section 5.2.2.8</a>
128
135
*/
@@ -131,7 +138,7 @@ public static CacheControl maxAge(long maxAge, TimeUnit unit) {
131
138
}
132
139
133
140
/**
134
- * Add a "max-age=" directive.
141
+ * Return a "max-age=" directive.
135
142
* <p>This directive is well suited for publicly caching resources, knowing that
136
143
* they won't change within the configured amount of time. Additional directives
137
144
* can be also used, in case resources shouldn't be cached ({@link #cachePrivate()})
@@ -140,120 +147,120 @@ public static CacheControl maxAge(long maxAge, TimeUnit unit) {
140
147
* become stale (i.e. the "max-age" delay is passed), the "must-revalidate"
141
148
* directive should be set ({@link #mustRevalidate()}
142
149
* @param maxAge the maximum time the response should be cached
143
- * @return {@code this}, to facilitate method chaining
150
+ * @return a CacheControl instance with a "max-age" directive
144
151
* @since 5.2
145
152
* @see <a href="https://tools.ietf.org/html/rfc7234#section-5.2.2.8">rfc7234 section 5.2.2.8</a>
146
153
*/
147
154
public static CacheControl maxAge (Duration maxAge ) {
148
155
return new CacheControl (maxAge , false , false , false , false , false , false , false ,
149
- null , null , null , false );
156
+ null , null , null , false );
150
157
}
151
158
152
159
/**
153
- * Add a "no-cache" directive.
160
+ * Return a "no-cache" directive.
154
161
* <p>This directive is well suited for telling caches that the response
155
162
* can be reused only if the client revalidates it with the server.
156
163
* This directive won't disable cache altogether and may result with clients
157
164
* sending conditional requests (with "ETag", "If-Modified-Since" headers)
158
165
* and the server responding with "304 - Not Modified" status.
159
166
* <p>In order to disable caching and minimize requests/responses exchanges,
160
167
* the {@link #noStore()} directive should be used instead of {@code #noCache()}.
161
- * @return {@code this}, to facilitate method chaining
168
+ * @return a CacheControl instance with a "no-cache" directive
162
169
* @see <a href="https://tools.ietf.org/html/rfc7234#section-5.2.2.2">rfc7234 section 5.2.2.2</a>
163
170
*/
164
171
public static CacheControl noCache () {
165
172
return new CacheControl (null , true , false , false , false , false , false , false ,
166
- null , null , null , false );
173
+ null , null , null , false );
167
174
}
168
175
169
176
/**
170
- * Add a "no-store" directive.
177
+ * Return a "no-store" directive.
171
178
* <p>This directive is well suited for preventing caches (browsers and proxies)
172
179
* to cache the content of responses.
173
- * @return {@code this}, to facilitate method chaining
180
+ * @return a CacheControl instance with a "no-store" directive
174
181
* @see <a href="https://tools.ietf.org/html/rfc7234#section-5.2.2.3">rfc7234 section 5.2.2.3</a>
175
182
*/
176
183
public static CacheControl noStore () {
177
184
return new CacheControl (null , false , true , false , false , false , false , false ,
178
- null , null , null , false );
185
+ null , null , null , false );
179
186
}
180
187
181
188
182
189
/**
183
- * Add a "must-revalidate" directive.
190
+ * Return a new instance with an additional "must-revalidate" directive.
184
191
* <p>This directive indicates that once it has become stale, a cache MUST NOT
185
192
* use the response to satisfy subsequent requests without successful validation
186
193
* on the origin server.
187
- * @return {@code this}, to facilitate method chaining
194
+ * @return a new CacheControl instance with an additional "must-revalidate" directive
188
195
* @see <a href="https://tools.ietf.org/html/rfc7234#section-5.2.2.1">rfc7234 section 5.2.2.1</a>
189
196
*/
190
197
public CacheControl mustRevalidate () {
191
198
return new CacheControl (this .maxAge , this .noCache , this .noStore , true , this .noTransform ,
192
- this .cachePublic , this .cachePrivate , this .proxyRevalidate , this .staleWhileRevalidate ,
193
- this .staleIfError , this .sMaxAge , this .immutable );
199
+ this .cachePublic , this .cachePrivate , this .proxyRevalidate , this .staleWhileRevalidate ,
200
+ this .staleIfError , this .sMaxAge , this .immutable );
194
201
}
195
202
196
203
/**
197
- * Add a "no-transform" directive.
204
+ * Return a new instance with an additional "no-transform" directive.
198
205
* <p>This directive indicates that intermediaries (caches and others) should
199
206
* not transform the response content. This can be useful to force caches and
200
207
* CDNs not to automatically gzip or optimize the response content.
201
- * @return {@code this}, to facilitate method chaining
208
+ * @return a new CacheControl instance with an additional "no-transform" directive
202
209
* @see <a href="https://tools.ietf.org/html/rfc7234#section-5.2.2.4">rfc7234 section 5.2.2.4</a>
203
210
*/
204
211
public CacheControl noTransform () {
205
212
return new CacheControl (this .maxAge , this .noCache , this .noStore , this .mustRevalidate , true ,
206
- this .cachePublic , this .cachePrivate , this .proxyRevalidate , this .staleWhileRevalidate ,
207
- this .staleIfError , this .sMaxAge , this .immutable );
213
+ this .cachePublic , this .cachePrivate , this .proxyRevalidate , this .staleWhileRevalidate ,
214
+ this .staleIfError , this .sMaxAge , this .immutable );
208
215
}
209
216
210
217
/**
211
- * Add a "public" directive.
218
+ * Return a new instance with an additional "public" directive.
212
219
* <p>This directive indicates that any cache MAY store the response,
213
220
* even if the response would normally be non-cacheable or cacheable
214
221
* only within a private cache.
215
- * @return {@code this}, to facilitate method chaining
222
+ * @return a new CacheControl instance with an additional "public" directive
216
223
* @see <a href="https://tools.ietf.org/html/rfc7234#section-5.2.2.5">rfc7234 section 5.2.2.5</a>
217
224
*/
218
225
public CacheControl cachePublic () {
219
226
return new CacheControl (this .maxAge , this .noCache , this .noStore , this .mustRevalidate , this .noTransform ,
220
- true , this .cachePrivate , this .proxyRevalidate , this .staleWhileRevalidate ,
221
- this .staleIfError , this .sMaxAge , this .immutable );
227
+ true , this .cachePrivate , this .proxyRevalidate , this .staleWhileRevalidate ,
228
+ this .staleIfError , this .sMaxAge , this .immutable );
222
229
}
223
230
224
231
/**
225
- * Add a "private" directive.
232
+ * Return a new instance with an additional "private" directive.
226
233
* <p>This directive indicates that the response message is intended
227
234
* for a single user and MUST NOT be stored by a shared cache.
228
- * @return {@code this}, to facilitate method chaining
235
+ * @return a new CacheControl instance with an additional "private" directive
229
236
* @see <a href="https://tools.ietf.org/html/rfc7234#section-5.2.2.6">rfc7234 section 5.2.2.6</a>
230
237
*/
231
238
public CacheControl cachePrivate () {
232
239
return new CacheControl (this .maxAge , this .noCache , this .noStore , this .mustRevalidate , this .noTransform ,
233
- this .cachePublic , true , this .proxyRevalidate , this .staleWhileRevalidate ,
234
- this .staleIfError , this .sMaxAge , this .immutable );
240
+ this .cachePublic , true , this .proxyRevalidate , this .staleWhileRevalidate ,
241
+ this .staleIfError , this .sMaxAge , this .immutable );
235
242
}
236
243
237
244
/**
238
- * Add a "proxy-revalidate" directive.
245
+ * Return a new instance with an additional "proxy-revalidate" directive.
239
246
* <p>This directive has the same meaning as the "must-revalidate" directive,
240
247
* except that it does not apply to private caches (i.e. browsers, HTTP clients).
241
- * @return {@code this}, to facilitate method chaining
248
+ * @return a new CacheControl instance with an additional "proxy-revalidate" directive
242
249
* @see <a href="https://tools.ietf.org/html/rfc7234#section-5.2.2.7">rfc7234 section 5.2.2.7</a>
243
250
*/
244
251
public CacheControl proxyRevalidate () {
245
252
return new CacheControl (this .maxAge , this .noCache , this .noStore , this .mustRevalidate , this .noTransform ,
246
- this .cachePublic , this .cachePrivate , true , this .staleWhileRevalidate ,
247
- this .staleIfError , this .sMaxAge , this .immutable );
253
+ this .cachePublic , this .cachePrivate , true , this .staleWhileRevalidate ,
254
+ this .staleIfError , this .sMaxAge , this .immutable );
248
255
}
249
256
250
257
/**
251
- * Add an "s-maxage" directive.
258
+ * Return a new instance with an additional "s-maxage" directive.
252
259
* <p>This directive indicates that, in shared caches, the maximum age specified
253
260
* by this directive overrides the maximum age specified by other directives.
254
261
* @param sMaxAge the maximum time the response should be cached
255
262
* @param unit the time unit of the {@code sMaxAge} argument
256
- * @return {@code this}, to facilitate method chaining
263
+ * @return a new CacheControl instance with an additional "s-maxage" directive
257
264
* @see #sMaxAge(Duration)
258
265
* @see <a href="https://tools.ietf.org/html/rfc7234#section-5.2.2.9">rfc7234 section 5.2.2.9</a>
259
266
*/
@@ -262,30 +269,30 @@ public CacheControl sMaxAge(long sMaxAge, TimeUnit unit) {
262
269
}
263
270
264
271
/**
265
- * Add an "s-maxage" directive.
272
+ * Return a new instance with an additional "s-maxage" directive.
266
273
* <p>This directive indicates that, in shared caches, the maximum age specified
267
274
* by this directive overrides the maximum age specified by other directives.
268
275
* @param sMaxAge the maximum time the response should be cached
269
- * @return {@code this}, to facilitate method chaining
276
+ * @return a new CacheControl instance with an additional "s-maxage" directive
270
277
* @since 5.2
271
278
* @see <a href="https://tools.ietf.org/html/rfc7234#section-5.2.2.9">rfc7234 section 5.2.2.9</a>
272
279
*/
273
280
public CacheControl sMaxAge (Duration sMaxAge ) {
274
281
return new CacheControl (this .maxAge , this .noCache , this .noStore , this .mustRevalidate , this .noTransform ,
275
- this .cachePublic , this .cachePrivate , this .proxyRevalidate , this .staleWhileRevalidate ,
276
- this .staleIfError , sMaxAge , this .immutable );
282
+ this .cachePublic , this .cachePrivate , this .proxyRevalidate , this .staleWhileRevalidate ,
283
+ this .staleIfError , sMaxAge , this .immutable );
277
284
}
278
285
279
286
/**
280
- * Add a "stale-while-revalidate" directive.
287
+ * Return a new instance with an additional "stale-while-revalidate" directive.
281
288
* <p>This directive indicates that caches MAY serve the response in which it
282
289
* appears after it becomes stale, up to the indicated number of seconds.
283
290
* If a cached response is served stale due to the presence of this extension,
284
291
* the cache SHOULD attempt to revalidate it while still serving stale responses
285
292
* (i.e. without blocking).
286
293
* @param staleWhileRevalidate the maximum time the response should be used while being revalidated
287
294
* @param unit the time unit of the {@code staleWhileRevalidate} argument
288
- * @return {@code this}, to facilitate method chaining
295
+ * @return a new CacheControl instance with an additional "stale-while-revalidate" directive
289
296
* @see #staleWhileRevalidate(Duration)
290
297
* @see <a href="https://tools.ietf.org/html/rfc5861#section-3">rfc5861 section 3</a>
291
298
*/
@@ -294,30 +301,30 @@ public CacheControl staleWhileRevalidate(long staleWhileRevalidate, TimeUnit uni
294
301
}
295
302
296
303
/**
297
- * Add a "stale-while-revalidate" directive.
304
+ * Return a new instance with an additional "stale-while-revalidate" directive.
298
305
* <p>This directive indicates that caches MAY serve the response in which it
299
306
* appears after it becomes stale, up to the indicated number of seconds.
300
307
* If a cached response is served stale due to the presence of this extension,
301
308
* the cache SHOULD attempt to revalidate it while still serving stale responses
302
309
* (i.e. without blocking).
303
310
* @param staleWhileRevalidate the maximum time the response should be used while being revalidated
304
- * @return {@code this}, to facilitate method chaining
311
+ * @return a new CacheControl instance with an additional "stale-while-revalidate" directive
305
312
* @since 5.2
306
313
* @see <a href="https://tools.ietf.org/html/rfc5861#section-3">rfc5861 section 3</a>
307
314
*/
308
315
public CacheControl staleWhileRevalidate (Duration staleWhileRevalidate ) {
309
316
return new CacheControl (this .maxAge , this .noCache , this .noStore , this .mustRevalidate , this .noTransform ,
310
- this .cachePublic , this .cachePrivate , this .proxyRevalidate , staleWhileRevalidate ,
311
- this .staleIfError , this .sMaxAge , this .immutable );
317
+ this .cachePublic , this .cachePrivate , this .proxyRevalidate , staleWhileRevalidate ,
318
+ this .staleIfError , this .sMaxAge , this .immutable );
312
319
}
313
320
314
321
/**
315
- * Add a "stale-if-error" directive.
322
+ * Return a new instance with an additional "stale-if-error" directive.
316
323
* <p>This directive indicates that when an error is encountered, a cached stale response
317
324
* MAY be used to satisfy the request, regardless of other freshness information.
318
325
* @param staleIfError the maximum time the response should be used when errors are encountered
319
326
* @param unit the time unit of the {@code staleIfError} argument
320
- * @return {@code this}, to facilitate method chaining
327
+ * @return a new CacheControl instance with an additional "stale-if-error" directive
321
328
* @see #staleIfError(Duration)
322
329
* @see <a href="https://tools.ietf.org/html/rfc5861#section-4">rfc5861 section 4</a>
323
330
*/
@@ -326,34 +333,34 @@ public CacheControl staleIfError(long staleIfError, TimeUnit unit) {
326
333
}
327
334
328
335
/**
329
- * Add a "stale-if-error" directive.
336
+ * Return a new instance with an additional "stale-if-error" directive.
330
337
* <p>This directive indicates that when an error is encountered, a cached stale response
331
338
* MAY be used to satisfy the request, regardless of other freshness information.
332
339
* @param staleIfError the maximum time the response should be used when errors are encountered
333
- * @return {@code this}, to facilitate method chaining
340
+ * @return a new CacheControl instance with an additional "stale-if-error" directive
334
341
* @since 5.2
335
342
* @see <a href="https://tools.ietf.org/html/rfc5861#section-4">rfc5861 section 4</a>
336
343
*/
337
344
public CacheControl staleIfError (Duration staleIfError ) {
338
345
return new CacheControl (this .maxAge , this .noCache , this .noStore , this .mustRevalidate , this .noTransform ,
339
- this .cachePublic , this .cachePrivate , this .proxyRevalidate , this .staleWhileRevalidate ,
340
- staleIfError , this .sMaxAge , this .immutable );
346
+ this .cachePublic , this .cachePrivate , this .proxyRevalidate , this .staleWhileRevalidate ,
347
+ staleIfError , this .sMaxAge , this .immutable );
341
348
}
342
349
343
350
/**
344
- * Add an "immutable" directive.
351
+ * Return a new instance with an additional "immutable" directive.
345
352
* <p>This directive indicates that the origin server will not update the
346
353
* representation of that resource during the freshness lifetime of the response.
347
354
* Adding a {@link #maxAge(Duration) max-age} directive is strongly advised
348
355
* to enforce the actual freshness lifetime.
349
- * @return {@code this}, to facilitate method chaining
356
+ * @return a new CacheControl instance with an additional "immutable" directive
350
357
* @since 6.0.5
351
358
* @see <a href="https://tools.ietf.org/html/rfc8246">rfc8246</a>
352
359
*/
353
360
public CacheControl immutable () {
354
361
return new CacheControl (this .maxAge , this .noCache , this .noStore , this .mustRevalidate , this .noTransform ,
355
- this .cachePublic , this .cachePrivate , this .proxyRevalidate , this .staleWhileRevalidate ,
356
- this .staleIfError , this .sMaxAge , true );
362
+ this .cachePublic , this .cachePrivate , this .proxyRevalidate , this .staleWhileRevalidate ,
363
+ this .staleIfError , this .sMaxAge , true );
357
364
}
358
365
359
366
/**
0 commit comments