Skip to content

Commit 0ef90df

Browse files
committed
Relax SPR-13867 changes for ResourceHttpRequestHandler
Prior to this change, SPR-13867 made sure that any class extending WebContentGenerator would not overwrite existing HTTP "Cache-Control" response headers - set by a filter, a Controller handler, etc. This caused issues with resource handling, since specifying a cache configuration there would not overwrite default headers set by filters, for example by Spring Security. This commit restricts the previous changes to the RequestMappingHandlerAdapter, in order to avoid overwriting header set by a filter or a Controller handler in those cases. Issue: SPR-14005 Cherry-picked from 50bcd67
1 parent 8a44560 commit 0ef90df

File tree

3 files changed

+48
-39
lines changed

3 files changed

+48
-39
lines changed

spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapter.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -743,11 +743,13 @@ protected ModelAndView handleInternal(HttpServletRequest request,
743743
mav = invokeHandlerMethod(request, response, handlerMethod);
744744
}
745745

746-
if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
747-
applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
748-
}
749-
else {
750-
prepareResponse(response);
746+
if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
747+
if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
748+
applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
749+
}
750+
else {
751+
prepareResponse(response);
752+
}
751753
}
752754

753755
return mav;
@@ -887,7 +889,7 @@ private WebDataBinderFactory getDataBinderFactory(HandlerMethod handlerMethod) t
887889
}
888890
List<InvocableHandlerMethod> initBinderMethods = new ArrayList<InvocableHandlerMethod>();
889891
// Global methods first
890-
for (Entry<ControllerAdviceBean, Set<Method>> entry : this.initBinderAdviceCache .entrySet()) {
892+
for (Entry<ControllerAdviceBean, Set<Method>> entry : this.initBinderAdviceCache.entrySet()) {
891893
if (entry.getKey().isApplicableToBeanType(handlerType)) {
892894
Object bean = entry.getKey().resolveBean();
893895
for (Method method : entry.getValue()) {

spring-webmvc/src/main/java/org/springframework/web/servlet/support/WebContentGenerator.java

Lines changed: 29 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public abstract class WebContentGenerator extends WebApplicationObjectSupport {
7171

7272
private static final String HEADER_EXPIRES = "Expires";
7373

74-
private static final String HEADER_CACHE_CONTROL = "Cache-Control";
74+
protected static final String HEADER_CACHE_CONTROL = "Cache-Control";
7575

7676

7777
/** Set of supported HTTP methods */
@@ -330,16 +330,14 @@ protected final void prepareResponse(HttpServletResponse response) {
330330
* @since 4.2
331331
*/
332332
protected final void applyCacheControl(HttpServletResponse response, CacheControl cacheControl) {
333-
if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
334-
String ccValue = cacheControl.getHeaderValue();
335-
if (ccValue != null) {
336-
// Set computed HTTP 1.1 Cache-Control header
337-
response.setHeader(HEADER_CACHE_CONTROL, ccValue);
338-
339-
if (response.containsHeader(HEADER_PRAGMA)) {
340-
// Reset HTTP 1.0 Pragma header if present
341-
response.setHeader(HEADER_PRAGMA, "");
342-
}
333+
String ccValue = cacheControl.getHeaderValue();
334+
if (ccValue != null) {
335+
// Set computed HTTP 1.1 Cache-Control header
336+
response.setHeader(HEADER_CACHE_CONTROL, ccValue);
337+
338+
if (response.containsHeader(HEADER_PRAGMA)) {
339+
// Reset HTTP 1.0 Pragma header if present
340+
response.setHeader(HEADER_PRAGMA, "");
343341
}
344342
}
345343
}
@@ -355,32 +353,30 @@ protected final void applyCacheControl(HttpServletResponse response, CacheContro
355353
*/
356354
@SuppressWarnings("deprecation")
357355
protected final void applyCacheSeconds(HttpServletResponse response, int cacheSeconds) {
358-
if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
359-
if (this.useExpiresHeader || !this.useCacheControlHeader) {
360-
// Deprecated HTTP 1.0 cache behavior, as in previous Spring versions
361-
if (cacheSeconds > 0) {
362-
cacheForSeconds(response, cacheSeconds);
363-
}
364-
else if (cacheSeconds == 0) {
365-
preventCaching(response);
356+
if (this.useExpiresHeader || !this.useCacheControlHeader) {
357+
// Deprecated HTTP 1.0 cache behavior, as in previous Spring versions
358+
if (cacheSeconds > 0) {
359+
cacheForSeconds(response, cacheSeconds);
360+
}
361+
else if (cacheSeconds == 0) {
362+
preventCaching(response);
363+
}
364+
}
365+
else {
366+
CacheControl cControl;
367+
if (cacheSeconds > 0) {
368+
cControl = CacheControl.maxAge(cacheSeconds, TimeUnit.SECONDS);
369+
if (this.alwaysMustRevalidate) {
370+
cControl = cControl.mustRevalidate();
366371
}
367372
}
373+
else if (cacheSeconds == 0) {
374+
cControl = (this.useCacheControlNoStore ? CacheControl.noStore() : CacheControl.noCache());
375+
}
368376
else {
369-
CacheControl cControl;
370-
if (cacheSeconds > 0) {
371-
cControl = CacheControl.maxAge(cacheSeconds, TimeUnit.SECONDS);
372-
if (this.alwaysMustRevalidate) {
373-
cControl = cControl.mustRevalidate();
374-
}
375-
}
376-
else if (cacheSeconds == 0) {
377-
cControl = (this.useCacheControlNoStore ? CacheControl.noStore() : CacheControl.noCache());
378-
}
379-
else {
380-
cControl = CacheControl.empty();
381-
}
382-
applyCacheControl(response, cControl);
377+
cControl = CacheControl.empty();
383378
}
379+
applyCacheControl(response, cControl);
384380
}
385381
}
386382

spring-webmvc/src/test/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandlerTests.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,17 @@ public void writeContentInputStreamThrowingNullPointerException() throws Excepti
503503
assertEquals(0, this.response.getContentLength());
504504
}
505505

506+
// SPR-14005
507+
@Test
508+
public void doOverwriteExistingCacheControlHeaders() throws Exception {
509+
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "foo.css");
510+
this.response.setHeader("Cache-Control", "no-store");
511+
512+
this.handler.handleRequest(this.request, this.response);
513+
514+
assertEquals("max-age=3600", this.response.getHeader("Cache-Control"));
515+
}
516+
506517

507518
private long dateHeaderAsLong(String responseHeaderName) throws Exception {
508519
return dateFormat.parse(this.response.getHeader(responseHeaderName)).getTime();

0 commit comments

Comments
 (0)