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

MatteKarla picture MatteKarla · Oct 19, 2015 · Viewed 43.2k times · Source

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

Answer

Alexandr Latushkin picture Alexandr Latushkin · Feb 26, 2016

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