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