Reviewers: shindig.remailer_gmail.com,

Description:
Support a fallback_url parameter in the content proxy. This URL is
fetched when the original target URL returns an error (HTTP >= 400).

This is of particular value with the image proxy: fallback_url can be
set to a valid known image to avoid broken images showing up.

Includes tweaks and a fix verified in integration test.

Please review this at http://codereview.appspot.com/130055

Affected files:
java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/ProxyHandler.java java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/ProxyHandlerTest.java


Index: java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/ProxyHandlerTest.java
===================================================================
--- java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/ProxyHandlerTest.java (revision 820902) +++ java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/ProxyHandlerTest.java (working copy)
@@ -20,6 +20,7 @@

 import static org.easymock.EasyMock.capture;
 import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.isA;

 import com.google.common.collect.Maps;

@@ -145,7 +146,30 @@
     assertEquals(magicGarbage, recorder.getHeader("X-Magic-Garbage"));
     assertTrue(rewriter.responseWasRewritten());
   }
+
+  public void testGetFallback() throws Exception {
+    String url = "http://example.org/file.evil";;
+    String domain = "example.org";
+    String fallback_url = "http://fallback.com/fallback.png";;

+ expect(lockedDomainService.isSafeForOpenProxy(domain)).andReturn(true).atLeastOnce();
+    setupProxyRequestMock(domain, url);
+ expect(request.getParameter(ProxyBase.IGNORE_CACHE_PARAM)).andReturn("1").atLeastOnce(); + expect(request.getParameter(ProxyHandler.FALLBACK_URL_PARAM)).andReturn(fallback_url).atLeastOnce();
+
+    HttpRequest req = new HttpRequest(Uri.parse(url)).setIgnoreCache(true);
+    HttpResponse resp = HttpResponse.error();
+    HttpResponse fallback_resp = new HttpResponse("Fallback");
+    expect(pipeline.execute(req)).andReturn(resp);
+ expect(pipeline.execute(isA(HttpRequest.class))).andReturn(fallback_resp);
+
+    replay();
+
+    proxyHandler.fetch(request, recorder);
+
+    verify();
+  }
+
   public void testNoCache() throws Exception {
     String url = "http://example.org/file.evil";;
     String domain = "example.org";
Index: java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/ProxyHandler.java
===================================================================
--- java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/ProxyHandler.java (revision 822533) +++ java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/ProxyHandler.java (working copy)
@@ -55,6 +55,8 @@
   private static final String[] INTEGER_RESIZE_PARAMS = new String[] {
PARAM_RESIZE_HEIGHT, PARAM_RESIZE_WIDTH, PARAM_RESIZE_QUALITY, PARAM_NO_EXPAND
   };
+
+  static final String FALLBACK_URL_PARAM = "fallback_url";

   private final RequestPipeline requestPipeline;
   private final LockedDomainService lockedDomainService;
@@ -72,8 +74,13 @@
   /**
* Generate a remote content request based on the parameters sent from the client.
    */
- private HttpRequest buildHttpRequest(HttpServletRequest request) throws GadgetException {
-    Uri url = validateUrl(request.getParameter(URL_PARAM));
+ private HttpRequest buildHttpRequest(HttpServletRequest request, String urlParam)
+      throws GadgetException {
+    String theUrl = request.getParameter(urlParam);
+    if (theUrl == null) {
+      return null;
+    }
+    Uri url = validateUrl(theUrl);

     HttpRequest req = new HttpRequest(url)
         .setContainer(getContainer(request));
@@ -135,8 +142,17 @@
throw new GadgetException(GadgetException.Code.INVALID_PARAMETER, msg);
     }

-    HttpRequest rcr = buildHttpRequest(request);
+    HttpRequest rcr = buildHttpRequest(request, URL_PARAM);
     HttpResponse results = requestPipeline.execute(rcr);
+
+    if (results.isError()) {
+      // Error: try the fallback. Particularly useful for proxied images.
+ HttpRequest fallbackRcr = buildHttpRequest(request, FALLBACK_URL_PARAM);
+      if (fallbackRcr != null) {
+        results = requestPipeline.execute(fallbackRcr);
+      }
+    }
+
     if (contentRewriterRegistry != null) {
       try {
results = contentRewriterRegistry.rewriteHttpResponse(rcr, results);


Reply via email to