Skip to content

Commit 1ceb3fa

Browse files
committed
Migrate CacheControl to use java.time.Duration for durations
1 parent 238286c commit 1ceb3fa

File tree

2 files changed

+102
-18
lines changed

2 files changed

+102
-18
lines changed

spring-web/src/main/java/org/springframework/http/CacheControl.java

+77-18
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.http;
1818

19+
import java.time.Duration;
1920
import java.util.concurrent.TimeUnit;
2021

2122
import org.springframework.lang.Nullable;
@@ -50,7 +51,8 @@
5051
*/
5152
public class CacheControl {
5253

53-
private long maxAge = -1;
54+
@Nullable
55+
private Duration maxAge = null;
5456

5557
private boolean noCache = false;
5658

@@ -66,12 +68,14 @@ public class CacheControl {
6668

6769
private boolean proxyRevalidate = false;
6870

69-
private long staleWhileRevalidate = -1;
70-
71-
private long staleIfError = -1;
71+
@Nullable
72+
private Duration staleWhileRevalidate = null;
7273

73-
private long sMaxAge = -1;
74+
@Nullable
75+
private Duration staleIfError = null;
7476

77+
@Nullable
78+
private Duration sMaxAge = null;
7579

7680
/**
7781
* Create an empty CacheControl instance.
@@ -106,8 +110,25 @@ public static CacheControl empty() {
106110
* @see <a href="https://tools.ietf.org/html/rfc7234#section-5.2.2.8">rfc7234 section 5.2.2.8</a>
107111
*/
108112
public static CacheControl maxAge(long maxAge, TimeUnit unit) {
113+
return maxAge(Duration.ofSeconds(unit.toSeconds(maxAge)));
114+
}
115+
116+
/**
117+
* Add a "max-age=" directive.
118+
* <p>This directive is well suited for publicly caching resources, knowing that
119+
* they won't change within the configured amount of time. Additional directives
120+
* can be also used, in case resources shouldn't be cached ({@link #cachePrivate()})
121+
* or transformed ({@link #noTransform()}) by shared caches.
122+
* <p>In order to prevent caches to reuse the cached response even when it has
123+
* become stale (i.e. the "max-age" delay is passed), the "must-revalidate"
124+
* directive should be set ({@link #mustRevalidate()}
125+
* @param maxAge the maximum time the response should be cached
126+
* @return {@code this}, to facilitate method chaining
127+
* @see <a href="https://tools.ietf.org/html/rfc7234#section-5.2.2.8">rfc7234 section 5.2.2.8</a>
128+
*/
129+
public static CacheControl maxAge(Duration maxAge) {
109130
CacheControl cc = new CacheControl();
110-
cc.maxAge = unit.toSeconds(maxAge);
131+
cc.maxAge = maxAge;
111132
return cc;
112133
}
113134

@@ -216,7 +237,19 @@ public CacheControl proxyRevalidate() {
216237
* @see <a href="https://tools.ietf.org/html/rfc7234#section-5.2.2.9">rfc7234 section 5.2.2.9</a>
217238
*/
218239
public CacheControl sMaxAge(long sMaxAge, TimeUnit unit) {
219-
this.sMaxAge = unit.toSeconds(sMaxAge);
240+
return sMaxAge(Duration.ofSeconds(unit.toSeconds(sMaxAge)));
241+
}
242+
243+
/**
244+
* Add an "s-maxage" directive.
245+
* <p>This directive indicates that, in shared caches, the maximum age specified
246+
* by this directive overrides the maximum age specified by other directives.
247+
* @param sMaxAge the maximum time the response should be cached
248+
* @return {@code this}, to facilitate method chaining
249+
* @see <a href="https://tools.ietf.org/html/rfc7234#section-5.2.2.9">rfc7234 section 5.2.2.9</a>
250+
*/
251+
public CacheControl sMaxAge(Duration sMaxAge) {
252+
this.sMaxAge = sMaxAge;
220253
return this;
221254
}
222255

@@ -233,7 +266,22 @@ public CacheControl sMaxAge(long sMaxAge, TimeUnit unit) {
233266
* @see <a href="https://tools.ietf.org/html/rfc5861#section-3">rfc5861 section 3</a>
234267
*/
235268
public CacheControl staleWhileRevalidate(long staleWhileRevalidate, TimeUnit unit) {
236-
this.staleWhileRevalidate = unit.toSeconds(staleWhileRevalidate);
269+
return staleWhileRevalidate(Duration.ofSeconds(unit.toSeconds(staleWhileRevalidate)));
270+
}
271+
272+
/**
273+
* Add a "stale-while-revalidate" directive.
274+
* <p>This directive indicates that caches MAY serve the response in which it
275+
* appears after it becomes stale, up to the indicated number of seconds.
276+
* If a cached response is served stale due to the presence of this extension,
277+
* the cache SHOULD attempt to revalidate it while still serving stale responses
278+
* (i.e. without blocking).
279+
* @param staleWhileRevalidate the maximum time the response should be used while being revalidated
280+
* @return {@code this}, to facilitate method chaining
281+
* @see <a href="https://tools.ietf.org/html/rfc5861#section-3">rfc5861 section 3</a>
282+
*/
283+
public CacheControl staleWhileRevalidate(Duration staleWhileRevalidate) {
284+
this.staleWhileRevalidate = staleWhileRevalidate;
237285
return this;
238286
}
239287

@@ -247,10 +295,21 @@ public CacheControl staleWhileRevalidate(long staleWhileRevalidate, TimeUnit uni
247295
* @see <a href="https://tools.ietf.org/html/rfc5861#section-4">rfc5861 section 4</a>
248296
*/
249297
public CacheControl staleIfError(long staleIfError, TimeUnit unit) {
250-
this.staleIfError = unit.toSeconds(staleIfError);
251-
return this;
298+
return staleIfError(Duration.ofSeconds(unit.toSeconds(staleIfError)));
252299
}
253300

301+
/**
302+
* Add a "stale-if-error" directive.
303+
* <p>This directive indicates that when an error is encountered, a cached stale response
304+
* MAY be used to satisfy the request, regardless of other freshness information.
305+
* @param staleIfError the maximum time the response should be used when errors are encountered
306+
* @return {@code this}, to facilitate method chaining
307+
* @see <a href="https://tools.ietf.org/html/rfc5861#section-4">rfc5861 section 4</a>
308+
*/
309+
public CacheControl staleIfError(Duration staleIfError) {
310+
this.staleIfError = staleIfError;
311+
return this;
312+
}
254313

255314
/**
256315
* Return the "Cache-Control" header value, if any.
@@ -268,8 +327,8 @@ public String getHeaderValue() {
268327
*/
269328
private String toHeaderValue() {
270329
StringBuilder headerValue = new StringBuilder();
271-
if (this.maxAge != -1) {
272-
appendDirective(headerValue, "max-age=" + this.maxAge);
330+
if (this.maxAge != null) {
331+
appendDirective(headerValue, "max-age=" + this.maxAge.getSeconds());
273332
}
274333
if (this.noCache) {
275334
appendDirective(headerValue, "no-cache");
@@ -292,14 +351,14 @@ private String toHeaderValue() {
292351
if (this.proxyRevalidate) {
293352
appendDirective(headerValue, "proxy-revalidate");
294353
}
295-
if (this.sMaxAge != -1) {
296-
appendDirective(headerValue, "s-maxage=" + this.sMaxAge);
354+
if (this.sMaxAge != null) {
355+
appendDirective(headerValue, "s-maxage=" + this.sMaxAge.getSeconds());
297356
}
298-
if (this.staleIfError != -1) {
299-
appendDirective(headerValue, "stale-if-error=" + this.staleIfError);
357+
if (this.staleIfError != null) {
358+
appendDirective(headerValue, "stale-if-error=" + this.staleIfError.getSeconds());
300359
}
301-
if (this.staleWhileRevalidate != -1) {
302-
appendDirective(headerValue, "stale-while-revalidate=" + this.staleWhileRevalidate);
360+
if (this.staleWhileRevalidate != null) {
361+
appendDirective(headerValue, "stale-while-revalidate=" + this.staleWhileRevalidate.getSeconds());
303362
}
304363
return headerValue.toString();
305364
}

spring-web/src/test/java/org/springframework/http/CacheControlTests.java

+25
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import static org.junit.Assert.*;
2323

24+
import java.time.Duration;
2425
import java.util.concurrent.TimeUnit;
2526

2627
/**
@@ -40,6 +41,12 @@ public void maxAge() throws Exception {
4041
assertThat(cc.getHeaderValue(), Matchers.equalTo("max-age=3600"));
4142
}
4243

44+
@Test
45+
public void maxAge_duration() throws Exception {
46+
CacheControl cc = CacheControl.maxAge(Duration.ofHours(1));
47+
assertThat(cc.getHeaderValue(), Matchers.equalTo("max-age=3600"));
48+
}
49+
4350
@Test
4451
public void maxAgeAndDirectives() throws Exception {
4552
CacheControl cc = CacheControl.maxAge(3600, TimeUnit.SECONDS).cachePublic().noTransform();
@@ -52,6 +59,12 @@ public void maxAgeAndSMaxAge() throws Exception {
5259
assertThat(cc.getHeaderValue(), Matchers.equalTo("max-age=3600, s-maxage=1800"));
5360
}
5461

62+
@Test
63+
public void maxAgeAndSMaxAge_duration() throws Exception {
64+
CacheControl cc = CacheControl.maxAge(Duration.ofHours(1)).sMaxAge(Duration.ofMinutes(30));
65+
assertThat(cc.getHeaderValue(), Matchers.equalTo("max-age=3600, s-maxage=1800"));
66+
}
67+
5568
@Test
5669
public void noCachePrivate() throws Exception {
5770
CacheControl cc = CacheControl.noCache().cachePrivate();
@@ -70,10 +83,22 @@ public void staleIfError() throws Exception {
7083
assertThat(cc.getHeaderValue(), Matchers.equalTo("max-age=3600, stale-if-error=7200"));
7184
}
7285

86+
@Test
87+
public void staleIfError_duration() throws Exception {
88+
CacheControl cc = CacheControl.maxAge(Duration.ofHours(1)).staleIfError(2, TimeUnit.HOURS);
89+
assertThat(cc.getHeaderValue(), Matchers.equalTo("max-age=3600, stale-if-error=7200"));
90+
}
91+
7392
@Test
7493
public void staleWhileRevalidate() throws Exception {
7594
CacheControl cc = CacheControl.maxAge(1, TimeUnit.HOURS).staleWhileRevalidate(2, TimeUnit.HOURS);
7695
assertThat(cc.getHeaderValue(), Matchers.equalTo("max-age=3600, stale-while-revalidate=7200"));
7796
}
7897

98+
@Test
99+
public void staleWhileRevalidate_duration() throws Exception {
100+
CacheControl cc = CacheControl.maxAge(Duration.ofHours(1)).staleWhileRevalidate(2, TimeUnit.HOURS);
101+
assertThat(cc.getHeaderValue(), Matchers.equalTo("max-age=3600, stale-while-revalidate=7200"));
102+
}
103+
79104
}

0 commit comments

Comments
 (0)