diff --git a/spring-web/src/main/java/org/springframework/http/CacheControl.java b/spring-web/src/main/java/org/springframework/http/CacheControl.java index 6cd1f6fd63..e8142d6804 100644 --- a/spring-web/src/main/java/org/springframework/http/CacheControl.java +++ b/spring-web/src/main/java/org/springframework/http/CacheControl.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2023 the original author or authors. + * Copyright 2002-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,7 +23,8 @@ import org.springframework.lang.Nullable; import org.springframework.util.StringUtils; /** - * A builder for creating "Cache-Control" HTTP response headers. + * A builder for creating "Cache-Control" HTTP response headers. As of Spring + * Framework 6.2, this class is immutable. * *
Adding Cache-Control directives to HTTP responses can significantly improve the client * experience when interacting with a web application. This builder creates opinionated @@ -51,9 +52,7 @@ import org.springframework.util.StringUtils; */ public class CacheControl { - private static final CacheControl EMPTY = new CacheControl(null, false, false, false, - false, false, false, false, null, null, - null, false); + private static final CacheControl EMPTY = new CacheControl(); @Nullable private final Duration maxAge; @@ -83,10 +82,18 @@ public class CacheControl { private final boolean immutable; + /** + * Create an empty CacheControl instance. + * @see #empty() + */ + protected CacheControl() { + this(null, false, false, false, false, false, false, false, null, null, null, false); + } + private CacheControl(@Nullable Duration maxAge, boolean noCache, boolean noStore, - boolean mustRevalidate, boolean noTransform, boolean cachePublic, - boolean cachePrivate, boolean proxyRevalidate, @Nullable Duration staleWhileRevalidate, - @Nullable Duration staleIfError, @Nullable Duration sMaxAge, boolean immutable) { + boolean mustRevalidate, boolean noTransform, boolean cachePublic, + boolean cachePrivate, boolean proxyRevalidate, @Nullable Duration staleWhileRevalidate, + @Nullable Duration staleIfError, @Nullable Duration sMaxAge, boolean immutable) { this.maxAge = maxAge; this.noCache = noCache; this.noStore = noStore; @@ -105,14 +112,14 @@ public class CacheControl { * Return an empty directive. *
This is well suited for using other optional directives without "max-age", * "no-cache" or "no-store". - * @return {@code this}, to facilitate method chaining + * @return en empty directive */ public static CacheControl empty() { return EMPTY; } /** - * Add a "max-age=" directive. + * Return a "max-age=" directive. *
This directive is well suited for publicly caching resources, knowing that * they won't change within the configured amount of time. Additional directives * can be also used, in case resources shouldn't be cached ({@link #cachePrivate()}) @@ -122,7 +129,7 @@ public class CacheControl { * directive should be set ({@link #mustRevalidate()} * @param maxAge the maximum time the response should be cached * @param unit the time unit of the {@code maxAge} argument - * @return {@code this}, to facilitate method chaining + * @return a CacheControl instance with a "max-age" directive * @see #maxAge(Duration) * @see rfc7234 section 5.2.2.8 */ @@ -131,7 +138,7 @@ public class CacheControl { } /** - * Add a "max-age=" directive. + * Return a "max-age=" directive. *
This directive is well suited for publicly caching resources, knowing that * they won't change within the configured amount of time. Additional directives * can be also used, in case resources shouldn't be cached ({@link #cachePrivate()}) @@ -140,17 +147,17 @@ public class CacheControl { * become stale (i.e. the "max-age" delay is passed), the "must-revalidate" * directive should be set ({@link #mustRevalidate()} * @param maxAge the maximum time the response should be cached - * @return {@code this}, to facilitate method chaining + * @return a CacheControl instance with a "max-age" directive * @since 5.2 * @see rfc7234 section 5.2.2.8 */ public static CacheControl maxAge(Duration maxAge) { return new CacheControl(maxAge, false, false, false, false, false, false, false, - null, null, null, false); + null, null, null, false); } /** - * Add a "no-cache" directive. + * Return a "no-cache" directive. *
This directive is well suited for telling caches that the response * can be reused only if the client revalidates it with the server. * This directive won't disable cache altogether and may result with clients @@ -158,102 +165,102 @@ public class CacheControl { * and the server responding with "304 - Not Modified" status. *
In order to disable caching and minimize requests/responses exchanges, * the {@link #noStore()} directive should be used instead of {@code #noCache()}. - * @return {@code this}, to facilitate method chaining + * @return a CacheControl instance with a "no-cache" directive * @see rfc7234 section 5.2.2.2 */ public static CacheControl noCache() { return new CacheControl(null, true, false, false, false, false, false, false, - null, null, null, false); + null, null, null, false); } /** - * Add a "no-store" directive. + * Return a "no-store" directive. *
This directive is well suited for preventing caches (browsers and proxies) * to cache the content of responses. - * @return {@code this}, to facilitate method chaining + * @return a CacheControl instance with a "no-store" directive * @see rfc7234 section 5.2.2.3 */ public static CacheControl noStore() { return new CacheControl(null, false, true, false, false, false, false, false, - null, null, null, false); + null, null, null, false); } /** - * Add a "must-revalidate" directive. + * Return a new instance with an additional "must-revalidate" directive. *
This directive indicates that once it has become stale, a cache MUST NOT * use the response to satisfy subsequent requests without successful validation * on the origin server. - * @return {@code this}, to facilitate method chaining + * @return a new CacheControl instance with an additional "must-revalidate" directive * @see rfc7234 section 5.2.2.1 */ public CacheControl mustRevalidate() { return new CacheControl(this.maxAge, this.noCache, this.noStore, true, this.noTransform, - this.cachePublic, this.cachePrivate, this.proxyRevalidate, this.staleWhileRevalidate, - this.staleIfError, this.sMaxAge, this.immutable); + this.cachePublic, this.cachePrivate, this.proxyRevalidate, this.staleWhileRevalidate, + this.staleIfError, this.sMaxAge, this.immutable); } /** - * Add a "no-transform" directive. + * Return a new instance with an additional "no-transform" directive. *
This directive indicates that intermediaries (caches and others) should * not transform the response content. This can be useful to force caches and * CDNs not to automatically gzip or optimize the response content. - * @return {@code this}, to facilitate method chaining + * @return a new CacheControl instance with an additional "no-transform" directive * @see rfc7234 section 5.2.2.4 */ public CacheControl noTransform() { return new CacheControl(this.maxAge, this.noCache, this.noStore, this.mustRevalidate, true, - this.cachePublic, this.cachePrivate, this.proxyRevalidate, this.staleWhileRevalidate, - this.staleIfError, this.sMaxAge, this.immutable); + this.cachePublic, this.cachePrivate, this.proxyRevalidate, this.staleWhileRevalidate, + this.staleIfError, this.sMaxAge, this.immutable); } /** - * Add a "public" directive. + * Return a new instance with an additional "public" directive. *
This directive indicates that any cache MAY store the response, * even if the response would normally be non-cacheable or cacheable * only within a private cache. - * @return {@code this}, to facilitate method chaining + * @return a new CacheControl instance with an additional "public" directive * @see rfc7234 section 5.2.2.5 */ public CacheControl cachePublic() { return new CacheControl(this.maxAge, this.noCache, this.noStore, this.mustRevalidate, this.noTransform, - true, this.cachePrivate, this.proxyRevalidate, this.staleWhileRevalidate, - this.staleIfError, this.sMaxAge, this.immutable); + true, this.cachePrivate, this.proxyRevalidate, this.staleWhileRevalidate, + this.staleIfError, this.sMaxAge, this.immutable); } /** - * Add a "private" directive. + * Return a new instance with an additional "private" directive. *
This directive indicates that the response message is intended * for a single user and MUST NOT be stored by a shared cache. - * @return {@code this}, to facilitate method chaining + * @return a new CacheControl instance with an additional "private" directive * @see rfc7234 section 5.2.2.6 */ public CacheControl cachePrivate() { return new CacheControl(this.maxAge, this.noCache, this.noStore, this.mustRevalidate, this.noTransform, - this.cachePublic, true, this.proxyRevalidate, this.staleWhileRevalidate, - this.staleIfError, this.sMaxAge, this.immutable); + this.cachePublic, true, this.proxyRevalidate, this.staleWhileRevalidate, + this.staleIfError, this.sMaxAge, this.immutable); } /** - * Add a "proxy-revalidate" directive. + * Return a new instance with an additional "proxy-revalidate" directive. *
This directive has the same meaning as the "must-revalidate" directive, * except that it does not apply to private caches (i.e. browsers, HTTP clients). - * @return {@code this}, to facilitate method chaining + * @return a new CacheControl instance with an additional "proxy-revalidate" directive * @see rfc7234 section 5.2.2.7 */ public CacheControl proxyRevalidate() { return new CacheControl(this.maxAge, this.noCache, this.noStore, this.mustRevalidate, this.noTransform, - this.cachePublic, this.cachePrivate, true, this.staleWhileRevalidate, - this.staleIfError, this.sMaxAge, this.immutable); + this.cachePublic, this.cachePrivate, true, this.staleWhileRevalidate, + this.staleIfError, this.sMaxAge, this.immutable); } /** - * Add an "s-maxage" directive. + * Return a new instance with an additional "s-maxage" directive. *
This directive indicates that, in shared caches, the maximum age specified * by this directive overrides the maximum age specified by other directives. * @param sMaxAge the maximum time the response should be cached * @param unit the time unit of the {@code sMaxAge} argument - * @return {@code this}, to facilitate method chaining + * @return a new CacheControl instance with an additional "s-maxage" directive * @see #sMaxAge(Duration) * @see rfc7234 section 5.2.2.9 */ @@ -262,22 +269,22 @@ public class CacheControl { } /** - * Add an "s-maxage" directive. + * Return a new instance with an additional "s-maxage" directive. *
This directive indicates that, in shared caches, the maximum age specified * by this directive overrides the maximum age specified by other directives. * @param sMaxAge the maximum time the response should be cached - * @return {@code this}, to facilitate method chaining + * @return a new CacheControl instance with an additional "s-maxage" directive * @since 5.2 * @see rfc7234 section 5.2.2.9 */ public CacheControl sMaxAge(Duration sMaxAge) { return new CacheControl(this.maxAge, this.noCache, this.noStore, this.mustRevalidate, this.noTransform, - this.cachePublic, this.cachePrivate, this.proxyRevalidate, this.staleWhileRevalidate, - this.staleIfError, sMaxAge, this.immutable); + this.cachePublic, this.cachePrivate, this.proxyRevalidate, this.staleWhileRevalidate, + this.staleIfError, sMaxAge, this.immutable); } /** - * Add a "stale-while-revalidate" directive. + * Return a new instance with an additional "stale-while-revalidate" directive. *
This directive indicates that caches MAY serve the response in which it * appears after it becomes stale, up to the indicated number of seconds. * If a cached response is served stale due to the presence of this extension, @@ -285,7 +292,7 @@ public class CacheControl { * (i.e. without blocking). * @param staleWhileRevalidate the maximum time the response should be used while being revalidated * @param unit the time unit of the {@code staleWhileRevalidate} argument - * @return {@code this}, to facilitate method chaining + * @return a new CacheControl instance with an additional "stale-while-revalidate" directive * @see #staleWhileRevalidate(Duration) * @see rfc5861 section 3 */ @@ -294,30 +301,30 @@ public class CacheControl { } /** - * Add a "stale-while-revalidate" directive. + * Return a new instance with an additional "stale-while-revalidate" directive. *
This directive indicates that caches MAY serve the response in which it * appears after it becomes stale, up to the indicated number of seconds. * If a cached response is served stale due to the presence of this extension, * the cache SHOULD attempt to revalidate it while still serving stale responses * (i.e. without blocking). * @param staleWhileRevalidate the maximum time the response should be used while being revalidated - * @return {@code this}, to facilitate method chaining + * @return a new CacheControl instance with an additional "stale-while-revalidate" directive * @since 5.2 * @see rfc5861 section 3 */ public CacheControl staleWhileRevalidate(Duration staleWhileRevalidate) { return new CacheControl(this.maxAge, this.noCache, this.noStore, this.mustRevalidate, this.noTransform, - this.cachePublic, this.cachePrivate, this.proxyRevalidate, staleWhileRevalidate, - this.staleIfError, this.sMaxAge, this.immutable); + this.cachePublic, this.cachePrivate, this.proxyRevalidate, staleWhileRevalidate, + this.staleIfError, this.sMaxAge, this.immutable); } /** - * Add a "stale-if-error" directive. + * Return a new instance with an additional "stale-if-error" directive. *
This directive indicates that when an error is encountered, a cached stale response * MAY be used to satisfy the request, regardless of other freshness information. * @param staleIfError the maximum time the response should be used when errors are encountered * @param unit the time unit of the {@code staleIfError} argument - * @return {@code this}, to facilitate method chaining + * @return a new CacheControl instance with an additional "stale-if-error" directive * @see #staleIfError(Duration) * @see rfc5861 section 4 */ @@ -326,34 +333,34 @@ public class CacheControl { } /** - * Add a "stale-if-error" directive. + * Return a new instance with an additional "stale-if-error" directive. *
This directive indicates that when an error is encountered, a cached stale response * MAY be used to satisfy the request, regardless of other freshness information. * @param staleIfError the maximum time the response should be used when errors are encountered - * @return {@code this}, to facilitate method chaining + * @return a new CacheControl instance with an additional "stale-if-error" directive * @since 5.2 * @see rfc5861 section 4 */ public CacheControl staleIfError(Duration staleIfError) { return new CacheControl(this.maxAge, this.noCache, this.noStore, this.mustRevalidate, this.noTransform, - this.cachePublic, this.cachePrivate, this.proxyRevalidate, this.staleWhileRevalidate, - staleIfError, this.sMaxAge, this.immutable); + this.cachePublic, this.cachePrivate, this.proxyRevalidate, this.staleWhileRevalidate, + staleIfError, this.sMaxAge, this.immutable); } /** - * Add an "immutable" directive. + * Return a new instance with an additional "immutable" directive. *
This directive indicates that the origin server will not update the * representation of that resource during the freshness lifetime of the response. * Adding a {@link #maxAge(Duration) max-age} directive is strongly advised * to enforce the actual freshness lifetime. - * @return {@code this}, to facilitate method chaining + * @return a new CacheControl instance with an additional "immutable" directive * @since 6.0.5 * @see rfc8246 */ public CacheControl immutable() { return new CacheControl(this.maxAge, this.noCache, this.noStore, this.mustRevalidate, this.noTransform, - this.cachePublic, this.cachePrivate, this.proxyRevalidate, this.staleWhileRevalidate, - this.staleIfError, this.sMaxAge, true); + this.cachePublic, this.cachePrivate, this.proxyRevalidate, this.staleWhileRevalidate, + this.staleIfError, this.sMaxAge, true); } /**