Search code examples
springspring-bootcachinghttp-headerscontent-type

Cache static files by content type in Spring Boot


I'm trying to set up caching headers on specific static file type in Spring Boot. In directory src/main/resources/static there are few subdirectories with different file types:

src/main/resources/static/font   --> *.otf
src/main/resources/static/lib    --> *.js
src/main/resources/static/images --> *.png, *.jpg

Is there a way to put cache headers by file type inside Spring configuration?

*.otf 365 days
*.png 30 days
*.jpg 7 days

Spring version is 5.2.3 and Spring Boot 2.2.4 - is there a chance that Spring Boot deals with it and makes it not work?

Tried with

@Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
    final CacheControl oneYearPublic =
        CacheControl.maxAge(365, TimeUnit.DAYS).cachePublic();
    // it does not "work" with "/static/fonts/"
    registry
        .addResourceHandler("/fonts/{filename:\\w+\\.otf}")
        .setCacheControl(oneYearPublic);
}

but I get weird results. When checking with Network tab of DevTools I get these headers:

    Cache-Control: no-cache, no-store, max-age=0, must-revalidate
    Pragma: no-cache
    Expires: 0

But when I go to the URL directly, I get 404

http://localhost/fonts/1952RHEINMETALL.otf

Without any configuration I get "no-store" Cache-Control header.


Solution

  • I've managed to have a working solution for this problem. Check the GitHub repo https://github.com/alexsomai/cache-static-assets.

    This is an example of config that should work:

    @Configuration
    public class WebConfig implements WebMvcConfigurer {
    
        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            Objects.requireNonNull(registry);
    
            // could use either '/**/images/{filename:\w+\.png}' or '/**/images/*.png'
            registry.addResourceHandler("/**/images/{filename:\\w+\\.png}")
                    .addResourceLocations("classpath:/static/")
                    .setCacheControl(CacheControl.maxAge(1, TimeUnit.DAYS));
    
            registry.addResourceHandler("/**/images/*.jpg")
                    .addResourceLocations("classpath:/static/")
                    .setCacheControl(CacheControl.maxAge(2, TimeUnit.DAYS));
    
            registry.addResourceHandler("/**/lib/*.js")
                    .addResourceLocations("classpath:/static/")
                    .setCacheControl(CacheControl.maxAge(3, TimeUnit.DAYS));
        }
    }
    

    You could easily adjust it for your needs, based on file type and cache duration.

    As key takeaways, make sure to add the addResourceLocations function (without this one, you get 404). Plus, if you are using Spring Boot, you don't need the @EnableWebMvc, as it was initially posted in this example https://stackoverflow.com/a/33216168/6908551.