提交 88936632 编写于 作者: B Brian Clozel

Do not process undefined conditional HTTP requests

Prior to this change, the HttpEntityMethodProcessor would try to process
conditional requests that are undefined by the spec, such as:

* an HTTP GET request with "If-None-Match:*"
* a request with both "If-None-Match" and "If-Match"
* a request with both "If-None-Match" and "If-Unmodified-Since"

This commit skips the processing of those requests as conditional
requests and continues with normal request handling.

Issue: SPR-13626
上级 9f4c9d7f
......@@ -172,7 +172,7 @@ public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodPro
Object body = responseEntity.getBody();
if (responseEntity instanceof ResponseEntity) {
outputMessage.setStatusCode(((ResponseEntity<?>) responseEntity).getStatusCode());
if (inputMessage.getMethod() == HttpMethod.GET &&
if (inputMessage.getMethod().equals(HttpMethod.GET) &&
isResourceNotModified(inputMessage, outputMessage)) {
outputMessage.setStatusCode(HttpStatus.NOT_MODIFIED);
// Ensure headers are flushed, no body should be written.
......@@ -196,7 +196,11 @@ public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodPro
long lastModified = outputMessage.getHeaders().getLastModified();
boolean notModified = false;
if (lastModified != -1 && StringUtils.hasLength(eTag)) {
if (!ifNoneMatch.isEmpty() && (inputMessage.getHeaders().containsKey(HttpHeaders.IF_UNMODIFIED_SINCE)
|| inputMessage.getHeaders().containsKey(HttpHeaders.IF_MATCH))) {
// invalid conditional request, do not process
}
else if (lastModified != -1 && StringUtils.hasLength(eTag)) {
notModified = isETagNotModified(ifNoneMatch, eTag) && isTimeStampNotModified(ifModifiedSince, lastModified);
}
else if (lastModified != -1) {
......@@ -213,8 +217,7 @@ public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodPro
for (String clientETag : ifNoneMatch) {
// Compare weak/strong ETags as per https://tools.ietf.org/html/rfc7232#section-2.3
if (StringUtils.hasLength(clientETag) &&
(clientETag.replaceFirst("^W/", "").equals(etag.replaceFirst("^W/", "")) ||
clientETag.equals("*"))) {
(clientETag.replaceFirst("^W/", "").equals(etag.replaceFirst("^W/", "")))) {
return true;
}
}
......
......@@ -349,11 +349,9 @@ public class HttpEntityMethodProcessorMockTests {
processor.handleReturnValue(returnValue, returnTypeResponseEntity, mavContainer, webRequest);
assertTrue(mavContainer.isRequestHandled());
assertEquals(HttpStatus.NOT_MODIFIED.value(), servletResponse.getStatus());
assertResponseNotModified();
assertEquals(1, servletResponse.getHeaderValues(HttpHeaders.LAST_MODIFIED).size());
assertEquals(dateFormat.format(oneMinuteAgo), servletResponse.getHeader(HttpHeaders.LAST_MODIFIED));
assertEquals(0, servletResponse.getContentAsByteArray().length);
}
@Test
......@@ -370,11 +368,9 @@ public class HttpEntityMethodProcessorMockTests {
processor.handleReturnValue(returnValue, returnTypeResponseEntity, mavContainer, webRequest);
assertTrue(mavContainer.isRequestHandled());
assertEquals(HttpStatus.NOT_MODIFIED.value(), servletResponse.getStatus());
assertResponseNotModified();
assertEquals(1, servletResponse.getHeaderValues(HttpHeaders.ETAG).size());
assertEquals(etagValue, servletResponse.getHeader(HttpHeaders.ETAG));
assertEquals(0, servletResponse.getContentAsByteArray().length);
}
@Test
......@@ -395,13 +391,11 @@ public class HttpEntityMethodProcessorMockTests {
processor.handleReturnValue(returnValue, returnTypeResponseEntity, mavContainer, webRequest);
assertTrue(mavContainer.isRequestHandled());
assertEquals(HttpStatus.NOT_MODIFIED.value(), servletResponse.getStatus());
assertResponseNotModified();
assertEquals(1, servletResponse.getHeaderValues(HttpHeaders.LAST_MODIFIED).size());
assertEquals(dateFormat.format(oneMinuteAgo), servletResponse.getHeader(HttpHeaders.LAST_MODIFIED));
assertEquals(1, servletResponse.getHeaderValues(HttpHeaders.ETAG).size());
assertEquals(etagValue, servletResponse.getHeader(HttpHeaders.ETAG));
assertEquals(0, servletResponse.getContentAsByteArray().length);
}
@Test
......@@ -420,12 +414,16 @@ public class HttpEntityMethodProcessorMockTests {
processor.handleReturnValue(returnValue, returnTypeResponseEntity, mavContainer, webRequest);
assertTrue(mavContainer.isRequestHandled());
assertEquals(HttpStatus.NOT_MODIFIED.value(), servletResponse.getStatus());
assertResponseNotModified();
assertEquals(1, servletResponse.getHeaderValues(HttpHeaders.LAST_MODIFIED).size());
assertEquals(dateFormat.format(oneMinuteAgo), servletResponse.getHeader(HttpHeaders.LAST_MODIFIED));
assertEquals(1, servletResponse.getHeaderValues(HttpHeaders.ETAG).size());
assertEquals(etagValue, servletResponse.getHeader(HttpHeaders.ETAG));
}
private void assertResponseNotModified() {
assertTrue(mavContainer.isRequestHandled());
assertEquals(HttpStatus.NOT_MODIFIED.value(), servletResponse.getStatus());
assertEquals(0, servletResponse.getContentAsByteArray().length);
}
......@@ -472,15 +470,81 @@ public class HttpEntityMethodProcessorMockTests {
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);
assertResponseOkWithBody("body");
assertEquals(1, servletResponse.getHeaderValues(HttpHeaders.ETAG).size());
assertEquals(etagValue, servletResponse.getHeader(HttpHeaders.ETAG));
}
// SPR-13626
@Test
public void handleReturnTypeGetIfNoneMatchWildcard() throws Exception {
String wildcardValue = "*";
String etagValue = "\"some-etag\"";
servletRequest.addHeader(HttpHeaders.IF_NONE_MATCH, wildcardValue);
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.set(HttpHeaders.ETAG, etagValue);
ResponseEntity<String> returnValue = new ResponseEntity<String>("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());
assertResponseOkWithBody("body");
assertEquals(1, servletResponse.getHeaderValues(HttpHeaders.ETAG).size());
assertEquals(etagValue, servletResponse.getHeader(HttpHeaders.ETAG));
}
// SPR-13626
@Test
public void handleReturnTypeIfNoneMatchIfMatch() throws Exception {
String etagValue = "\"some-etag\"";
servletRequest.addHeader(HttpHeaders.IF_NONE_MATCH, etagValue);
servletRequest.addHeader(HttpHeaders.IF_MATCH, "ifmatch");
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.set(HttpHeaders.ETAG, etagValue);
ResponseEntity<String> returnValue = new ResponseEntity<String>("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);
assertResponseOkWithBody("body");
assertEquals(1, servletResponse.getHeaderValues(HttpHeaders.ETAG).size());
assertEquals(etagValue, servletResponse.getHeader(HttpHeaders.ETAG));
}
// SPR-13626
@Test
public void handleReturnTypeIfNoneMatchIfUnmodifiedSince() throws Exception {
String etagValue = "\"some-etag\"";
servletRequest.addHeader(HttpHeaders.IF_NONE_MATCH, etagValue);
servletRequest.addHeader(HttpHeaders.IF_UNMODIFIED_SINCE, dateFormat.format(new Date().getTime()));
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.set(HttpHeaders.ETAG, etagValue);
ResponseEntity<String> returnValue = new ResponseEntity<String>("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);
assertResponseOkWithBody("body");
assertEquals(1, servletResponse.getHeaderValues(HttpHeaders.ETAG).size());
assertEquals(etagValue, servletResponse.getHeader(HttpHeaders.ETAG));
}
private void assertResponseOkWithBody(String body) throws Exception {
assertTrue(mavContainer.isRequestHandled());
assertEquals(HttpStatus.OK.value(), servletResponse.getStatus());
ArgumentCaptor<HttpOutputMessage> outputMessage = ArgumentCaptor.forClass(HttpOutputMessage.class);
verify(messageConverter).write(eq("body"), eq(MediaType.TEXT_PLAIN), outputMessage.capture());
verify(messageConverter).write(eq("body"), eq(MediaType.TEXT_PLAIN), outputMessage.capture());
}
@SuppressWarnings("unused")
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册