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
This commit is contained in:
@@ -99,6 +99,15 @@ public class ServletWebRequestHttpMethodsTests {
|
|||||||
assertEquals(dateFormat.format(epochTime), servletResponse.getHeader("Last-Modified"));
|
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
|
@Test
|
||||||
public void checkNotModifiedHeaderAlreadySet() {
|
public void checkNotModifiedHeaderAlreadySet() {
|
||||||
long epochTime = currentDate.getTime();
|
long epochTime = currentDate.getTime();
|
||||||
|
|||||||
@@ -223,25 +223,29 @@ public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodPro
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isResourceNotModified(ServletServerHttpRequest inputMessage, ServletServerHttpResponse outputMessage) {
|
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;
|
boolean notModified = false;
|
||||||
|
try {
|
||||||
if (!ifNoneMatch.isEmpty() && (inputMessage.getHeaders().containsKey(HttpHeaders.IF_UNMODIFIED_SINCE)
|
long ifModifiedSince = inputMessage.getHeaders().getIfModifiedSince();
|
||||||
|| inputMessage.getHeaders().containsKey(HttpHeaders.IF_MATCH))) {
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IllegalArgumentException exc) {
|
||||||
// invalid conditional request, do not process
|
// 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);
|
|
||||||
}
|
|
||||||
return notModified;
|
return notModified;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -379,6 +379,21 @@ public class HttpEntityMethodProcessorMockTests {
|
|||||||
assertEquals(etagValue, servletResponse.getHeader(HttpHeaders.ETAG));
|
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
|
@Test
|
||||||
public void handleReturnValueETagAndLastModified() throws Exception {
|
public void handleReturnValueETagAndLastModified() throws Exception {
|
||||||
long currentTime = new Date().getTime();
|
long currentTime = new Date().getTime();
|
||||||
|
|||||||
Reference in New Issue
Block a user