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:
setCacheSeconds(-1)
in the controller.httpResponse.setHeader("Cache-Control", "max-age=123")
in the controller.@Bean
that returns WebContentInterceptor
for which I've called setCacheSeconds(-1)
.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?
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 .
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.
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.
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 .
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.
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());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With