You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@shindig.apache.org by jt...@apache.org on 2011/08/26 00:55:23 UTC
svn commit: r1161788 - in /shindig/trunk/java/gadgets/src:
main/java/org/apache/shindig/gadgets/servlet/
test/java/org/apache/shindig/gadgets/servlet/
Author: jtarrio
Date: Thu Aug 25 22:55:22 2011
New Revision: 1161788
URL: http://svn.apache.org/viewvc?rev=1161788&view=rev
Log:
Generate and check ETags using the proper syntax.
According to the RFC, ETags have to be in quote signs. Also, the If-None-Matches request header can specify several ETags, separated with commas.
Review: https://reviews.apache.org/r/1648/
Modified:
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/ETaggingHttpResponse.java
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/ETagFilterTest.java
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/ETaggingHttpResponseTest.java
Modified: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/ETaggingHttpResponse.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/ETaggingHttpResponse.java?rev=1161788&r1=1161787&r2=1161788&view=diff
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/ETaggingHttpResponse.java (original)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/ETaggingHttpResponse.java Thu Aug 25 22:55:22 2011
@@ -18,6 +18,10 @@
package org.apache.shindig.gadgets.servlet;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.CharMatcher;
+import com.google.common.base.Splitter;
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableList;
import org.apache.http.util.ByteArrayBuffer;
import org.apache.shindig.common.util.HashUtil;
@@ -48,6 +52,9 @@ public class ETaggingHttpResponse extend
public static final String RESPONSE_HEADER = "ETag";
public static final String REQUEST_HEADER = "If-None-Match";
+ private static final Splitter IF_NONE_MATCH_SPLITTER =
+ Splitter.on(',').trimResults().trimResults(CharMatcher.is('"'));
+
protected final HttpServletRequest request;
protected final BufferServletOutputStream stream;
protected ServletOutputStream originalStream;
@@ -145,16 +152,15 @@ public class ETaggingHttpResponse extend
*
* @throws IOException If there was a problem writing to the output.
*/
- void writeToOutput() throws IOException {
+ protected void writeToOutput() throws IOException {
if (writer != null) {
writer.flush();
}
byte[] bytes = stream.getBuffer().toByteArray();
if (batching) {
String etag = stream.getContentHash();
- String reqEtag = request.getHeader(REQUEST_HEADER);
- ((HttpServletResponse) getResponse()).setHeader(RESPONSE_HEADER, etag);
- if (etag.equals(reqEtag)) {
+ ((HttpServletResponse) getResponse()).setHeader(RESPONSE_HEADER, '"' + etag + '"');
+ if (etagMatches(etag)) {
emitETagMatchedResult();
} else {
emitFullResponseBody(bytes);
@@ -165,6 +171,14 @@ public class ETaggingHttpResponse extend
}
}
+ protected boolean etagMatches(String etag) {
+ String ifNoneMatches = request.getHeader(REQUEST_HEADER);
+ if (Strings.isNullOrEmpty(ifNoneMatches)) {
+ return false;
+ }
+ return ImmutableList.copyOf(IF_NONE_MATCH_SPLITTER.split(ifNoneMatches)).contains(etag);
+ }
+
protected void emitETagMatchedResult() {
((HttpServletResponse) getResponse()).setStatus(HttpServletResponse.SC_NOT_MODIFIED);
getResponse().setContentLength(0);
Modified: shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/ETagFilterTest.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/ETagFilterTest.java?rev=1161788&r1=1161787&r2=1161788&view=diff
==============================================================================
--- shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/ETagFilterTest.java (original)
+++ shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/ETagFilterTest.java Thu Aug 25 22:55:22 2011
@@ -69,7 +69,7 @@ public class ETagFilterTest {
EasyMock.expect(response.getOutputStream()).andReturn(stream).anyTimes();
EasyMock.expect(response.getCharacterEncoding()).andReturn(ENCODING).anyTimes();
EasyMock.expect(request.getHeader(ETaggingHttpResponse.REQUEST_HEADER)).andReturn(null);
- response.setHeader(ETaggingHttpResponse.RESPONSE_HEADER, GOOD_ETAG);
+ response.setHeader(ETaggingHttpResponse.RESPONSE_HEADER, '"' + GOOD_ETAG + '"');
response.setContentLength(RESPONSE_BODY_LENGTH);
}
Modified: shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/ETaggingHttpResponseTest.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/ETaggingHttpResponseTest.java?rev=1161788&r1=1161787&r2=1161788&view=diff
==============================================================================
--- shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/ETaggingHttpResponseTest.java (original)
+++ shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/ETaggingHttpResponseTest.java Thu Aug 25 22:55:22 2011
@@ -19,6 +19,10 @@ package org.apache.shindig.gadgets.servl
import static org.junit.Assert.*;
+import com.google.common.base.Function;
+import com.google.common.base.Joiner;
+import com.google.common.collect.Lists;
+
import org.apache.http.util.ByteArrayBuffer;
import org.apache.shindig.gadgets.servlet.ETaggingHttpResponse.BufferServletOutputStream;
import org.easymock.EasyMock;
@@ -26,6 +30,8 @@ import org.easymock.IMocksControl;
import org.junit.Before;
import org.junit.Test;
+import java.util.Arrays;
+
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -49,6 +55,12 @@ public class ETaggingHttpResponseTest {
private static final String SECOND_ETAG = "b6e56fb0129c3530f23dbb795daa3200";
private static final String BAD_ETAG = "some bogus etag";
private static final String EMPTY_CONTENT_ETAG = "d41d8cd98f00b204e9800998ecf8427e";
+
+ private static final Function<String, String> ETAG_QUOTER = new Function<String, String>() {
+ public String apply(String input) {
+ return '"' + input + '"';
+ }
+ };
private IMocksControl control;
private HttpServletRequest request;
@@ -73,7 +85,7 @@ public class ETaggingHttpResponseTest {
@Test
public void testTagContentWithPrint() throws Exception {
- expectRequestETag(null);
+ expectRequestETag();
expectFullResponse();
control.replay();
@@ -83,7 +95,7 @@ public class ETaggingHttpResponseTest {
assertResponseHasBody();
control.verify();
}
-
+
@Test
public void testNotModifiedWithPrint() throws Exception {
expectRequestETag(GOOD_ETAG);
@@ -96,6 +108,19 @@ public class ETaggingHttpResponseTest {
assertResponseBodyIsEmpty();
control.verify();
}
+
+ @Test
+ public void testNotModifiedWithManyETagsInRequest() throws Exception {
+ expectRequestETag(SECOND_ETAG, GOOD_ETAG, BAD_ETAG);
+ expectNotModifiedResponse(GOOD_ETAG);
+ control.replay();
+
+ response.getWriter().print(RESPONSE_BODY);
+ response.flushBuffer();
+
+ assertResponseBodyIsEmpty();
+ control.verify();
+ }
@Test
public void testNonMatchingETagWithPrint() throws Exception {
@@ -109,10 +134,23 @@ public class ETaggingHttpResponseTest {
assertResponseHasBody();
control.verify();
}
+
+ @Test
+ public void testNonMatchingETagWithManyETagsInRequest() throws Exception {
+ expectRequestETag(BAD_ETAG, SECOND_ETAG, EMPTY_CONTENT_ETAG);
+ expectFullResponse();
+ control.replay();
+
+ response.getWriter().print(RESPONSE_BODY);
+ response.flushBuffer();
+
+ assertResponseHasBody();
+ control.verify();
+ }
@Test
public void testTagContentWithWrite() throws Exception {
- expectRequestETag(null);
+ expectRequestETag();
expectFullResponse();
control.replay();
@@ -151,8 +189,8 @@ public class ETaggingHttpResponseTest {
@Test
public void testTagEmptyContent() throws Exception {
- expectRequestETag(null);
- origResponse.setHeader(ETaggingHttpResponse.RESPONSE_HEADER, EMPTY_CONTENT_ETAG);
+ expectRequestETag();
+ origResponse.setHeader(ETaggingHttpResponse.RESPONSE_HEADER, '"' + EMPTY_CONTENT_ETAG + '"');
origResponse.setContentLength(0);
control.replay();
@@ -165,7 +203,7 @@ public class ETaggingHttpResponseTest {
@Test
public void testStreamingMode() throws Exception {
- expectRequestETag(null);
+ expectRequestETag();
control.replay();
response.getWriter().print(RESPONSE_BODY);
@@ -213,17 +251,21 @@ public class ETaggingHttpResponseTest {
control.verify();
}
- private void expectRequestETag(String eTag) {
- EasyMock.expect(request.getHeader(ETaggingHttpResponse.REQUEST_HEADER)).andReturn(eTag);
+ private void expectRequestETag(String... eTag) {
+ String eTags = null;
+ if (eTag.length > 0) {
+ eTags = Joiner.on(',').join(Lists.transform(Arrays.asList(eTag), ETAG_QUOTER));
+ }
+ EasyMock.expect(request.getHeader(ETaggingHttpResponse.REQUEST_HEADER)).andReturn(eTags);
}
private void expectFullResponse() {
- origResponse.setHeader(ETaggingHttpResponse.RESPONSE_HEADER, GOOD_ETAG);
+ origResponse.setHeader(ETaggingHttpResponse.RESPONSE_HEADER, '"' + GOOD_ETAG + '"');
origResponse.setContentLength(RESPONSE_BODY_LENGTH);
}
private void expectNotModifiedResponse(String eTag) {
- origResponse.setHeader(ETaggingHttpResponse.RESPONSE_HEADER, eTag);
+ origResponse.setHeader(ETaggingHttpResponse.RESPONSE_HEADER, '"' + eTag + '"');
origResponse.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
origResponse.setContentLength(0);
}