mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-05-03 04:19:47 +01:00
Don't implicitly check preconditions on PUT requests
Prior to this commit, the `HttpEntityMethodProcessor` would check HTTP
conditions on non-safe requests (i.e. not GET/HEAD). This would prevent
Controllers from returning `ResponseEntity` containing response headers
with updated values of `"Last-Modified"` or `ETag` once the resource has
been updated.
This commit avoids those checks for non GET/HEAD requests - this code
can still be leveraged from Controllers themselves using
`ServletWebRequest::checkNotModified` methods.
Issue: SPR-15780
(cherry picked from ed7684d2b2)
This commit is contained in:
+7
-2
@@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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.lang.reflect.Type;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.EnumSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.springframework.core.MethodParameter;
|
import org.springframework.core.MethodParameter;
|
||||||
import org.springframework.core.ResolvableType;
|
import org.springframework.core.ResolvableType;
|
||||||
@@ -59,6 +61,8 @@ import org.springframework.web.method.support.ModelAndViewContainer;
|
|||||||
*/
|
*/
|
||||||
public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodProcessor {
|
public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodProcessor {
|
||||||
|
|
||||||
|
private static final Set<HttpMethod> SAFE_METHODS = EnumSet.of(HttpMethod.GET, HttpMethod.HEAD);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Basic constructor with converters only. Suitable for resolving
|
* Basic constructor with converters only. Suitable for resolving
|
||||||
* {@code HttpEntity}. For handling {@code ResponseEntity} consider also
|
* {@code HttpEntity}. For handling {@code ResponseEntity} consider also
|
||||||
@@ -190,7 +194,8 @@ public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodPro
|
|||||||
int returnStatus = ((ResponseEntity<?>) responseEntity).getStatusCodeValue();
|
int returnStatus = ((ResponseEntity<?>) responseEntity).getStatusCodeValue();
|
||||||
outputMessage.getServletResponse().setStatus(returnStatus);
|
outputMessage.getServletResponse().setStatus(returnStatus);
|
||||||
if (returnStatus == 200) {
|
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.
|
// Ensure headers are flushed, no body should be written.
|
||||||
outputMessage.flush();
|
outputMessage.flush();
|
||||||
// Skip call to converters, as they may update the body.
|
// Skip call to converters, as they may update the body.
|
||||||
|
|||||||
+16
-1
@@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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);
|
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<String> returnValue = ResponseEntity.ok()
|
||||||
|
.lastModified(justModified).body("body");
|
||||||
|
initStringMessageConversion(MediaType.TEXT_PLAIN);
|
||||||
|
processor.handleReturnValue(returnValue, returnTypeResponseEntity, mavContainer, webRequest);
|
||||||
|
|
||||||
|
assertConditionalResponse(HttpStatus.OK, null, null, justModified);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void varyHeader() throws Exception {
|
public void varyHeader() throws Exception {
|
||||||
String[] entityValues = {"Accept-Language", "User-Agent"};
|
String[] entityValues = {"Accept-Language", "User-Agent"};
|
||||||
|
|||||||
Reference in New Issue
Block a user