How to add Cache-Control header to static resource in Spring Boot?

how to set cache-control header in spring boot
spring boot http header cache-control
how to set cache-control header in java
spring headers cachecontrol
spring static resource versioning
spring boot resources folder
spring boot disable cache
spring boot hostname property

How can I add Cache-Control HTTP header in Spring Boot for static resources?

Tried using a filter-component in the application, which writes headers correctly, but Cache-Control header gets overwritten.

@Component
public class CacheBustingFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) 
                                              throws IOException, ServletException {

        HttpServletResponse httpResp = (HttpServletResponse) resp;
        httpResp.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
        httpResp.setHeader("This-Header-Is-Set", "no-cache, no-store, must-revalidate");
        httpResp.setHeader("Expires", "0");

        chain.doFilter(req, resp);
    }

What I get in the browser is:

Cache-Control:no-store
This-Header-Is-Set:no-cache, no-store, must-revalidate
Expires:0

What I would like is:

Cache-Control:no-cache, no-store, must-revalidate
This-Header-Is-Set:no-cache, no-store, must-revalidate
Expires:0

As per the documentation, of ResourceHandlerRegistry. It is pretty easy. (I have no code related to it right now.)

In the place where you configure your static resources just add addResourceHandler method, It will return ResourceHandlerRegistration object.

There you can use setCacheControl method. What you have to do is configure and set a CacheControl obejct.

This is since spring 4.2, else you will have to do it like below.

@Configuration
@EnableWebMvc
@ComponentScan("my.packages.here")
public class WebConfig extends WebMvcConfigurerAdapter {


   @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/**").setCachePeriod(0);
    }

}

Cachable Static Assets with Spring MVC, This article shows how to cache your static assets such as Javascript and CSS files Here's a simple example of how to do that – setting the Cache-Control header on the To customize the Cache-Control headers in Spring Boot, we can use This applies to all static resources served by Spring Boot. In Spring Boot, we can set spring.resources.cache-period property to specify the cache period for the static resources in seconds. By default this value is zero. The value set to this property (say n) will cause the response header of Cache-Control:max-age=n to be sent to the browser.

This happens because of Spring Security: it rewrites all cache headers to disable caching totally. So we need to do two things:

  1. Disable spring security for static resources
  2. Enable static resource cache processing

In current version of Spring Boot we can change this behavior in application.properties config.

Disable spring security for some resources:

# Comma-separated list of paths to exclude from the default secured 
security.ignored=/myAssets/**

Enable sending cache headers for static resources:

# Enable HTML5 application cache manifest rewriting.
spring.resources.chain.html-application-cache=true

# Enable the Spring Resource Handling chain. Disabled by default unless at least one strategy has been enabled.
spring.resources.chain.enabled=true
# Enable the content Version Strategy.
spring.resources.chain.strategy.content.enabled=true 
# Comma-separated list of patterns to apply to the Version Strategy.
spring.resources.chain.strategy.content.paths=/** 

# Locations of static resources.
spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/

That's all. Now Spring will check if your static files was changed and can send smarter responses (If-Modiffied-Since and others) and rewrite your appcache also.

Also, if there are reasons to not use content-based version for some resources - you can use alternate FixedVersion strategy and set version explicitly in your config:

#Enable the fixed Version Strategy.
spring.resources.chain.strategy.fixed.enabled=false 
# Comma-separated list of patterns to apply to the Version Strategy.
spring.resources.chain.strategy.fixed.paths= 
# Version string to use for the Version Strategy.
spring.resources.chain.strategy.fixed.version= 

See more in docs

Set CacheControl for static resources from properties file · Issue , Currently, we can set the max-age of static resources by setting I'd like to have a set of properties ( spring.resources.cache-control. CacheControl has 4 static methods to help avoid building a Cache-Control header with incompatible tinexw added a commit to tinexw/spring-boot that referenced this  Simply adding the <headers> element with no child elements will automatically add Cache Control and quite a few other protections. However, if you only want cache control, you can enable this feature using Spring Security’s XML namespace with the <cache-control> element and the [email protected]attribute.

The are properties that control the default cache headers for resources:

spring.resources.cache.cachecontrol.max-age: 3600

https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html

Spring Boot - Setting Cache Period for Static Resources, The value set to this property (say n) will cause the response header of Cache-​Control:max-age=n to be sent to the browser. Example. In this  To customize the Cache-Control headers in Spring Boot, we can use properties under the spring.resources.cache.cachecontrol property namespace. For example, to change the max-age to one year, we can add the following to our application.properties: spring.resources.cache.cachecontrol.max-age=365d

There are a lot of ways in spring boot for caching http resource. Using spring boot 2.1.1 and additionally spring security 5.1.1.

1. For resources using resourcehandler in code (UNTESTED):

You can add customized extensions of resources this way.

registry.addResourceHandler

Is for adding the uri path where to get the resource

.addResourceLocations

Is for setting the location in the filesystem where the resources are located( given is a relative with classpath but absolute path with file::// is also possible.)

.setCacheControl

Is for setting the cache headers (self explanatory.)

Resourcechain and resolver are optional (in this case exactly as the default values.)

@Configuration
public class CustomWebMVCConfig implements WebMvcConfigurer {

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/**")
            .addResourceLocations("classpath:/static/")
            .setCacheControl(CacheControl.noStore()
                    .mustRevalidate())
            .setCacheControl(CacheControl.noCache())
            .resourceChain(true)
            .addResolver(new PathResourceResolver());
    }
}

2. For resources using application properties config file

Same as above, minus the specific patterns, but now as config. This configuration is applied to all resources in the static-locations listed.

spring.resources.cache.cachecontrol.no-store=true
spring.resources.cache.cachecontrol.must-revalidate=true
spring.resources.cache.cachecontrol.no-cache=true

3. At controller level

Response here is the HttpServletResponse injected in the controller method as parameter.

response.setHeader(HttpHeaders.CACHE_CONTROL,
            "no-cache, must-revalidate, no-store");
response.setHeader("Expires", "0");

Caching in Spring Boot with Spring Security, No problem, since no headers have been set yet. If no controller handles the request, then the Spring Boot auto-configured static resource  For security version < 4.0, <security:headers /> will turn on all default headers (including cache control). If you don't need any headers, just remove the <security:headers/>. If you need some headers, then explicitly list them. If your security version is 4.0, then try adding the attribute disabled-defaults="true" – ikumen Jul 14 '15 at 18:05

Maleenc's, answer is correct. However, there is one issue with this implementation.

The following code will provide the correct cache-control header on the first request, but not a future request that returns 304 (Not-Modified) will return the default cache-control header set by spring security. {code}

public void addResourceHandlers(ResourceHandlerRegistry registry) {         
    registry.addResourceHandler("/resources/**").setCacheControl(CacheControl.maxAge(10, TimeUnit.SECONDS));
}

I have raised up this issue to the spring team, see https://jira.spring.io/browse/SPR-15133. Here was there response: "Now you shouldn't disable security cache-control headers for your whole application indeed; the proper way to disable those for a specific path (resource handling, here) is explained in that issue comment, see the "Workaround" section."

CacheControl (Spring Framework 5.2.7.RELEASE API), As per the documentation, of ResourceHandlerRegistry . It is pretty easy. (I have no code related to it right now.) In the place where you configure your static  The Cache-Control HTTP header holds directives (instructions) for caching in both requests and responses. A given directive in a request does not mean the same directive should be in the response. A given directive in a request does not mean the same directive should be in the response.

HTTP cache with Spring examples, A builder for creating "Cache-Control" HTTP response headers. Adding Cache-​Control directives to HTTP responses can significantly improve the client All Methods Static Methods Instance Methods Concrete Methods Additional directives can be also used, in case resources shouldn't be cached ( cachePrivate() ) or  By default, Spring Boot serves all static content under the root part of the request, that is, /**. Even though it seems to be a good default configuration, we can change it via the spring.mvc.static-path-pattern configuration property.

Java Code Examples org.springframework.http.CacheControl, Learn how to use the HTTP cache in Spring Boot examples. considered for static resources like images, CSS stylesheets, or JavaScript files. The HTTP protocol defines several request and response headers which you can use In order to set an HTTP header in Spring's controller, instead of a regular  By using cache control headers effectively, we can instruct our browser to cache resources and avoid network hops. This decreases latency, and also the load on our server. By default, Spring Security sets specific cache control header values for us, without us having to configure anything.

Spring MVC 5, This page provides Java code examples for org.springframework.http. Set cache timeout for static resources to reduce resource burden on application registry. Project: onetwo File: BootMvcConfigurerAdapter.java Source Code and License, 6 votes Set the HTTP Cache-Control header according to the given settings. Make sure, you have spring-boot-starter-test dependency in your project to get access to TestRestTemplate class in runtime. If you are using the @SpringBootTest annotation, a TestRestTemplate is automatically available and can be @Autowired into your test.

Comments
  • stackoverflow.com/questions/24164014/…
  • Tried that also, didn't work. It adds X-headers and various stuff. But Cache-Control is always "no-store".
  • Setting CacheControl object with setCacheControl() makes the server send the correct headers, verified with curl -I
  • I couldn't find any code samples of the CacheControl object and setCacheControl, could you please share how you did this? Thanks!
  • Actually, you shouldn't use @EnableWebMvc. It caused me lot of time to figure out what happens, because some pages weren't served. See stackoverflow.com/a/27383522/4252764
  • If you're using Spring Boot, just use spring.resources.cache-period and make sure you configure Spring Security to ignore the static resources stackoverflow.com/questions/36835420/…
  • What is "current version" of spring boot?
  • No, it does not need to turn off spring security. See docs.spring.io/spring-security/site/docs/current/reference/…
  • Glad to know spring boot fix this issue years after
  • That works for static resources including index.html. How would I prevent the server from setting the header, when index.html is requested (but set it on requests for all other static resources)?
  • @dagerber do you still need this requirement? I figured it out.