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 a2d858f31f7..8b84b59bdcd 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-2017 the original author or authors. + * Copyright 2002-2018 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,8 +21,10 @@ import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collections; +import java.util.EnumSet; import java.util.List; import java.util.Map; +import java.util.Set; import org.springframework.core.MethodParameter; import org.springframework.core.ResolvableType; @@ -59,6 +61,8 @@ import org.springframework.web.method.support.ModelAndViewContainer; */ public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodProcessor { + private static final Set SAFE_METHODS = EnumSet.of(HttpMethod.GET, HttpMethod.HEAD); + /** * Basic constructor with converters only. Suitable for resolving * {@code HttpEntity}. For handling {@code ResponseEntity} consider also @@ -190,7 +194,8 @@ public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodPro int returnStatus = ((ResponseEntity) responseEntity).getStatusCodeValue(); outputMessage.getServletResponse().setStatus(returnStatus); if (returnStatus == 200) { - if (isResourceNotModified(inputMessage, outputMessage)) { + if (SAFE_METHODS.contains(inputMessage.getMethod()) + && isResourceNotModified(inputMessage, outputMessage)) { // Ensure headers are flushed, no body should be written. outputMessage.flush(); // Skip call to converters, as they may update the body. 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 a83770776c9..dc7f30863d4 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2018 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. @@ -511,6 +511,21 @@ public class HttpEntityMethodProcessorMockTests { assertConditionalResponse(HttpStatus.OK, "body", etagValue, -1); } + @Test + public void shouldNotFailPreconditionForPutRequests() throws Exception { + servletRequest.setMethod("PUT"); + long dateTime = new Date().getTime(); + servletRequest.addHeader(HttpHeaders.IF_UNMODIFIED_SINCE, dateFormat.format(dateTime)); + + long justModified = dateTime + 1; + ResponseEntity returnValue = ResponseEntity.ok() + .lastModified(justModified).body("body"); + initStringMessageConversion(MediaType.TEXT_PLAIN); + processor.handleReturnValue(returnValue, returnTypeResponseEntity, mavContainer, webRequest); + + assertConditionalResponse(HttpStatus.OK, null, null, justModified); + } + @Test public void varyHeader() throws Exception { String[] entityValues = {"Accept-Language", "User-Agent"};