Thomas Tardy opened SPR-13780 and commented
We are migrating a project from spring-web 4.1.8 to 4.2.3 and need to replace the deprecated code
WebContentInterceptor interceptor = new WebContentInterceptor();
interceptor.setCacheSeconds(0);
interceptor.setUseExpiresHeader(true);
interceptor.setUseCacheControlHeader(true);
interceptor.setUseCacheControlNoStore(true);
with the usage of the new CacheControl
and interceptor.setCacheControl(cacheControl)
.
But with the new API of CacheControl
, you cannot use noStore()
and noCache()
together as these methods return a new CacheControl
and aren't updating the existing ones.
As it is still required to set the Cache-Control
header to no-store, no-cache
to disable caching in different browsers, this should be possible.
Affects: 4.2.3
Comment From: spring-projects-issues
Brian Clozel commented
Hi Thomas Tardy
Out of curiosity, which use cases/browsers require both no-store
and no-cache
?
Comment From: spring-projects-issues
Thomas Tardy commented
Older browsers doesn't correctly support no-cache and no-store is required in addition. See http://stackoverflow.com/questions/866822/why-both-no-cache-and-no-store-should-be-used-in-http-response
Comment From: spring-projects-issues
Brian Clozel commented
I don't see any reference stating that "Cache-Control: no-store"
does not work with old browsers.
If anything, people are stating that some versions of IE are reusing previous responses when using the back button and "no-cache"
; even if it's not a proper behavior, it's does not strictly go against the spec, since "no-cache"
means caching the response but revalidating it with the server before reusing it and "no-store"
means no caching at all. In old versions of IE, the browser seemed to wrongly handle "no-cache"
as "no-store"
, when it should have sent conditional requests to revalidate the cached response.
When deciding on those static methods, I looked hard and found no evidence of "no-store"
not working on some browsers, but rather tons of advice stating that you should stack up directives like "Cache-Control: must-revalidate, no-cache, no-store, max-age=0"
+ "Expires: [date in past]"
+ "Pragma: no-cache"
.
Do you have a reference that states that some browser versions don't support "no-store"
?
If "no-store"
works out of the box for all browsers, do you see other reasons to combine both?
Thanks!
Comment From: spring-projects-issues
Thomas Tardy commented
... but rather tons of advice stating that you should stack up directives like
"Cache-Control: must-revalidate, no-cache, no-store, max-age=0"
+"Expires: [date in past]"
+"Pragma: no-cache"
How would you do that with the CacheControl
API?
Comment From: spring-projects-issues
Brian Clozel commented
You can't, that's the point. This API has been designed to help developers make the right decision. When I'm referring to "stacking up directives", I think this is a wrong thing to recommend since you're sending mixed signals to HTTP clients.
For me it doesn't make sense to use "no-store"
and "no-cache"
at the same time, since they mean different things and I've found no proof whatsoever stating that you should use both for a specific compatibility version. You can check the latest recommendations for HTTP caching by Google and Mark Nottingham.
Now I'm just trying to make the right choice: should we open this possibility because it's actually useful? Or should we leave it as it is because using both directives is some kind of anti-pattern. Do you know if a particular HTTP client/browser needs that combination? I'd be happy to test it.
Thanks,
Comment From: spring-projects-issues
Thomas Tardy commented
Do you know if a particular HTTP client/browser needs that combination?
No, I'm not. We should be fine with "no-store"
. You can close this ticket.
Thanks a lot for your quick responses and your support!
Comment From: spring-projects-issues
Brian Clozel commented
Thanks for this report Thomas Tardy, don't hesitate to reopen/create a new issue if you find something new. Feedback from Spring developers is always great.
Comment From: spring-projects-issues
Aurélien Leboulanger commented
If the no-cache + no-store mention isn't supported by the CacheControl API builder, please remove this comment from the javadoc of the noCache
method to avoid mistakes (and to avoid people to try to use both noCache and noStore at the same time):
/**
[...]
* <p>In order to disable caching and minimize requests/responses exchanges, the {@link #noStore()} directive
* should be used.
[...]
*/
Comment From: void-spark
I'm a bit confused here, it seems Spring Web is of the opinion that only one of no-store, no-cache, max-age should be set. At the same time Spring Security defaults to "no-cache, no-store, max-age=0, must-revalidate". I'm not sure what is the best practice anymore, leaving me with the somewhat fragile approach of carefully not setting anything in Spring Web for URLs I don't want to have cached, and setting values in Spring Web for URLs I do want cached. I'd prefer a single place to set clear rules for everything :)
It feels like maybe Web and Security should have a talk and agree on what the correct way is :)
Comment From: bclozel
I guess Spring Security is also using max-age=0
for security reasons and to ensure compatibility with (very) old clients.
The MDN mentions this:
max-age=0 is a workaround for no-cache, because many old (HTTP/1.0) cache implementations don't support no-cache. Recently browsers are still using max-age=0 in "reloading" — for backward compatibility — and alternatively using no-cache to cause a "force reloading".
I don't think we need to change anything here. From an application perspective, our recommendations are fine. Feel free to create a Spring Security issue if you feel that this legacy directive should be removed from Spring Security headers.