Set static asset cache management headers in Dropwizard

What's the best way to set static asset cache management headers in Dropwizard?

In some Googling, the AssetsBundle constructor appeared:

AssetsBundle (String resourcePath, com.google.common.cache.CacheBuilderSpec cacheBuilderSpec, String uriPath)

However, upon further investigation, it appears that the com.yammer.dropwizard.bundles package has not been part of Dropwizard since version 5.1.

Maybe I'm missing something obvious, but is there a preferred way to handle this?

+7
cache-control dropwizard
source share
3 answers

Based on Tim Barclay’s answer, I created a filter that sets Cache-Control and Expires one year in the future, if the requested resource is a file with the extension js, css, png, jpg, gif or svg, otherwise the cache is disabled.

Hope this can be helpful for someone!

 protected void setCacheHeaders(Environment environment, String urlPattern, int seconds) { FilterRegistration.Dynamic filter = environment.servlets().addFilter( "cacheControlFilter", new Filter() { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse; String[] cacheFileTypes = {"js","css","png","jpg","gif","svg"}; String filetypeRequested = FilenameUtils.getExtension(httpServletRequest.getRequestURL().toString()); if (httpServletRequest.getMethod() == "GET" && seconds > 0 && Arrays.asList(cacheFileTypes).contains(filetypeRequested)) { httpServletResponse.setHeader("Cache-Control", "public, max-age=" + seconds); Calendar c = Calendar.getInstance(); c.setTime(new Date()); c.add(Calendar.SECOND, seconds); SimpleDateFormat format = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss zzz", Locale.US); format.setTimeZone(TimeZone.getTimeZone("GMT")); httpServletResponse.setHeader("Expires", format.format(c.getTime())); } else { httpServletResponse.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); httpServletResponse.setHeader("Expires", "0"); httpServletResponse.setHeader("Pragma", "no-cache"); } filterChain.doFilter(servletRequest, servletResponse); } @Override public void destroy() { } } ); filter.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), true, urlPattern); } 

PS: I could not get an acceptable answer method to install Expires -header:

 resp.setHeader("Expires", new Date().getTime()+500000 + ""); 

Mine is badly bloated in comparison, but it works:

 Calendar c = Calendar.getInstance(); c.setTime(new Date()); c.add(Calendar.SECOND, seconds); SimpleDateFormat format = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss zzz", Locale.US); format.setTimeZone(TimeZone.getTimeZone("GMT")); httpServletResponse.setHeader("Expires", format.format(c.getTime())); 
+1
source share

In case someone is interested (which, judging by the number of views this question had, they probably don’t), that's how I decided it.

I created the CacheControlFilter class in the same package as my service class:

 public class CacheControlFilter implements Filter{ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletResponse resp = (HttpServletResponse) response; // Add whatever headers you want here resp.setHeader("Cache-Control", "public, max-age=500000"); resp.setHeader("Expires", new Date().getTime()+500000 + ""); chain.doFilter(request, response); } public void destroy() {} public void init(FilterConfig arg0) throws ServletException {} } 

Then in the service class just add the line:

 env.addFilter(new CacheControlFilter(), "/*"); 

Of course, you can be more precise and add another filter, say image files and css files, but this adds headers for all requests.

+8
source share

If you just want to clear the cache for each request, below is my solution that uses the CacheBustingFilter provided by DropWizard.

  • Define a custom configuration, in my case its WebConfiguration. Use this configuration when configuring the DropWizard application.

     public class WebConfiguration extends Configuration { @JsonProperty private String enableCacheControl; public String getEnableCacheControl() { return enableCacheControl; } public void setEnableCacheControl(String enableCacheControl) { this.enableCacheControl = enableCacheControl; } 

    }

  • Get the configuration defined in # 1 and register a CacheBustingFilter based on its value.

Add this to your execution method -

  // get the cache control settings from the YAML - configuration String enableCacheControl = configuration.getEnableCacheControl(); boolean enableCacheBustingFilter = Boolean.parseBoolean(enableCacheControl); if(enableCacheBustingFilter){ // caching was enabled in YAML - was set to true - enabling the cacheBustingFilter // this will ALWAYS return "must-revalidate,no-cache,no-store" in the Cache-Control response header environment.servlets().addFilter("CacheBustingFilter", new CacheBustingFilter()) .addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, "/*"); } 
+2
source share

All Articles