From 1a97a26eb7ed21f5c12f0d89aa67ad518d213e89 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Thu, 18 Apr 2019 11:45:05 -0400 Subject: [PATCH] Disable response caching when controller resolves ETag See gh-22797 --- .../annotation/HttpEntityMethodProcessor.java | 4 +++- .../ServletInvocableHandlerMethod.java | 17 ++++++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/HttpEntityMethodProcessor.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/HttpEntityMethodProcessor.java index 6196dd4271..35747fcfbf 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/HttpEntityMethodProcessor.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/HttpEntityMethodProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -48,6 +48,7 @@ import org.springframework.web.accept.ContentNegotiationManager; import org.springframework.web.bind.support.WebDataBinderFactory; import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.context.request.ServletWebRequest; +import org.springframework.web.filter.ShallowEtagHeaderFilter; import org.springframework.web.method.support.ModelAndViewContainer; import org.springframework.web.servlet.mvc.support.RedirectAttributes; import org.springframework.web.servlet.support.RequestContextUtils; @@ -207,6 +208,7 @@ public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodPro && isResourceNotModified(inputMessage, outputMessage)) { // Ensure headers are flushed, no body should be written. outputMessage.flush(); + ShallowEtagHeaderFilter.disableContentCaching(inputMessage.getServletRequest()); // Skip call to converters, as they may update the body. return; } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletInvocableHandlerMethod.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletInvocableHandlerMethod.java index 6c4679a5a2..63ca9df833 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletInvocableHandlerMethod.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletInvocableHandlerMethod.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +21,7 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.util.concurrent.Callable; +import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.core.MethodParameter; @@ -33,6 +34,7 @@ import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.context.request.ServletWebRequest; +import org.springframework.web.filter.ShallowEtagHeaderFilter; import org.springframework.web.method.HandlerMethod; import org.springframework.web.method.support.HandlerMethodReturnValueHandler; import org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite; @@ -104,6 +106,7 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod { if (returnValue == null) { if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) { + disableContentCachingIfNecessary(webRequest); mavContainer.setRequestHandled(true); return; } @@ -160,6 +163,18 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod { return webRequest.isNotModified(); } + private void disableContentCachingIfNecessary(ServletWebRequest webRequest) { + if (!isRequestNotModified(webRequest)) { + HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class); + Assert.notNull(response, "Expected HttpServletResponse"); + if (StringUtils.hasText(response.getHeader("ETag"))) { + HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class); + Assert.notNull(request, "Expected HttpServletRequest"); + ShallowEtagHeaderFilter.disableContentCaching(request); + } + } + } + private String formatErrorForReturnValue(@Nullable Object returnValue) { return "Error handling return value=[" + returnValue + "]" + (returnValue != null ? ", type=" + returnValue.getClass().getName() : "") +