Author: etnu
Date: Tue Jun 23 00:01:58 2009
New Revision: 787460

URL: http://svn.apache.org/viewvc?rev=787460&view=rev
Log:
Fixed a compliance issue with caching. REFRESH_INTERVAL should override *all* 
HTTP response headers. Previously, it was not overriding responses that 
completely disabled caching.

The order of caching precedence is now:

- Check nocache / ignore cache on request
- Check refresh interval on request
- Check response headers on response
- Check default expiration time


Modified:
    
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/AbstractHttpCache.java
    
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpResponseBuilder.java
    
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/AbstractHttpCacheTest.java
    
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/HttpResponseBuilderTest.java

Modified: 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/AbstractHttpCache.java
URL: 
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/AbstractHttpCache.java?rev=787460&r1=787459&r2=787460&view=diff
==============================================================================
--- 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/AbstractHttpCache.java
 (original)
+++ 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/AbstractHttpCache.java
 Tue Jun 23 00:01:58 2009
@@ -21,12 +21,12 @@
 import static 
org.apache.shindig.gadgets.rewrite.image.BasicImageRewriter.PARAM_RESIZE_QUALITY;
 import static 
org.apache.shindig.gadgets.rewrite.image.BasicImageRewriter.PARAM_RESIZE_WIDTH;
 
-import com.google.inject.Inject;
-
 import org.apache.shindig.auth.SecurityToken;
 import org.apache.shindig.common.util.TimeSource;
 import org.apache.shindig.gadgets.AuthType;
 
+import com.google.inject.Inject;
+
 /**
  * Base class for content caches. Defines cache expiration rules and
  * and restrictions on allowed content.
@@ -64,7 +64,7 @@
   }
 
   public boolean addResponse(HttpRequest request, HttpResponse response) {
-    if (isCacheable(request) && isCacheable(response)) {
+    if (isCacheable(request, response)) {
       // Both are cacheable. Check for forced cache TTL overrides.
       HttpResponseBuilder responseBuilder = new HttpResponseBuilder(response);
       int forcedTtl = request.getCacheTtl();
@@ -91,10 +91,6 @@
     return null;
   }
 
-  protected boolean isCacheable(HttpResponse response) {
-    return !response.isStrictNoCache();
-  }
-
   protected boolean isCacheable(HttpRequest request) {
     if (request.getIgnoreCache()) {
       return false;
@@ -103,6 +99,20 @@
         !"GET".equals(request.getHeader("X-Method-Override")));
   }
 
+  protected boolean isCacheable(HttpRequest request, HttpResponse response) {
+    if (!isCacheable(request)) {
+      return false;
+    }
+
+    if (request.getCacheTtl() != -1) {
+      // Caching was forced. Ignore what the response wants.
+      return true;
+    }
+
+    // If the HTTP response allows for it, we can cache.
+    return !response.isStrictNoCache();
+  }
+
   /**
    * Produce a key from the given request.
    *

Modified: 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpResponseBuilder.java
URL: 
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpResponseBuilder.java?rev=787460&r1=787459&r2=787460&view=diff
==============================================================================
--- 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpResponseBuilder.java
 (original)
+++ 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpResponseBuilder.java
 Tue Jun 23 00:01:58 2009
@@ -17,13 +17,15 @@
  */
 package org.apache.shindig.gadgets.http;
 
+import org.apache.shindig.common.util.CharsetUtil;
+import org.apache.shindig.common.util.DateUtil;
+
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Multimap;
+
 import org.apache.commons.lang.ArrayUtils;
-import org.apache.shindig.common.util.CharsetUtil;
-import org.apache.shindig.common.util.DateUtil;
 
 import java.util.Collection;
 import java.util.List;
@@ -35,9 +37,9 @@
  */
 public class HttpResponseBuilder {
   private int httpStatusCode = HttpResponse.SC_OK;
-  private Multimap<String, String> headers = HttpResponse.newHeaderMultimap();
+  private final Multimap<String, String> headers = 
HttpResponse.newHeaderMultimap();
   private byte[] responseBytes = ArrayUtils.EMPTY_BYTE_ARRAY;
-  private Map<String, String> metadata = Maps.newHashMap();
+  private final Map<String, String> metadata = Maps.newHashMap();
 
   public HttpResponseBuilder() {}
 
@@ -72,7 +74,7 @@
     return this;
   }
 
-  /**   
+  /**
    * @param responseBytes The response body. Copied when set.
    */
   public HttpResponseBuilder setResponse(byte[] responseBytes) {
@@ -149,7 +151,7 @@
   public HttpResponseBuilder setCacheTtl(int cacheTtl) {
     headers.removeAll("Pragma");
     headers.removeAll("Expires");
-    headers.put("Cache-Control", "public,max-age=" + cacheTtl);
+    headers.replaceValues("Cache-Control", ImmutableList.of("public,max-age=" 
+ cacheTtl));
     return this;
   }
 
@@ -167,7 +169,7 @@
   /**
    * Sets cache-control headers indicating the response is not cacheable.
    */
-  private List<String> NO_CACHE_HEADER = ImmutableList.of("no-cache");
+  private final List<String> NO_CACHE_HEADER = ImmutableList.of("no-cache");
   public HttpResponseBuilder setStrictNoCache() {
     headers.replaceValues("Cache-Control", NO_CACHE_HEADER);
     headers.replaceValues("Pragma", NO_CACHE_HEADER);

Modified: 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/AbstractHttpCacheTest.java
URL: 
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/AbstractHttpCacheTest.java?rev=787460&r1=787459&r2=787460&view=diff
==============================================================================
--- 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/AbstractHttpCacheTest.java
 (original)
+++ 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/AbstractHttpCacheTest.java
 Tue Jun 23 00:01:58 2009
@@ -24,9 +24,6 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Maps;
-
 import org.apache.shindig.auth.BasicSecurityToken;
 import org.apache.shindig.auth.SecurityToken;
 import org.apache.shindig.common.uri.Uri;
@@ -35,6 +32,10 @@
 import org.apache.shindig.gadgets.AuthType;
 import org.apache.shindig.gadgets.oauth.OAuthArguments;
 import org.apache.shindig.gadgets.spec.RequestAuthenticationInfo;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+
 import org.easymock.classextension.EasyMock;
 import org.junit.Test;
 
@@ -300,6 +301,34 @@
   }
 
   @Test
+  public void addResponseWithForcedTtlAndStrictNoCache() {
+    HttpRequest request = new HttpRequest(DEFAULT_URI)
+        .setCacheTtl(10);
+
+    String key = cache.createKey(request);
+    HttpResponse response = new HttpResponseBuilder()
+        .setResponseString("result")
+        .setStrictNoCache()
+        .create();
+
+    assertTrue(cache.addResponse(request, response));
+
+    assertEquals("public,max-age=10", 
cache.map.get(key).getHeader("Cache-Control"));
+  }
+
+  @Test
+  public void addResponseWithNoCachingHeaders() {
+    HttpRequest request = new HttpRequest(DEFAULT_URI);
+
+    String key = cache.createKey(request);
+    HttpResponse response = new HttpResponse("no headers");
+
+    assertTrue(cache.addResponse(request, response));
+
+    assertEquals("no headers", cache.map.get(key).getResponseAsString());
+  }
+
+  @Test
   public void removeResponse() {
     HttpRequest request = new HttpRequest(DEFAULT_URI);
     String key = cache.createKey(request);

Modified: 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/HttpResponseBuilderTest.java
URL: 
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/HttpResponseBuilderTest.java?rev=787460&r1=787459&r2=787460&view=diff
==============================================================================
--- 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/HttpResponseBuilderTest.java
 (original)
+++ 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/HttpResponseBuilderTest.java
 Tue Jun 23 00:01:58 2009
@@ -17,6 +17,10 @@
  */
 package org.apache.shindig.gadgets.http;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
 import com.google.common.base.Joiner;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
@@ -24,9 +28,6 @@
 import com.google.common.collect.Maps;
 import com.google.common.collect.Multimap;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
 import org.junit.Test;
 
 import java.util.Arrays;
@@ -61,7 +62,7 @@
 
   @Test
   public void addHeadersMap() {
-    Map<String, String> headers = ImmutableMap.of("foo", "bar", "blah", 
"blah");    
+    Map<String, String> headers = ImmutableMap.of("foo", "bar", "blah", 
"blah");
 
     HttpResponseBuilder builder = new HttpResponseBuilder()
         .addHeaders(headers);
@@ -105,6 +106,7 @@
     HttpResponseBuilder builder = new HttpResponseBuilder()
         .addHeader("Pragma", "no-cache")
         .addHeader("Expires", "some time stamp normally goes here")
+        .addHeader("Cache-Control", "no-cache")
         .setCacheTtl(100);
 
     Multimap<String, String> headers = builder.getHeaders();


Reply via email to