Author: beaton
Date: Sat Jul 19 23:47:35 2008
New Revision: 678253

URL: http://svn.apache.org/viewvc?rev=678253&view=rev
Log:
Fix several caching bugs as prep for caching OAuth authenticated fetches.
Bug #1: unauthenticated fetches could read cached data from authenticated 
fetches.
Bug #2: various bits of code were unintentially tampering with the default 
fetching
options.  (Example: new HttpRequest(uri).getOptions().ignoreCache = true would
disable caching for almost all fetches.)

There are interface changes here that will likely affect Shindig deployments.
These were discussed on shindig-dev without objection, but if they cause you 
pain let me (and shindig-dev) know.

Added:
    
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpCacheKey.java
    
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/HttpCacheKeyTest.java
Modified:
    
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/SigningFetcher.java
    
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/BasicHttpCache.java
    
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/BasicHttpFetcher.java
    
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpCache.java
    
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpRequest.java
    
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/OAuthFetcher.java
    
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/InterceptingContentFetcher.java
    
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/SigningFetcherTest.java
    
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/BasicHttpCacheTest.java
    
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/HttpRequestTest.java

Modified: 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/SigningFetcher.java
URL: 
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/SigningFetcher.java?rev=678253&r1=678252&r2=678253&view=diff
==============================================================================
--- 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/SigningFetcher.java
 (original)
+++ 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/SigningFetcher.java
 Sat Jul 19 23:47:35 2008
@@ -18,6 +18,7 @@
 import org.apache.shindig.common.crypto.Crypto;
 import org.apache.shindig.common.util.TimeSource;
 import org.apache.shindig.gadgets.http.HttpCache;
+import org.apache.shindig.gadgets.http.HttpCacheKey;
 import org.apache.shindig.gadgets.http.HttpFetcher;
 import org.apache.shindig.gadgets.http.HttpRequest;
 import org.apache.shindig.gadgets.http.HttpResponse;
@@ -29,7 +30,6 @@
 import net.oauth.OAuth.Parameter;
 import net.oauth.signature.RSA_SHA1;
 
-import java.io.IOException;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URL;
@@ -149,45 +149,36 @@
       throws GadgetException {
 
     try {
-      HttpRequest cacheableRequest = makeCacheableRequest(request);
-      HttpResponse result = cache.getResponse(cacheableRequest);
+      HttpCacheKey cacheKey = makeCacheKey(request);
+      HttpResponse result = cache.getResponse(cacheKey, request);
       if (result != null) {
         return result;
       }
 
       HttpRequest signedRequest = signRequest(request);
-      // Signed requests are not externally cacehable
+      // Signed requests are not externally cacheable
       signedRequest.getOptions().ignoreCache = true;
       result = nextFetcher.fetch(signedRequest);
 
       // Try and cache the response
-      return cache.addResponse(cacheableRequest, result);
+      return cache.addResponse(cacheKey, request, result);
     } catch (GadgetException e) {
       throw e;
     } catch (Exception e) {
       throw new GadgetException(GadgetException.Code.INTERNAL_SERVER_ERROR, e);
     }
   }
-
-  private HttpRequest makeCacheableRequest(
-      HttpRequest request)
-      throws IOException, URISyntaxException, RequestSigningException {
-    // Create a request without the OAuth params which includes the
-    // OpenSocial ones and see if we can find it in the cache
-    URI resource = request.getUri();
-    String query = resource.getRawQuery();
-    List<Parameter> cacheableParams = sanitize(OAuth.decodeForm(query));
-    addOpenSocialParams(request.getOptions(), cacheableParams);
-    addOAuthNonTemporalParams(cacheableParams);
-    String cacheableQuery = OAuth.formEncode(cacheableParams);
-    URL url = new URL(
-          resource.getScheme(),
-          resource.getHost(),
-          resource.getPort(),
-          resource.getRawPath() + '?' + cacheableQuery);
-    HttpRequest cacheableRequest =
-        new HttpRequest(url.toURI(), request);
-    return cacheableRequest;
+  
+  private HttpCacheKey makeCacheKey(HttpRequest request) {
+    HttpCacheKey key = new HttpCacheKey(request);
+    key.set("authentication", "signed");
+    List<Parameter> signedFetchParams = new ArrayList<Parameter>();
+    addOpenSocialParams(request.getOptions(), signedFetchParams);
+    addOAuthNonTemporalParams(signedFetchParams);
+    for (Parameter p : signedFetchParams) {
+      key.set(p.getKey(), p.getValue());
+    }
+    return key;
   }
 
   private HttpRequest signRequest(HttpRequest req)

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=678253&r1=678252&r2=678253&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
 Sat Jul 19 23:47:35 2008
@@ -17,8 +17,6 @@
  */
 package org.apache.shindig.gadgets.http;
 
-import java.net.URI;
-
 /**
  * Base class for content caches. Defines cache expiration rules and
  * and restrictions on allowed content. Also enforces rewriting
@@ -26,24 +24,22 @@
  */
 public abstract class AbstractHttpCache implements HttpCache {
 
-  public final HttpResponse getResponse(HttpRequest request) {
-    if (canCacheRequest(request)) {
-      HttpResponse response = getResponse(request.getUri());
-      return checkRewrite(request, response);
+  public final HttpResponse getResponse(HttpCacheKey key, HttpRequest request) 
{
+    if (key.isCacheable()) {
+      String keyString = key.toString();
+      HttpResponse cached = getResponseImpl(keyString);
+      if (responseStillUsable(cached)) {
+        return checkRewrite(keyString, request, cached);
+      }
     }
     return null;
   }
 
-  public final HttpResponse getResponse(URI uri) {
-    if (uri == null) return null;
-    return checkResponse(getResponseImpl(uri));
-  }
-
-  protected abstract HttpResponse getResponseImpl(URI uri);
-
-  public HttpResponse addResponse(HttpRequest request, HttpResponse response) {
-    if (canCacheRequest(request)) {
+  protected abstract HttpResponse getResponseImpl(String key);
 
+  public HttpResponse addResponse(HttpCacheKey key, HttpRequest request,
+      HttpResponse response) {
+    if (key.isCacheable()) {
       // If the request forces a minimum TTL for the cached content then have
       // the response honor it
       if (response != null) {
@@ -53,61 +49,44 @@
       // !!! Note that we only rewrite cacheable content. Move this call above 
the if
       // to rewrite all content that passes through the cache regardless of 
cacheability
       rewrite(request, response);
-      addResponse(request.getUri(), response);
-      return checkRewrite(request, response);
+      String keyString = key.toString();
+      if (responseStillUsable(response)) {
+        addResponseImpl(keyString, response);
+      }
+      return checkRewrite(keyString, request, response);
     }
     return response;
   }
 
-  public HttpResponse addResponse(URI uri, HttpResponse response) {
-    if (uri == null || response == null) return response;
-    response = checkResponse(response);
-    addResponseImpl(uri, response);
-    return response;
-  }
-
-  protected abstract void addResponseImpl(URI uri, HttpResponse response);
-
-  public HttpResponse removeResponse(HttpRequest request) {
-    return removeResponse(request.getUri());
-  }
+  protected abstract void addResponseImpl(String key, HttpResponse response);
 
-  public HttpResponse removeResponse(URI uri) {
-    if (uri == null) return null;
-    HttpResponse response = getResponseImpl(uri);
-    removeResponseImpl(uri);
-    return checkResponse(response);
+  public HttpResponse removeResponse(HttpCacheKey key) {
+    String keyString = key.toString();
+    HttpResponse response = getResponseImpl(keyString);
+    removeResponseImpl(keyString);
+    if (responseStillUsable(response)) {
+      return response;
+    }
+    return null;
   }
 
-  protected abstract HttpResponse removeResponseImpl(URI uri);
+  protected abstract HttpResponse removeResponseImpl(String key);
 
   /**
    * Utility function to verify that an entry is cacheable and not expired
-   * Returns null if the content is no longer cacheable.
-   *
-   * @param request
-   * @return content or null
-   */
-  protected boolean canCacheRequest(HttpRequest request) {
-    return ("GET".equals(request.getMethod()) &&
-        !request.getOptions().ignoreCache);
-  }
-
-  /**
-   * Utility function to verify that an entry is cacheable and not expired
-   * Returns null if the content is no longer cacheable.
+   * Returns false if the content is no longer cacheable.
    *
    * @param response
-   * @return content or null
+   * @return true if the response can be used.
    */
-  protected HttpResponse checkResponse(HttpResponse response) {
+  protected boolean responseStillUsable(HttpResponse response) {
     if (response == null) {
-      return null;
+      return false;
     }
     if (response.getCacheExpiration() < System.currentTimeMillis()) {
-      return null;
+      return false;
     }
-    return response;
+    return true;
   }
 
   /**
@@ -115,13 +94,16 @@
    * we can add it. Re-cache if we created rewritten content.
    * Return the appropriately re-written version if requested
    */
-  protected HttpResponse checkRewrite(HttpRequest request, HttpResponse 
response) {
-    if (response == null) return null;
+  protected HttpResponse checkRewrite(String keyString, HttpRequest request,
+      HttpResponse response) {
+    if (response == null) {
+      return null;
+    }
 
     // Perform a rewrite and store the content back to the cache if the
     // content is actually rewritten
     if (rewrite(request, response)) {
-      addResponseImpl(request.getUri(), response);
+      addResponseImpl(keyString, response);
     }
 
     // Return the rewritten version if requested

Modified: 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/BasicHttpCache.java
URL: 
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/BasicHttpCache.java?rev=678253&r1=678252&r2=678253&view=diff
==============================================================================
--- 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/BasicHttpCache.java
 (original)
+++ 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/BasicHttpCache.java
 Sat Jul 19 23:47:35 2008
@@ -23,28 +23,26 @@
 import com.google.inject.Inject;
 import com.google.inject.name.Named;
 
-import java.net.URI;
-
 /**
  * Simple cache of HttpResponse. Uses WeakHashMap for memory management
  */
 public class BasicHttpCache extends AbstractHttpCache {
 
-  private final Cache<URI, HttpResponse> cache;
+  private final Cache<String, HttpResponse> cache;
 
   @Override
-  protected HttpResponse getResponseImpl(URI uri) {
-    return cache.getElement(uri);
+  protected HttpResponse getResponseImpl(String key) {
+    return cache.getElement(key);
   }
 
   @Override
-  protected void addResponseImpl(URI uri, HttpResponse response) {
-    cache.addElement(uri, response);
+  protected void addResponseImpl(String key, HttpResponse response) {
+    cache.addElement(key, response);
   }
 
   @Override
-  protected HttpResponse removeResponseImpl(URI uri) {
-    return cache.removeElement(uri);
+  protected HttpResponse removeResponseImpl(String key) {
+    return cache.removeElement(key);
   }
 
   @Inject

Modified: 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/BasicHttpFetcher.java
URL: 
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/BasicHttpFetcher.java?rev=678253&r1=678252&r2=678253&view=diff
==============================================================================
--- 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/BasicHttpFetcher.java
 (original)
+++ 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/BasicHttpFetcher.java
 Sat Jul 19 23:47:35 2008
@@ -145,7 +145,8 @@
 
   /** [EMAIL PROTECTED] */
   public HttpResponse fetch(HttpRequest request) {
-    HttpResponse response = cache.getResponse(request);
+    HttpCacheKey cacheKey = new HttpCacheKey(request);
+    HttpResponse response = cache.getResponse(cacheKey, request);
     if (response != null) {
       return response;
     }
@@ -162,7 +163,7 @@
         IOUtils.copy(request.getPostBody(), fetcher.getOutputStream());
       }
       response = makeResponse(fetcher);
-      return cache.addResponse(request, response);
+      return cache.addResponse(cacheKey, request, response);
     } catch (IOException e) {
       if (e instanceof java.net.SocketTimeoutException ||
           e instanceof java.net.SocketException) {

Modified: 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpCache.java
URL: 
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpCache.java?rev=678253&r1=678252&r2=678253&view=diff
==============================================================================
--- 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpCache.java
 (original)
+++ 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpCache.java
 Sat Jul 19 23:47:35 2008
@@ -19,25 +19,20 @@
 
 import com.google.inject.ImplementedBy;
 
-import java.net.URI;
-
 /**
- * Cache of HttpResponse keyed by URI/HttpRequest
+ * Cache of HttpResponse.
+ * 
+ * Keys are made of more or less arbitrary name/value pairs (the HttpCacheKey)
+ * and data about the HttpRequest.  The values are the HttpResponse.
  */
-
 @ImplementedBy(BasicHttpCache.class)
-
 public interface HttpCache {
 
-  public HttpResponse getResponse(URI uri);
-
-  public HttpResponse getResponse(HttpRequest request);
-
-  public HttpResponse addResponse(URI uri, HttpResponse response);
+  public HttpResponse getResponse(HttpCacheKey key, HttpRequest request);
 
-  public HttpResponse addResponse(HttpRequest request, HttpResponse response);
+  public HttpResponse addResponse(HttpCacheKey key, HttpRequest request,
+      HttpResponse response);
 
-  public HttpResponse removeResponse(URI uri);
+  public HttpResponse removeResponse(HttpCacheKey key);
 
-  public HttpResponse removeResponse(HttpRequest request);
 }

Added: 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpCacheKey.java
URL: 
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpCacheKey.java?rev=678253&view=auto
==============================================================================
--- 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpCacheKey.java
 (added)
+++ 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpCacheKey.java
 Sat Jul 19 23:47:35 2008
@@ -0,0 +1,99 @@
+/*
+ * 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
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shindig.gadgets.http;
+
+import org.json.JSONArray;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Key for use in an HttpCache
+ *
+ * The key is made up of name/value pairs.  By default only the HTTP method
+ * and URL are included in the cache key.  Use the set() method to add
+ * additional data to the cache key.
+ */
+public class HttpCacheKey {
+
+  private Map<String, String> data;
+  private boolean cacheable;
+
+  /**
+   * Create a cache key for the specified request.
+   * 
+   * @param request
+   */
+  public HttpCacheKey(HttpRequest request) {
+    data = new HashMap<String,String>();
+    setCacheable(true);
+    if (!"GET".equals(request.getMethod()) ||
+        request.getOptions().ignoreCache) {
+      setCacheable(false);
+    }
+    // In theory we only cache GET, but including the method in the cache key
+    // provides some additional insurance that we aren't mixing cache content.
+    set("method", request.getMethod());
+    set("url", request.getUri().toASCIIString());
+  }
+  
+  /**
+   * Add additional data to the cache key.
+   */
+  public void set(String key, String value) {
+    data.put(key, value);
+  }
+  
+  /**
+   * Remove data from the cache key.
+   */
+  public void remove(String key) {
+    data.remove(key);
+  }
+  
+  public void setCacheable(boolean cacheable) {
+    this.cacheable = cacheable;
+  }
+  
+  public boolean isCacheable() {
+    return cacheable;
+  }
+  
+  /**
+   * Figure out a string representation of this cache key.  The representation
+   * will be:
+   * 
+   * canonical: identical sets of key/value pairs will always map to the same
+   * string.
+   * 
+   * unique: different sets of key/value pairs will always map to different
+   * strings.
+   */
+  @Override
+  public String toString() {
+    List<String> list = new ArrayList<String>();
+    list.addAll(data.keySet());
+    Collections.sort(list);
+    JSONArray json = new JSONArray();
+    for (String key : list) {
+      json.put(Collections.singletonMap(key, data.get(key)));
+    }
+    return json.toString();
+  }
+
+}

Modified: 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpRequest.java
URL: 
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpRequest.java?rev=678253&r1=678252&r2=678253&view=diff
==============================================================================
--- 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpRequest.java
 (original)
+++ 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpRequest.java
 Sat Jul 19 23:47:35 2008
@@ -228,7 +228,7 @@
    * @param uri
    */
   public HttpRequest(URI uri) {
-    this("GET", uri, null, null, DEFAULT_OPTIONS);
+    this("GET", uri, null, null, getDefaultOptions());
   }
 
   /**
@@ -247,7 +247,7 @@
    * @param headers
    */
   public HttpRequest(URI uri, Map<String, List<String>> headers) {
-    this("GET", uri, headers, null, DEFAULT_OPTIONS);
+    this("GET", uri, headers, null, getDefaultOptions());
   }
 
   /**
@@ -267,7 +267,7 @@
    * @param postBody
    */
   public HttpRequest(URI uri, byte[] postBody) {
-    this("POST", uri, null, postBody, DEFAULT_OPTIONS);
+    this("POST", uri, null, postBody, getDefaultOptions());
   }
 
   /**
@@ -288,7 +288,7 @@
    */
   public HttpRequest(URI uri, Map<String, List<String>> headers,
       byte[] postBody) {
-    this("POST", uri, headers, postBody, DEFAULT_OPTIONS);
+    this("POST", uri, headers, postBody, getDefaultOptions());
   }
 
   /**
@@ -342,10 +342,14 @@
     return false;
   }
 
-  public static final Options DEFAULT_OPTIONS = new Options();
-  public static final Options IGNORE_CACHE_OPTIONS = new Options();
-  static {
-    IGNORE_CACHE_OPTIONS.ignoreCache = true;
+  public static Options getDefaultOptions() {
+    return new Options();
+  }
+  
+  public static Options getIgnoreCacheOptions() {
+    Options o = new Options();
+    o.ignoreCache = true;
+    return o;
   }
 
   /**

Modified: 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/OAuthFetcher.java
URL: 
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/OAuthFetcher.java?rev=678253&r1=678252&r2=678253&view=diff
==============================================================================
--- 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/OAuthFetcher.java
 (original)
+++ 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/OAuthFetcher.java
 Sat Jul 19 23:47:35 2008
@@ -491,7 +491,7 @@
                                  null,
                                  HttpRequest.DEFAULT_CONTENT_TYPE,
                                  null,
-                                 HttpRequest.DEFAULT_OPTIONS);
+                                 HttpRequest.getIgnoreCacheOptions());
 
     HttpResponse response = nextFetcher.fetch(oauthRequest);
     checkForProtocolProblem(response);

Modified: 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/InterceptingContentFetcher.java
URL: 
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/InterceptingContentFetcher.java?rev=678253&r1=678252&r2=678253&view=diff
==============================================================================
--- 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/InterceptingContentFetcher.java
 (original)
+++ 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/InterceptingContentFetcher.java
 Sat Jul 19 23:47:35 2008
@@ -16,6 +16,8 @@
 
 import org.apache.shindig.gadgets.http.HttpResponse;
 import org.apache.shindig.gadgets.http.HttpRequest;
+import org.json.JSONException;
+import org.json.JSONObject;
 
 /**
  * Test utility to intercept remote content requests for inspection.
@@ -30,7 +32,15 @@
 
   public HttpResponse fetch(HttpRequest request) {
     interceptedRequest = request;
-    return null;
+    try {
+      JSONObject resp = new JSONObject();
+      resp.put("url", request.getUri().toASCIIString());
+      resp.put("method", request.getMethod());
+      resp.put("body", request.getPostBodyAsString());
+      return new HttpResponse(resp.toString());
+    } catch (JSONException e) {
+      return new HttpResponse(e.toString());
+    }
   }
 
 }

Modified: 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/SigningFetcherTest.java
URL: 
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/SigningFetcherTest.java?rev=678253&r1=678252&r2=678253&view=diff
==============================================================================
--- 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/SigningFetcherTest.java
 (original)
+++ 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/SigningFetcherTest.java
 Sat Jul 19 23:47:35 2008
@@ -132,16 +132,60 @@
   }
 
   public void testNoSignOwner() throws Exception {
-    HttpRequest unsigned
-        = makeHttpRequest("GET", "http://test";, null);
+    HttpRequest unsigned = makeHttpRequest("GET", "http://test";, null);
+    unsigned.getOptions().viewerSigned = false;
+    HttpRequest out = signAndInspect(unsigned);
+    List<OAuth.Parameter> queryParams = 
OAuth.decodeForm(out.getUri().getRawQuery());
+    assertTrue(contains(queryParams, "opensocial_owner_id", "o"));
+    assertFalse(contains(queryParams, "opensocial_viewer_id", "v"));
+  }
+  
+  public void testCacheHit() throws Exception {
+    HttpRequest unsigned = makeHttpRequest("GET", "http://test";, null);
+    HttpRequest out = signAndInspect(unsigned);
+
+    HttpRequest unsigned2 = makeHttpRequest("GET", "http://test";, null);
+    interceptor.interceptedRequest = null;
+    signer.fetch(unsigned2);
+    assertNull(interceptor.interceptedRequest);
+  }
+  
+  public void testCacheMiss_noOwner() throws Exception {
+    HttpRequest unsigned = makeHttpRequest("GET", "http://test";, null);
     unsigned.getOptions().ownerSigned = false;
     HttpRequest out = signAndInspect(unsigned);
-    List<OAuth.Parameter> queryParams
-        = OAuth.decodeForm(out.getUri().getRawQuery());
-    assertFalse(contains(queryParams, "opensocial_owner_id", "o"));
-    assertTrue(contains(queryParams, "opensocial_viewer_id", "v"));
-  }
 
+    HttpRequest unsigned2 = makeHttpRequest("GET", "http://test";, null);
+    interceptor.interceptedRequest = null;
+    signer.fetch(unsigned2);
+    assertNotNull(interceptor.interceptedRequest);
+  }
+  
+  public void testCacheHit_ownerOnly() throws Exception {
+    HttpRequest unsigned = makeHttpRequest("GET", "http://test";, null);
+    unsigned.getOptions().viewerSigned = false;
+    HttpRequest out = signAndInspect(unsigned);
+
+    HttpRequest unsigned2 = makeHttpRequest("GET", "http://test";, null);
+    unsigned2.getOptions().viewerSigned = false;
+    interceptor.interceptedRequest = null;
+    signer.fetch(unsigned2);
+    assertNull(interceptor.interceptedRequest);
+  }
+  
+  public void testCacheMiss_bypassCache() throws Exception {
+    HttpRequest unsigned = makeHttpRequest("GET", "http://test";, null);
+    unsigned.getOptions().viewerSigned = false;
+    HttpRequest out = signAndInspect(unsigned);
+
+    HttpRequest unsigned2 = makeHttpRequest("GET", "http://test";, null);
+    unsigned2.getOptions().ignoreCache = true;
+    unsigned2.getOptions().viewerSigned = false;
+    interceptor.interceptedRequest = null;
+    signer.fetch(unsigned2);
+    assertNotNull(interceptor.interceptedRequest);
+  }
+  
   public void testTrickyParametersInQuery() throws Exception {
     String tricky = "%6fpensocial_owner_id=gotcha";
     HttpRequest unsigned

Modified: 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/BasicHttpCacheTest.java
URL: 
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/BasicHttpCacheTest.java?rev=678253&r1=678252&r2=678253&view=diff
==============================================================================
--- 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/BasicHttpCacheTest.java
 (original)
+++ 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/BasicHttpCacheTest.java
 Sat Jul 19 23:47:35 2008
@@ -75,66 +75,76 @@
   }
 
   public void testEmptyCache() {
-    assertNull(cache.getResponse(createRequest("GET")));
+    HttpRequest req = createRequest("GET");
+    HttpCacheKey key = new HttpCacheKey(req);
+    assertNull(cache.getResponse(key, req));
   }
 
   public void testCacheable() {
     HttpRequest req = createRequest("GET");
     HttpResponse resp = createResponse(200, null, null);
-    cache.addResponse(req, resp);
-    assertEquals(cache.getResponse(req), resp);
+    HttpCacheKey key = new HttpCacheKey(req);
+    cache.addResponse(key, req, resp);
+    assertEquals(cache.getResponse(key, req), resp);
   }
 
   public void testNotCacheableForPost() {
     HttpRequest req = createRequest("POST");
     HttpResponse resp = createResponse(200, null, null);
-    cache.addResponse(req, resp);
-    assertNull(cache.getResponse(req));
+    HttpCacheKey key = new HttpCacheKey(req);
+    cache.addResponse(key, req, resp);
+    assertNull(cache.getResponse(key, req));
   }
 
   public void testCacheableForErr() {
     HttpRequest req = createRequest("GET");
     HttpResponse resp = createResponse(500, null, null);
-    cache.addResponse(req, resp);
-    assertEquals(resp, cache.getResponse(req));
+    HttpCacheKey key = new HttpCacheKey(req);
+    cache.addResponse(key, req, resp);
+    assertEquals(resp, cache.getResponse(key, req));
   }
 
   public void testCacheableForFutureExpires() {
     HttpRequest req = createRequest("GET");
     HttpResponse resp = createExpiresResponse(200,
         System.currentTimeMillis() + 10000L);
-    cache.addResponse(req, resp);
-    assertEquals(cache.getResponse(req), resp);
+    HttpCacheKey key = new HttpCacheKey(req);
+    cache.addResponse(key, req, resp);
+    assertEquals(cache.getResponse(key, req), resp);
   }
 
   public void testNotCacheableForPastExpires() {
     HttpRequest req = createRequest("GET");
     HttpResponse resp = createExpiresResponse(200,
         System.currentTimeMillis() - 10000L);
-    cache.addResponse(req, resp);
-    assertNull(cache.getResponse(req));
+    HttpCacheKey key = new HttpCacheKey(req);
+    cache.addResponse(key, req, resp);
+    assertNull(cache.getResponse(key, req));
   }
 
   public void testCacheableForFutureMaxAge() {
     HttpRequest req = createRequest("GET");
     HttpResponse resp = createMaxAgeResponse(200,
         10000L);
-    cache.addResponse(req, resp);
-    assertEquals(cache.getResponse(req), resp);
+    HttpCacheKey key = new HttpCacheKey(req);
+    cache.addResponse(key, req, resp);
+    assertEquals(cache.getResponse(key, req), resp);
   }
 
   public void testNotCacheableForNoCache() {
     HttpRequest req = createRequest("GET");
     HttpResponse resp = createResponse(200, "Cache-Control", "no-cache");
-    cache.addResponse(req, resp);
-    assertNull(cache.getResponse(req));
+    HttpCacheKey key = new HttpCacheKey(req);
+    cache.addResponse(key, req, resp);
+    assertNull(cache.getResponse(key, req));
   }
 
   public void testCacheableForExpiresWithWait() {
     HttpRequest req = createRequest("GET");
     HttpResponse resp = createExpiresResponse(200,
         System.currentTimeMillis() + 5000L);
-    cache.addResponse(req, resp);
+    HttpCacheKey key = new HttpCacheKey(req);
+    cache.addResponse(key, req, resp);
     try {
       synchronized (cache) {
         cache.wait(500L);
@@ -142,7 +152,7 @@
     } catch (InterruptedException ie) {
       fail("Failed to wait for cache");
     }
-    assertEquals(cache.getResponse(req), resp);
+    assertEquals(cache.getResponse(key, req), resp);
   }
 
 
@@ -150,7 +160,8 @@
     HttpRequest req = createRequest("GET");
     HttpResponse resp = createExpiresResponse(200,
         System.currentTimeMillis() + 1000L);
-    cache.addResponse(req, resp);
+    HttpCacheKey key = new HttpCacheKey(req);
+    cache.addResponse(key, req, resp);
     try {
       synchronized (cache) {
         cache.wait(1001L);
@@ -158,7 +169,7 @@
     } catch (InterruptedException ie) {
       fail("Failed to wait for cache");
     }
-    assertNull(cache.getResponse(req));
+    assertNull(cache.getResponse(key, req));
   }
 
   public void testCacheableWithForcedMinTTL() {
@@ -166,7 +177,8 @@
     // in seconds
     req.getOptions().minCacheTtl = 5;
     HttpResponse resp = createExpiresResponse(200, System.currentTimeMillis());
-    cache.addResponse(req, resp);
+    HttpCacheKey key = new HttpCacheKey(req);
+    cache.addResponse(key, req, resp);
     try {
       synchronized (cache) {
         cache.wait(2000L);
@@ -174,7 +186,7 @@
     } catch (InterruptedException ie) {
       fail("Failed to wait for cache");
     }
-    assertNotNull(cache.getResponse(req));
+    assertNotNull(cache.getResponse(key, req));
   }
 
 }

Added: 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/HttpCacheKeyTest.java
URL: 
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/HttpCacheKeyTest.java?rev=678253&view=auto
==============================================================================
--- 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/HttpCacheKeyTest.java
 (added)
+++ 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/HttpCacheKeyTest.java
 Sat Jul 19 23:47:35 2008
@@ -0,0 +1,105 @@
+/*
+ * 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
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+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 org.apache.shindig.gadgets.http.HttpRequest.Options;
+import org.json.JSONArray;
+import org.json.JSONObject;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.net.URI;
+
+public class HttpCacheKeyTest {
+
+  private URI target;
+
+  @Before
+  public void setUp() throws Exception {
+    target = new URI("http://www.example.com/";);
+  }
+  
+  @Test
+  public void testGet() throws Exception {
+    HttpRequest request = new HttpRequest(target);
+    HttpCacheKey key = new HttpCacheKey(request);
+    assertTrue(key.isCacheable());
+    assertEquals(
+        "[{\"method\":\"GET\"},{\"url\":\"http://www.example.com/\"}]";,
+        key.toString());
+  }
+  
+  @Test
+  public void testNonCacheableOptions() throws Exception {
+    Options options = new Options();
+    options.ignoreCache = true;
+    HttpRequest request = new HttpRequest(target, options);
+    HttpCacheKey key = new HttpCacheKey(request);
+    assertFalse(key.isCacheable());
+    assertEquals(
+        "[{\"method\":\"GET\"},{\"url\":\"http://www.example.com/\"}]";,
+        key.toString());
+  }
+  
+  @Test
+  public void testNonGet() throws Exception {
+    HttpRequest request = new HttpRequest("POST", target, null, null, null);
+    HttpCacheKey key = new HttpCacheKey(request);
+    assertFalse(key.isCacheable());
+    assertEquals(
+        "[{\"method\":\"POST\"},{\"url\":\"http://www.example.com/\"}]";,
+        key.toString());
+  }
+  
+  @Test
+  public void testOrdered() {
+    HttpCacheKey key = new HttpCacheKey(new HttpRequest(target));
+    key.set("c", "c");
+    key.set("b", "b");
+    key.set("g", "g");
+    key.set("d", "d");
+    key.set("e", "e");
+    key.set("f", "f");
+    key.set("g", "g");
+    key.set("a", "a");
+    assertEquals(
+        "[{\"a\":\"a\"},{\"b\":\"b\"},{\"c\":\"c\"},{\"d\":\"d\"}," +
+       "{\"e\":\"e\"},{\"f\":\"f\"},{\"g\":\"g\"},{\"method\":\"GET\"}" +
+       ",{\"url\":\"http://www.example.com/\"}]";,
+       key.toString());
+  }
+  
+  @Test
+  public void testWeirdChars() throws Exception {
+    final int CHARS_TO_TEST = 2000;
+    HttpCacheKey key = new HttpCacheKey(new HttpRequest(target));
+    for (char c = 0; c <= CHARS_TO_TEST; ++c) {
+      key.set(Character.toString(c), Character.toString(c));
+    }
+    key.remove("url");
+    key.remove("method");
+
+    String out = key.toString();
+    JSONArray array = new JSONArray(out);
+    for (char c = 0; c <= CHARS_TO_TEST; ++c) {
+      JSONObject o = array.getJSONObject(c);
+      String s = Character.toString(c);
+      assertEquals(s, o.get(s));
+    }
+  }
+}

Modified: 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/HttpRequestTest.java
URL: 
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/HttpRequestTest.java?rev=678253&r1=678252&r2=678253&view=diff
==============================================================================
--- 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/HttpRequestTest.java
 (original)
+++ 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/HttpRequestTest.java
 Sat Jul 19 23:47:35 2008
@@ -57,4 +57,13 @@
         = new HttpRequest(DEFAULT_URI, headers);
     assertEquals(TEST_HEADER_VALUE, request.getHeader(TEST_HEADER_KEY));
   }
+  
+  public void testDefaultOptionsSafelyMutable() throws Exception {
+    HttpRequest request = new HttpRequest(DEFAULT_URI);
+    assertFalse(request.getOptions().ignoreCache);
+    request.getOptions().ignoreCache = true;
+    
+    request = new HttpRequest(DEFAULT_URI);
+    assertFalse(request.getOptions().ignoreCache);
+  }
 }


Reply via email to