You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by lu...@apache.org on 2014/01/03 07:42:19 UTC
svn commit: r1555018 - in /struts/struts2/trunk:
core/src/main/java/org/apache/struts2/RequestUtils.java
core/src/test/java/org/apache/struts2/RequestUtilsTest.java
plugins/rest/src/main/java/org/apache/struts2/rest/DefaultHttpHeaders.java
Author: lukaszlenart
Date: Fri Jan 3 06:42:19 2014
New Revision: 1555018
URL: http://svn.apache.org/r1555018
Log:
WW-4263 Adds proper and thread safe handling of If-Modified-Since header
Modified:
struts/struts2/trunk/core/src/main/java/org/apache/struts2/RequestUtils.java
struts/struts2/trunk/core/src/test/java/org/apache/struts2/RequestUtilsTest.java
struts/struts2/trunk/plugins/rest/src/main/java/org/apache/struts2/rest/DefaultHttpHeaders.java
Modified: struts/struts2/trunk/core/src/main/java/org/apache/struts2/RequestUtils.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/RequestUtils.java?rev=1555018&r1=1555017&r2=1555018&view=diff
==============================================================================
--- struts/struts2/trunk/core/src/main/java/org/apache/struts2/RequestUtils.java (original)
+++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/RequestUtils.java Fri Jan 3 06:42:19 2014
@@ -21,7 +21,15 @@
package org.apache.struts2;
+import com.opensymphony.xwork2.util.logging.Logger;
+import com.opensymphony.xwork2.util.logging.LoggerFactory;
+import org.apache.commons.lang3.time.FastDateFormat;
+
import javax.servlet.http.HttpServletRequest;
+import java.text.ParseException;
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
/**
@@ -29,6 +37,20 @@ import javax.servlet.http.HttpServletReq
*/
public class RequestUtils {
+ private static final Logger LOG = LoggerFactory.getLogger(RequestUtils.class);
+
+ private static final TimeZone GMT = TimeZone.getTimeZone("GMT");
+
+ private static final String FORMAT_PATTERN_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss zzz";
+ private static final String FORMAT_PATTERN_RFC1036 = "EEE, dd-MMM-yy HH:mm:ss zzz";
+ private static final String FORMAT_PATTERN_ASCTIME = "EEE MMM d HH:mm:ss yyyy";
+
+ private static final FastDateFormat[] IF_MODIFIED_SINCE_FORMATS = {
+ FastDateFormat.getInstance(FORMAT_PATTERN_RFC1123, GMT, Locale.US),
+ FastDateFormat.getInstance(FORMAT_PATTERN_RFC1036, GMT, Locale.US),
+ FastDateFormat.getInstance(FORMAT_PATTERN_ASCTIME, GMT, Locale.US)
+ };
+
/**
* Retrieves the current request servlet path.
* Deals with differences between servlet specs (2.2 vs 2.3+)
@@ -84,4 +106,30 @@ public class RequestUtils {
uri = request.getRequestURI();
return uri.substring(request.getContextPath().length());
}
+
+ /**
+ * Parse input string as date in formats defined for If-Modified-Since header,
+ * see:
+ * https://issues.apache.org/jira/browse/WW-4263
+ * https://web.archive.org/web/20081014021349/http://rfc.net/rfc2616.html#p20
+ *
+ * @param headerValue value of If-Modified-Since header
+ * @return proper date or null
+ */
+ public static Date parseIfModifiedSince(String headerValue) {
+ for (FastDateFormat fastDateFormat : IF_MODIFIED_SINCE_FORMATS) {
+ try {
+ return fastDateFormat.parse(headerValue);
+ } catch (ParseException ignore) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Error parsing value [#0] as [#1]!", headerValue, fastDateFormat);
+ }
+ }
+ }
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Error parsing value [#0] as date!", headerValue);
+ }
+ return null;
+ }
+
}
Modified: struts/struts2/trunk/core/src/test/java/org/apache/struts2/RequestUtilsTest.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/test/java/org/apache/struts2/RequestUtilsTest.java?rev=1555018&r1=1555017&r2=1555018&view=diff
==============================================================================
--- struts/struts2/trunk/core/src/test/java/org/apache/struts2/RequestUtilsTest.java (original)
+++ struts/struts2/trunk/core/src/test/java/org/apache/struts2/RequestUtilsTest.java Fri Jan 3 06:42:19 2014
@@ -25,12 +25,12 @@ package org.apache.struts2;
* <code>RequestUtilsTest</code>
*
*/
-import javax.servlet.http.HttpServletRequest;
-
import junit.framework.TestCase;
-
import org.easymock.MockControl;
+import javax.servlet.http.HttpServletRequest;
+import java.util.Date;
+
public class RequestUtilsTest extends TestCase {
private MockControl control;
@@ -86,6 +86,22 @@ public class RequestUtilsTest extends Te
control.verify();
}
+ public void testParseRFC1123() {
+ Date date = RequestUtils.parseIfModifiedSince("Thu, 23 Jul 2013 19:42:23 GMT");
+ assertNotNull(date);
+ }
+
+ public void testParseRFC1036() {
+ Date date = RequestUtils.parseIfModifiedSince("Thursday, 23-Jul-13 19:42:23 GMT");
+ assertNotNull(date);
+ }
+
+ public void testParseASC() {
+ Date date = RequestUtils.parseIfModifiedSince("Thu Jul 23 19:42:23 2013");
+ assertNotNull(date);
+ }
+
+
protected void setUp() {
control = MockControl.createControl(HttpServletRequest.class);
requestMock = (HttpServletRequest) control.getMock();
Modified: struts/struts2/trunk/plugins/rest/src/main/java/org/apache/struts2/rest/DefaultHttpHeaders.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/plugins/rest/src/main/java/org/apache/struts2/rest/DefaultHttpHeaders.java?rev=1555018&r1=1555017&r2=1555018&view=diff
==============================================================================
--- struts/struts2/trunk/plugins/rest/src/main/java/org/apache/struts2/rest/DefaultHttpHeaders.java (original)
+++ struts/struts2/trunk/plugins/rest/src/main/java/org/apache/struts2/rest/DefaultHttpHeaders.java Fri Jan 3 06:42:19 2014
@@ -21,29 +21,19 @@
package org.apache.struts2.rest;
-import com.opensymphony.xwork2.util.logging.Logger;
-import com.opensymphony.xwork2.util.logging.LoggerFactory;
+import org.apache.struts2.RequestUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
import java.util.Date;
-import static javax.servlet.http.HttpServletResponse.SC_CREATED;
-import static javax.servlet.http.HttpServletResponse.SC_NOT_MODIFIED;
-import static javax.servlet.http.HttpServletResponse.SC_OK;
+import static javax.servlet.http.HttpServletResponse.*;
/**
* Default implementation of rest info that uses fluent-style construction
*/
public class DefaultHttpHeaders implements HttpHeaders {
- private static final Logger LOG = LoggerFactory.getLogger(DefaultHttpHeaders.class);
-
- private static final String IF_MODIFIED_SINCE_DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss zzz";
- private static final SimpleDateFormat IF_MODIFIED_SINCE_FORMAT = new SimpleDateFormat(IF_MODIFIED_SINCE_DATE_FORMAT);
-
private String resultCode;
private int status = SC_OK;
private Object etag;
@@ -144,13 +134,13 @@ public class DefaultHttpHeaders implemen
}
}
- String reqLastModified = request.getHeader("If-Modified-Since");
- if (lastModified != null && reqLastModified != null) {
- lastModifiedNotChanged = compareIfModifiedSince(reqLastModified);
+ String headerIfModifiedSince = request.getHeader("If-Modified-Since");
+ if (lastModified != null && headerIfModifiedSince != null) {
+ lastModifiedNotChanged = compareIfModifiedSince(headerIfModifiedSince);
}
if ((etagNotChanged && lastModifiedNotChanged) ||
- (etagNotChanged && reqLastModified == null) ||
+ (etagNotChanged && headerIfModifiedSince == null) ||
(lastModifiedNotChanged && reqETag == null)) {
status = SC_NOT_MODIFIED;
}
@@ -160,18 +150,9 @@ public class DefaultHttpHeaders implemen
return resultCode;
}
- private boolean compareIfModifiedSince(String reqLastModified) {
- try {
- if (lastModified.compareTo(IF_MODIFIED_SINCE_FORMAT.parse(reqLastModified)) >= 0) {
- return true;
- }
- } catch (ParseException e) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("Got error parsing If-Modified-Since header value [#0] as [#1]!", e, reqLastModified, IF_MODIFIED_SINCE_DATE_FORMAT);
- }
- return false;
- }
- return false;
+ private boolean compareIfModifiedSince(String headerIfModifiedSince) {
+ Date requestLastModified = RequestUtils.parseIfModifiedSince(headerIfModifiedSince);
+ return requestLastModified != null && lastModified.compareTo(requestLastModified) >= 0;
}
public int getStatus() {