From 583a48ab7565264ec0dc17089f3becd24bb1991a Mon Sep 17 00:00:00 2001 From: Brian Clozel Date: Thu, 24 Sep 2015 17:49:20 +0200 Subject: [PATCH] Do not process conditional requests for non-GET Prior to this commit, HttpEntityMethodProcessor would process conditional requests even if those aren't GET requests. This is an issue for POST requests with "If-None-Match: *" headers and many other use cases, which should not receive an HTTP 304 Not Modified status in response. This commit only triggers ETag/Last-Modified conditional requests bits for GET requests. Issue: SPR-13496 --- .../annotation/HttpEntityMethodProcessor.java | 3 +- .../HttpEntityMethodProcessorMockTests.java | 30 ++++++++++++++++++- 2 files changed, 31 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 22ebdbc3a23..e2495d4bde9 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 @@ -172,7 +172,8 @@ public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodPro Object body = responseEntity.getBody(); if (responseEntity instanceof ResponseEntity) { outputMessage.setStatusCode(((ResponseEntity) responseEntity).getStatusCode()); - if (isResourceNotModified(inputMessage, outputMessage)) { + if (inputMessage.getServletRequest().getMethod() == "GET" + && isResourceNotModified(inputMessage, outputMessage)) { outputMessage.setStatusCode(HttpStatus.NOT_MODIFIED); // Ensure headers are flushed, no body should be written. outputMessage.flush(); diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/HttpEntityMethodProcessorMockTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/HttpEntityMethodProcessorMockTests.java index f27bb0d5b3d..3669429edca 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/HttpEntityMethodProcessorMockTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/HttpEntityMethodProcessorMockTests.java @@ -112,7 +112,7 @@ public class HttpEntityMethodProcessorMockTests { returnTypeInt = new MethodParameter(getClass().getMethod("handle3"), -1); mavContainer = new ModelAndViewContainer(); - servletRequest = new MockHttpServletRequest("POST", "/foo"); + servletRequest = new MockHttpServletRequest("GET", "/foo"); servletResponse = new MockHttpServletResponse(); webRequest = new ServletWebRequest(servletRequest, servletResponse); } @@ -182,6 +182,7 @@ public class HttpEntityMethodProcessorMockTests { @Test(expected = HttpMediaTypeNotSupportedException.class) public void resolveArgumentNotReadable() throws Exception { MediaType contentType = MediaType.TEXT_PLAIN; + servletRequest.setMethod("POST"); servletRequest.addHeader("Content-Type", contentType.toString()); given(messageConverter.getSupportedMediaTypes()).willReturn(Collections.singletonList(contentType)); @@ -194,6 +195,7 @@ public class HttpEntityMethodProcessorMockTests { @Test(expected = HttpMediaTypeNotSupportedException.class) public void resolveArgumentNoContentType() throws Exception { + servletRequest.setMethod("POST"); servletRequest.setContent("some content".getBytes(Charset.forName("UTF-8"))); processor.resolveArgument(paramHttpEntity, mavContainer, webRequest, null); fail("Expected exception"); @@ -455,6 +457,32 @@ public class HttpEntityMethodProcessorMockTests { assertEquals(0, servletResponse.getContentAsByteArray().length); } + // SPR-13496 + @Test + public void handleReturnTypePostRequestWithIfNotModified() throws Exception { + String wildcardValue = "*"; + String etagValue = "\"some-etag\""; + servletRequest.setMethod("POST"); + servletRequest.addHeader(HttpHeaders.IF_NONE_MATCH, wildcardValue); + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.set(HttpHeaders.ETAG, etagValue); + ResponseEntity returnValue = new ResponseEntity("body", responseHeaders, HttpStatus.OK); + + given(messageConverter.canWrite(String.class, null)).willReturn(true); + given(messageConverter.getSupportedMediaTypes()).willReturn(Collections.singletonList(MediaType.TEXT_PLAIN)); + given(messageConverter.canWrite(String.class, MediaType.TEXT_PLAIN)).willReturn(true); + + + processor.handleReturnValue(returnValue, returnTypeResponseEntity, mavContainer, webRequest); + + assertTrue(mavContainer.isRequestHandled()); + assertEquals(HttpStatus.OK.value(), servletResponse.getStatus()); + assertEquals(1, servletResponse.getHeaderValues(HttpHeaders.ETAG).size()); + assertEquals(etagValue, servletResponse.getHeader(HttpHeaders.ETAG)); + ArgumentCaptor outputMessage = ArgumentCaptor.forClass(HttpOutputMessage.class); + verify(messageConverter).write(eq("body"), eq(MediaType.TEXT_PLAIN), outputMessage.capture()); + } + @SuppressWarnings("unused") public ResponseEntity handle1(HttpEntity httpEntity, ResponseEntity entity, int i, RequestEntity requestEntity) {