checkNotModified leniently handles IE-10-style If-Modified-Since values and silently proceeds if header value cannot be parsed at all
Issue: SPR-11727
(cherry picked from commit 794e859
)
This commit is contained in:
parent
ac85eab372
commit
5d5f70473a
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2014 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.
|
||||
|
@ -17,6 +17,7 @@
|
|||
package org.springframework.web.context.request;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
@ -151,10 +152,28 @@ public class ServletWebRequest extends ServletRequestAttributes implements Nativ
|
|||
return getRequest().isSecure();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public boolean checkNotModified(long lastModifiedTimestamp) {
|
||||
if (lastModifiedTimestamp >= 0 && !this.notModified &&
|
||||
(this.response == null || !this.response.containsHeader(HEADER_LAST_MODIFIED))) {
|
||||
long ifModifiedSince = getRequest().getDateHeader(HEADER_IF_MODIFIED_SINCE);
|
||||
long ifModifiedSince = -1;
|
||||
try {
|
||||
ifModifiedSince = getRequest().getDateHeader(HEADER_IF_MODIFIED_SINCE);
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
String headerValue = getRequest().getHeader(HEADER_IF_MODIFIED_SINCE);
|
||||
// Possibly an IE 10 style value: "Wed, 09 Apr 2014 09:57:42 GMT; length=13774"
|
||||
int separatorIndex = headerValue.indexOf(';');
|
||||
if (separatorIndex != -1) {
|
||||
String datePart = headerValue.substring(0, separatorIndex);
|
||||
try {
|
||||
ifModifiedSince = Date.parse(datePart);
|
||||
}
|
||||
catch (IllegalArgumentException ex2) {
|
||||
// Giving up
|
||||
}
|
||||
}
|
||||
}
|
||||
this.notModified = (ifModifiedSince >= (lastModifiedTimestamp / 1000 * 1000));
|
||||
if (this.response != null) {
|
||||
if (this.notModified && supportsNotModifiedStatus()) {
|
||||
|
@ -168,17 +187,18 @@ public class ServletWebRequest extends ServletRequestAttributes implements Nativ
|
|||
return this.notModified;
|
||||
}
|
||||
|
||||
public boolean checkNotModified(String eTag) {
|
||||
if (StringUtils.hasLength(eTag) && !this.notModified &&
|
||||
@Override
|
||||
public boolean checkNotModified(String etag) {
|
||||
if (StringUtils.hasLength(etag) && !this.notModified &&
|
||||
(this.response == null || !this.response.containsHeader(HEADER_ETAG))) {
|
||||
String ifNoneMatch = getRequest().getHeader(HEADER_IF_NONE_MATCH);
|
||||
this.notModified = eTag.equals(ifNoneMatch);
|
||||
this.notModified = etag.equals(ifNoneMatch);
|
||||
if (this.response != null) {
|
||||
if (this.notModified && supportsNotModifiedStatus()) {
|
||||
this.response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
|
||||
}
|
||||
else {
|
||||
this.response.setHeader(HEADER_ETAG, eTag);
|
||||
this.response.setHeader(HEADER_ETAG, etag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2014 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.
|
||||
|
@ -142,8 +142,11 @@ public interface WebRequest extends RequestAttributes {
|
|||
* return "myViewName";
|
||||
* }</pre>
|
||||
* <p><strong>Note:</strong> that you typically want to use either
|
||||
* this {@link #checkNotModified(long)} method; or
|
||||
* this {@code #checkNotModified(long)} method; or
|
||||
* {@link #checkNotModified(String)}, but not both.
|
||||
* <p>If the "If-Modified-Since" header is set but cannot be parsed
|
||||
* to a date value, this method will ignore the header and proceed
|
||||
* with setting the last-modified timestamp on the response.
|
||||
* @param lastModifiedTimestamp the last-modified timestamp that
|
||||
* the application determined for the underlying resource
|
||||
* @return whether the request qualifies as not modified,
|
||||
|
@ -170,16 +173,16 @@ public interface WebRequest extends RequestAttributes {
|
|||
* return "myViewName";
|
||||
* }</pre>
|
||||
* <p><strong>Note:</strong> that you typically want to use either
|
||||
* this {@link #checkNotModified(String)} method; or
|
||||
* this {@code #checkNotModified(String)} method; or
|
||||
* {@link #checkNotModified(long)}, but not both.
|
||||
* @param eTag the entity tag that the application determined
|
||||
* @param etag the entity tag that the application determined
|
||||
* for the underlying resource. This parameter will be padded
|
||||
* with quotes (") if necessary.
|
||||
* @return whether the request qualifies as not modified,
|
||||
* allowing to abort request processing and relying on the response
|
||||
* telling the client that the content has not been modified
|
||||
*/
|
||||
boolean checkNotModified(String eTag);
|
||||
boolean checkNotModified(String etag);
|
||||
|
||||
/**
|
||||
* Get a short description of this request,
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2014 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
@ -69,13 +69,13 @@ public class ServletWebRequestTests {
|
|||
assertEquals("value2", request.getParameterValues("param2")[0]);
|
||||
assertEquals("value2a", request.getParameterValues("param2")[1]);
|
||||
|
||||
Map paramMap = request.getParameterMap();
|
||||
Map<String, String[]> paramMap = request.getParameterMap();
|
||||
assertEquals(2, paramMap.size());
|
||||
assertEquals(1, ((String[]) paramMap.get("param1")).length);
|
||||
assertEquals("value1", ((String[]) paramMap.get("param1"))[0]);
|
||||
assertEquals(2, ((String[]) paramMap.get("param2")).length);
|
||||
assertEquals("value2", ((String[]) paramMap.get("param2"))[0]);
|
||||
assertEquals("value2a", ((String[]) paramMap.get("param2"))[1]);
|
||||
assertEquals(1, paramMap.get("param1").length);
|
||||
assertEquals("value1", paramMap.get("param1")[0]);
|
||||
assertEquals(2, paramMap.get("param2").length);
|
||||
assertEquals("value2", paramMap.get("param2")[0]);
|
||||
assertEquals("value2a", paramMap.get("param2")[1]);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -117,37 +117,77 @@ public class ServletWebRequestTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void checkNotModifiedTimeStampForGET() {
|
||||
public void checkNotModifiedTimestampForGET() {
|
||||
long currentTime = new Date().getTime();
|
||||
servletRequest.setMethod("GET");
|
||||
servletRequest.addHeader("If-Modified-Since", currentTime);
|
||||
|
||||
request.checkNotModified(currentTime);
|
||||
|
||||
assertTrue(request.checkNotModified(currentTime));
|
||||
assertEquals(304, servletResponse.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkModifiedTimeStampForGET() {
|
||||
public void checkModifiedTimestampForGET() {
|
||||
long currentTime = new Date().getTime();
|
||||
long oneMinuteAgo = currentTime - (1000 * 60);
|
||||
servletRequest.setMethod("GET");
|
||||
servletRequest.addHeader("If-Modified-Since", oneMinuteAgo);
|
||||
|
||||
request.checkNotModified(currentTime);
|
||||
assertFalse(request.checkNotModified(currentTime));
|
||||
assertEquals(200, servletResponse.getStatus());
|
||||
assertEquals("" + currentTime, servletResponse.getHeader("Last-Modified"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkNotModifiedTimestampForHEAD() {
|
||||
long currentTime = new Date().getTime();
|
||||
servletRequest.setMethod("HEAD");
|
||||
servletRequest.addHeader("If-Modified-Since", currentTime);
|
||||
|
||||
assertTrue(request.checkNotModified(currentTime));
|
||||
assertEquals(304, servletResponse.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkModifiedTimestampForHEAD() {
|
||||
long currentTime = new Date().getTime();
|
||||
long oneMinuteAgo = currentTime - (1000 * 60);
|
||||
servletRequest.setMethod("HEAD");
|
||||
servletRequest.addHeader("If-Modified-Since", oneMinuteAgo);
|
||||
|
||||
assertFalse(request.checkNotModified(currentTime));
|
||||
assertEquals(200, servletResponse.getStatus());
|
||||
assertEquals(""+currentTime, servletResponse.getHeader("Last-Modified"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkNotModifiedTimestampWithLengthPart() {
|
||||
long currentTime = Date.parse("Wed, 09 Apr 2014 09:57:42 GMT");
|
||||
servletRequest.setMethod("GET");
|
||||
servletRequest.addHeader("If-Modified-Since", "Wed, 09 Apr 2014 09:57:42 GMT; length=13774");
|
||||
|
||||
assertTrue(request.checkNotModified(currentTime));
|
||||
assertEquals(304, servletResponse.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkModifiedTimestampWithLengthPart() {
|
||||
long currentTime = Date.parse("Wed, 09 Apr 2014 09:57:42 GMT");
|
||||
servletRequest.setMethod("GET");
|
||||
servletRequest.addHeader("If-Modified-Since", "Wed, 08 Apr 2014 09:57:42 GMT; length=13774");
|
||||
|
||||
assertFalse(request.checkNotModified(currentTime));
|
||||
assertEquals(200, servletResponse.getStatus());
|
||||
assertEquals("" + currentTime, servletResponse.getHeader("Last-Modified"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkNotModifiedETagForGET() {
|
||||
String eTag = "\"Foo\"";
|
||||
servletRequest.setMethod("GET");
|
||||
servletRequest.addHeader("If-None-Match", eTag );
|
||||
|
||||
request.checkNotModified(eTag);
|
||||
|
||||
assertTrue(request.checkNotModified(eTag));
|
||||
assertEquals(304, servletResponse.getStatus());
|
||||
}
|
||||
|
||||
|
@ -158,44 +198,18 @@ public class ServletWebRequestTests {
|
|||
servletRequest.setMethod("GET");
|
||||
servletRequest.addHeader("If-None-Match", oldEtag);
|
||||
|
||||
request.checkNotModified(currentETag);
|
||||
|
||||
assertFalse(request.checkNotModified(currentETag));
|
||||
assertEquals(200, servletResponse.getStatus());
|
||||
assertEquals(currentETag, servletResponse.getHeader("ETag"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkNotModifiedTimeStampForHEAD() {
|
||||
long currentTime = new Date().getTime();
|
||||
servletRequest.setMethod("HEAD");
|
||||
servletRequest.addHeader("If-Modified-Since", currentTime);
|
||||
|
||||
request.checkNotModified(currentTime);
|
||||
|
||||
assertEquals(304, servletResponse.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkModifiedTimeStampForHEAD() {
|
||||
long currentTime = new Date().getTime();
|
||||
long oneMinuteAgo = currentTime - (1000 * 60);
|
||||
servletRequest.setMethod("HEAD");
|
||||
servletRequest.addHeader("If-Modified-Since", oneMinuteAgo);
|
||||
|
||||
request.checkNotModified(currentTime);
|
||||
|
||||
assertEquals(200, servletResponse.getStatus());
|
||||
assertEquals(""+currentTime, servletResponse.getHeader("Last-Modified"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkNotModifiedETagForHEAD() {
|
||||
String eTag = "\"Foo\"";
|
||||
servletRequest.setMethod("HEAD");
|
||||
servletRequest.addHeader("If-None-Match", eTag );
|
||||
|
||||
request.checkNotModified(eTag);
|
||||
|
||||
assertTrue(request.checkNotModified(eTag));
|
||||
assertEquals(304, servletResponse.getStatus());
|
||||
}
|
||||
|
||||
|
@ -206,8 +220,7 @@ public class ServletWebRequestTests {
|
|||
servletRequest.setMethod("HEAD");
|
||||
servletRequest.addHeader("If-None-Match", oldEtag);
|
||||
|
||||
request.checkNotModified(currentETag);
|
||||
|
||||
assertFalse(request.checkNotModified(currentETag));
|
||||
assertEquals(200, servletResponse.getStatus());
|
||||
assertEquals(currentETag, servletResponse.getHeader("ETag"));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue