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);
+ }
}