Author: johnh
Date: Thu Mar 11 02:32:35 2010
New Revision: 921668
URL: http://svn.apache.org/viewvc?rev=921668&view=rev
Log:
Adds MD5 as metadata to each HttpResponse, setting up its use in Proxy and
Concat Versioners.
Patch provided by Ziv Horesh. Description:
""
This feature will be used by the Uri rewritters to create versions for
resources.
The request pipeline calculates the md5 for each response and store it in the
HttpResponse metadata map.
The added class HttpResponseMetadataHelper will support updating the metadata
for other values, such as image dimensions to supoprt img link rewritter (will
be done if next CL).
""
Added:
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpResponseMetadataHelper.java
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/HttpResponseMetadataHelperTest.java
Modified:
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/DefaultRequestPipeline.java
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/DefaultInvalidationServiceTest.java
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/DefaultRequestPipelineTest.java
Modified:
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/DefaultRequestPipeline.java
URL:
http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/DefaultRequestPipeline.java?rev=921668&r1=921667&r2=921668&view=diff
==============================================================================
---
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/DefaultRequestPipeline.java
(original)
+++
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/DefaultRequestPipeline.java
Thu Mar 11 02:32:35 2010
@@ -20,6 +20,7 @@ package org.apache.shindig.gadgets.http;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
+import com.google.inject.internal.Nullable;
import org.apache.shindig.common.util.Utf8UrlCoder;
import org.apache.shindig.gadgets.GadgetException;
@@ -37,18 +38,21 @@ public class DefaultRequestPipeline impl
private final Provider<OAuthRequest> oauthRequestProvider;
private final ImageRewriter imageRewriter;
private final InvalidationService invalidationService;
+ private final HttpResponseMetadataHelper metadataHelper;
@Inject
public DefaultRequestPipeline(HttpFetcher httpFetcher,
HttpCache httpCache,
Provider<OAuthRequest> oauthRequestProvider,
ImageRewriter imageRewriter,
- InvalidationService invalidationService) {
+ InvalidationService invalidationService,
+ @Nullable HttpResponseMetadataHelper
metadataHelper) {
this.httpFetcher = httpFetcher;
this.httpCache = httpCache;
this.oauthRequestProvider = oauthRequestProvider;
this.imageRewriter = imageRewriter;
this.invalidationService = invalidationService;
+ this.metadataHelper = metadataHelper;
}
public HttpResponse execute(HttpRequest request) throws GadgetException {
@@ -104,7 +108,8 @@ public class DefaultRequestPipeline impl
if (!fetchedResponse.isError() && !request.getIgnoreCache() &&
request.getCacheTtl() != 0) {
fetchedResponse = imageRewriter.rewrite(request, fetchedResponse);
}
-
+ // Set response hash value in metadata (used for url versioning)
+ fetchedResponse = HttpResponseMetadataHelper.updateHash(fetchedResponse,
metadataHelper);
if (!request.getIgnoreCache() ) {
// Mark the response with invalidation information prior to caching
if (fetchedResponse.getCacheTtl() > 0) {
Added:
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpResponseMetadataHelper.java
URL:
http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpResponseMetadataHelper.java?rev=921668&view=auto
==============================================================================
---
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpResponseMetadataHelper.java
(added)
+++
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/http/HttpResponseMetadataHelper.java
Thu Mar 11 02:32:35 2010
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+
+import org.apache.shindig.common.util.Base32;
+
+import java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Map;
+import java.util.logging.Logger;
+
+/**
+ * Helper class to update HttpResponse metadata value.
+ */
+public class HttpResponseMetadataHelper {
+ public static final String DATA_HASH = "DataHash";
+ public static final String IMAGE_HEIGHT = "ImageHeight";
+ public static final String IMAGE_WIDTH = "ImageWidth";
+
+ private static final Logger log =
+ Logger.getLogger(HttpResponseMetadataHelper.class.getName());
+
+ /**
+ * Return a copy of input response with additional metadata values.
+ * @param response source response
+ * @param values added metadata values
+ * @return copy of source response with updated metadata
+ */
+ public static HttpResponse updateMetadata(HttpResponse response, Map<String,
String> values) {
+ Map<String, String> metadata = Maps.newHashMap(response.getMetadata());
+ // metadata.putAll(values);
+ for (Map.Entry<String, String> val : values.entrySet()) {
+ metadata.put(val.getKey(), val.getValue());
+ }
+ return new HttpResponseBuilder(response).setMetadata(metadata).create();
+ }
+
+ /**
+ * Calculate hash value for response and update metadata value (DATA_HASH)
+ * @return hash value
+ */
+ public String getHash(HttpResponse response) {
+ try {
+ MessageDigest md5 = MessageDigest.getInstance("MD5");
+ md5.update(response.getResponseAsBytes());
+ byte[] md5val = md5.digest();
+ return new String(Base32.encodeBase32(md5val), "UTF-8");
+ } catch (NoSuchAlgorithmException e) {
+ // Should not happen
+ log.info("Error getting MD5 digest, ignored");
+ } catch (UnsupportedEncodingException e) {
+ // Should not happen
+ log.info("Error parsing MD5 string as UTF8");
+ }
+ return null;
+ }
+
+ public static HttpResponse updateHash(HttpResponse response,
HttpResponseMetadataHelper helper) {
+ if (helper != null) {
+ String hash = helper.getHash(response);
+ if (hash != null) {
+ return updateMetadata(response, ImmutableMap.<String,
String>of(DATA_HASH, hash));
+ }
+ }
+ return response;
+ }
+}
Modified:
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/DefaultInvalidationServiceTest.java
URL:
http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/DefaultInvalidationServiceTest.java?rev=921668&r1=921667&r2=921668&view=diff
==============================================================================
---
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/DefaultInvalidationServiceTest.java
(original)
+++
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/DefaultInvalidationServiceTest.java
Thu Mar 11 02:32:35 2010
@@ -17,15 +17,14 @@
*/
package org.apache.shindig.gadgets.http;
+import com.google.common.collect.ImmutableSet;
+
import org.apache.shindig.common.cache.LruCacheProvider;
import org.apache.shindig.common.testing.FakeGadgetToken;
import org.apache.shindig.common.uri.Uri;
import org.apache.shindig.gadgets.AuthType;
import org.apache.shindig.gadgets.oauth.OAuthArguments;
import org.apache.shindig.gadgets.rewrite.image.NoOpImageRewriter;
-
-import com.google.common.collect.ImmutableSet;
-
import org.easymock.EasyMock;
import org.easymock.IMocksControl;
import org.junit.Assert;
@@ -82,7 +81,7 @@ public class DefaultInvalidationServiceT
fetcher = new DefaultRequestPipelineTest.FakeHttpFetcher();
oauth = new DefaultRequestPipelineTest.FakeOAuthRequestProvider();
requestPipeline = new DefaultRequestPipeline(fetcher, cache, oauth, new
NoOpImageRewriter(),
- service);
+ service, new HttpResponseMetadataHelper());
}
@Test
Modified:
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/DefaultRequestPipelineTest.java
URL:
http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/DefaultRequestPipelineTest.java?rev=921668&r1=921667&r2=921668&view=diff
==============================================================================
---
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/DefaultRequestPipelineTest.java
(original)
+++
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/DefaultRequestPipelineTest.java
Thu Mar 11 02:32:35 2010
@@ -38,8 +38,14 @@ public class DefaultRequestPipelineTest
private final FakeHttpCache cache = new FakeHttpCache();
private final FakeOAuthRequestProvider oauth = new
FakeOAuthRequestProvider();
+ private final HttpResponseMetadataHelper helper = new
HttpResponseMetadataHelper() {
+ @Override
+ public String getHash(HttpResponse resp) {
+ return resp.getResponseAsString();
+ }
+ };
private final RequestPipeline pipeline = new DefaultRequestPipeline(fetcher,
cache, oauth,
- new NoOpImageRewriter(), new NoOpInvalidationService());
+ new NoOpImageRewriter(), new NoOpInvalidationService(), helper);
@Test
public void authTypeNoneNotCached() throws Exception {
@@ -56,6 +62,25 @@ public class DefaultRequestPipelineTest
assertEquals(1, cache.readCount);
assertEquals(1, cache.writeCount);
assertEquals(1, fetcher.fetchCount);
+ assertEquals(1, response.getMetadata().size());
+ assertEquals("response",
+ response.getMetadata().get(HttpResponseMetadataHelper.DATA_HASH));
+ }
+
+ @Test
+ public void verifyHashCode() throws Exception {
+ HttpRequest request = new HttpRequest(DEFAULT_URI)
+ .setAuthType(AuthType.NONE);
+
+ fetcher.response = new HttpResponse("response");
+
+ RequestPipeline pipeline = new DefaultRequestPipeline(fetcher, cache,
oauth,
+ new NoOpImageRewriter(), new NoOpInvalidationService(),
+ new HttpResponseMetadataHelper());
+ HttpResponse response = pipeline.execute(request);
+ assertEquals(1, response.getMetadata().size());
+ assertEquals("q7u8tbpmidtu1gtqhjv0kb0rvo",
+ response.getMetadata().get(HttpResponseMetadataHelper.DATA_HASH));
}
@Test
@@ -93,6 +118,10 @@ public class DefaultRequestPipelineTest
assertEquals(1, cache.readCount);
assertEquals(1, cache.writeCount);
assertEquals(1, fetcher.fetchCount);
+ assertEquals(1, response.getMetadata().size());
+ assertEquals("fetched",
+ response.getMetadata().get(HttpResponseMetadataHelper.DATA_HASH));
+
}
@Test
Added:
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/HttpResponseMetadataHelperTest.java
URL:
http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/HttpResponseMetadataHelperTest.java?rev=921668&view=auto
==============================================================================
---
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/HttpResponseMetadataHelperTest.java
(added)
+++
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/http/HttpResponseMetadataHelperTest.java
Thu Mar 11 02:32:35 2010
@@ -0,0 +1,88 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 com.google.common.collect.ImmutableMap;
+
+import org.junit.Test;
+
+public class HttpResponseMetadataHelperTest {
+
+ @Test
+ public void testUpdateMetadata() {
+ HttpResponse local = new HttpResponseBuilder()
+ .setResponseString("data1")
+ .create();
+
+ HttpResponse compiled = HttpResponseMetadataHelper.updateMetadata(local,
+ ImmutableMap.<String, String>of("K", "V"));
+ assertEquals(1, compiled.getMetadata().size());
+ assertEquals("V", compiled.getMetadata().get("K"));
+
+ HttpResponse compiled2 =
HttpResponseMetadataHelper.updateMetadata(compiled,
+ ImmutableMap.<String, String>of("K2", "V2"));
+ assertEquals(2, compiled2.getMetadata().size());
+ assertEquals("V2", compiled2.getMetadata().get("K2"));
+
+ HttpResponse compiled3 =
HttpResponseMetadataHelper.updateMetadata(compiled2,
+ ImmutableMap.<String, String>of("K", "V3"));
+ assertEquals(2, compiled3.getMetadata().size());
+ assertEquals("V3", compiled3.getMetadata().get("K"));
+ }
+
+ @Test
+ public void testHashCodeSimple() {
+ HttpResponse local = new HttpResponseBuilder()
+ .setResponseString("data1")
+ .create();
+ verifyHash(local, 1, "h7cg7f1lrrf74jul5h8k6vvlvk");
+ }
+
+ @Test
+ public void testHashCodeExtraMeta() {
+ HttpResponse local = new HttpResponseBuilder()
+ .setResponseString("data1")
+ .setMetadata(ImmutableMap.<String, String>of("K","V"))
+ .setHeader("X-data", "no data")
+ .create();
+ verifyHash(local, 2, "h7cg7f1lrrf74jul5h8k6vvlvk");
+ }
+
+ @Test
+ public void testHashCodeError() {
+ verifyHash(HttpResponse.error(), 1, "qgeopmcf02p09qc016cepu22fo");
+ }
+
+ @Test
+ public void testHashCodeEmpty() {
+ HttpResponse local = new HttpResponseBuilder()
+ .setHttpStatusCode(200)
+ .create();
+ verifyHash(local, 1, "qgeopmcf02p09qc016cepu22fo");
+ }
+
+ private void verifyHash(HttpResponse resp, int metadataSize, String hash) {
+ HttpResponseMetadataHelper metdataHelper = new
HttpResponseMetadataHelper();
+ HttpResponse compiled = HttpResponseMetadataHelper.updateHash(resp,
metdataHelper);
+ assertEquals(metadataSize, compiled.getMetadata().size());
+ assertEquals(hash,
compiled.getMetadata().get(HttpResponseMetadataHelper.DATA_HASH));
+ }
+
+}