Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to enable HTTP response caching in Spring Boot

I have implemented a REST server using Spring Boot 1.0.2. I'm having trouble preventing Spring from setting HTTP headers that disable HTTP caching.

My controller is as following:

@Controller public class MyRestController {     @RequestMapping(value = "/someUrl", method = RequestMethod.GET)     public @ResponseBody ResponseEntity<String> myMethod(             HttpServletResponse httpResponse) throws SQLException {         return new ResponseEntity<String>("{}", HttpStatus.OK);     } } 

All HTTP responses contain the following headers:

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

I've tried the following to remove or change those headers:

  1. Call setCacheSeconds(-1) in the controller.
  2. Call httpResponse.setHeader("Cache-Control", "max-age=123") in the controller.
  3. Define @Bean that returns WebContentInterceptor for which I've called setCacheSeconds(-1).
  4. Set property spring.resources.cache-period to -1 or a positive value in application.properties.

None of the above have had any effect. How do I disable or change these headers for all or individual requests in Spring Boot?

like image 327
Samuli Pahaoja Avatar asked Jun 11 '14 13:06

Samuli Pahaoja


People also ask

How do I enable caching in spring boot?

To enable the Spring Boot caching feature, you need to add the @EnableCaching annotation to any of your classes annotated with @Configuration or to the boot application class annotated with @SpringBootApplication .

How do I enable cache control?

To use cache-control in HTML, you use the meta tag, e.g. The value in the content field is defined as one of the four values below. HTTP 1.1. Allowed values = PUBLIC | PRIVATE | NO-CACHE | NO-STORE.

What is Cache Control in Spring boot?

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.

What is HTTP response cache?

android.net.http.HttpResponseCache. Caches HTTP and HTTPS responses to the filesystem so they may be reused, saving time and bandwidth. This class supports HttpURLConnection and HttpsURLConnection ; there is no platform-provided cache for DefaultHttpClient or AndroidHttpClient .


2 Answers

Turns out the no-cache HTTP headers are set by Spring Security. This is discussed in http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#headers.

The following disables the HTTP response header Pragma: no-cache, but doesn't otherwise solve the problem:

import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;  @Configuration @EnableWebMvcSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter {     @Override     protected void configure(HttpSecurity http) throws Exception {         // Prevent the HTTP response header of "Pragma: no-cache".         http.headers().cacheControl().disable();     } } 

I ended up disabling Spring Security completely for public static resources as following (in the same class as above):

@Override public void configure(WebSecurity web) throws Exception {     web.ignoring().antMatchers("/static/public/**"); } 

This requires configuring two resource handlers to get cache control headers right:

@Configuration public class MvcConfigurer extends WebMvcConfigurerAdapter         implements EmbeddedServletContainerCustomizer {     @Override     public void addResourceHandlers(ResourceHandlerRegistry registry) {         // Resources without Spring Security. No cache control response headers.         registry.addResourceHandler("/static/public/**")             .addResourceLocations("classpath:/static/public/");          // Resources controlled by Spring Security, which         // adds "Cache-Control: must-revalidate".         registry.addResourceHandler("/static/**")             .addResourceLocations("classpath:/static/")             .setCachePeriod(3600*24);     } } 

See also Serving static web resources in Spring Boot & Spring Security application.

like image 144
Samuli Pahaoja Avatar answered Sep 29 '22 09:09

Samuli Pahaoja


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

1. For resources using resourcehandler in code:

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("/*.js", "/*.css", "/*.ttf", "/*.woff", "/*.woff2", "/*.eot",             "/*.svg")             .addResourceLocations("classpath:/static/")             .setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS)                     .cachePrivate()                     .mustRevalidate())             .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.cache-private=true spring.resources.cache.cachecontrol.must-revalidate=true spring.resources.cache.cachecontrol.max-age=31536000 spring.resources.static-locations=classpath:/static/ 

3. At controller level

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

no-cache, must-revalidate, private 

getHeaderValue will output the cache options as string. e.g.

response.setHeader(HttpHeaders.CACHE_CONTROL,             CacheControl.noCache()                     .cachePrivate()                     .mustRevalidate()                     .getHeaderValue()); 
like image 29
Merv Avatar answered Sep 29 '22 10:09

Merv