Browse Source

Fix server errors for invalid If-None-Match request headers

HttpEntityMethodProcessor should not throw IllegalArgumentExceptions for
invalid If-None-Match headers.

For those cases, this commit makes sure that both
`HttpEntityMethodProcessor` and `ServletWebRequest` have a consistent
behavior and stop processing the request as conditional and leave the
handler handle it.

Issue: SPR-14559
pull/1144/merge
Brian Clozel 10 years ago
parent
commit
d8fc13f6fc
  1. 9
      spring-web/src/test/java/org/springframework/web/context/request/ServletWebRequestHttpMethodsTests.java
  2. 36
      spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/HttpEntityMethodProcessor.java
  3. 15
      spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/HttpEntityMethodProcessorMockTests.java

9
spring-web/src/test/java/org/springframework/web/context/request/ServletWebRequestHttpMethodsTests.java

@ -99,6 +99,15 @@ public class ServletWebRequestHttpMethodsTests { @@ -99,6 +99,15 @@ public class ServletWebRequestHttpMethodsTests {
assertEquals(dateFormat.format(epochTime), servletResponse.getHeader("Last-Modified"));
}
@Test // SPR-14559
public void checkNotModifiedInvalidIfNoneMatchHeader() {
String eTag = "\"etagvalue\"";
servletRequest.addHeader("If-None-Match", "missingquotes");
assertFalse(request.checkNotModified(eTag));
assertEquals(200, servletResponse.getStatus());
assertEquals(eTag, servletResponse.getHeader("ETag"));
}
@Test
public void checkNotModifiedHeaderAlreadySet() {
long epochTime = currentDate.getTime();

36
spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/HttpEntityMethodProcessor.java

@ -223,24 +223,28 @@ public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodPro @@ -223,24 +223,28 @@ public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodPro
}
private boolean isResourceNotModified(ServletServerHttpRequest inputMessage, ServletServerHttpResponse outputMessage) {
List<String> ifNoneMatch = inputMessage.getHeaders().getIfNoneMatch();
long ifModifiedSince = inputMessage.getHeaders().getIfModifiedSince();
String eTag = addEtagPadding(outputMessage.getHeaders().getETag());
long lastModified = outputMessage.getHeaders().getLastModified();
boolean notModified = false;
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) {
notModified = isTimeStampNotModified(ifModifiedSince, lastModified);
try {
long ifModifiedSince = inputMessage.getHeaders().getIfModifiedSince();
String eTag = addEtagPadding(outputMessage.getHeaders().getETag());
long lastModified = outputMessage.getHeaders().getLastModified();
List<String> ifNoneMatch = inputMessage.getHeaders().getIfNoneMatch();
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) {
notModified = isTimeStampNotModified(ifModifiedSince, lastModified);
}
else if (StringUtils.hasLength(eTag)) {
notModified = isETagNotModified(ifNoneMatch, eTag);
}
}
else if (StringUtils.hasLength(eTag)) {
notModified = isETagNotModified(ifNoneMatch, eTag);
catch (IllegalArgumentException exc) {
// invalid conditional request, do not process
}
return notModified;
}

15
spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/HttpEntityMethodProcessorMockTests.java

@ -379,6 +379,21 @@ public class HttpEntityMethodProcessorMockTests { @@ -379,6 +379,21 @@ public class HttpEntityMethodProcessorMockTests {
assertEquals(etagValue, servletResponse.getHeader(HttpHeaders.ETAG));
}
@Test // SPR-14559
public void handleReturnValueEtagInvalidIfNoneMatch() throws Exception {
String etagValue = "\"deadb33f8badf00d\"";
servletRequest.addHeader(HttpHeaders.IF_NONE_MATCH, "unquoted");
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.set(HttpHeaders.ETAG, etagValue);
ResponseEntity<String> returnValue = new ResponseEntity<>("body", responseHeaders, HttpStatus.OK);
initStringMessageConversion(MediaType.TEXT_PLAIN);
processor.handleReturnValue(returnValue, returnTypeResponseEntity, mavContainer, webRequest);
assertTrue(mavContainer.isRequestHandled());
assertEquals(HttpStatus.OK.value(), servletResponse.getStatus());
}
@Test
public void handleReturnValueETagAndLastModified() throws Exception {
long currentTime = new Date().getTime();

Loading…
Cancel
Save