You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@shindig.apache.org by li...@apache.org on 2010/05/08 00:51:17 UTC

svn commit: r942261 - in /shindig/trunk: ./ config/ java/common/src/main/java/org/apache/shindig/common/servlet/ java/common/src/main/java/org/apache/shindig/config/ java/common/src/main/java/org/apache/shindig/protocol/ java/common/src/test/java/org/a...

Author: lindner
Date: Fri May  7 22:51:16 2010
New Revision: 942261

URL: http://svn.apache.org/viewvc?rev=942261&view=rev
Log:
Support Cross-Origin-Request-Sharing on the server side

Modified:
    shindig/trunk/UPGRADING
    shindig/trunk/config/container.js
    shindig/trunk/java/common/src/main/java/org/apache/shindig/common/servlet/HttpUtil.java
    shindig/trunk/java/common/src/main/java/org/apache/shindig/config/AbstractContainerConfig.java
    shindig/trunk/java/common/src/main/java/org/apache/shindig/config/ContainerConfig.java
    shindig/trunk/java/common/src/main/java/org/apache/shindig/protocol/ApiServlet.java
    shindig/trunk/java/common/src/main/java/org/apache/shindig/protocol/DataServiceServlet.java
    shindig/trunk/java/common/src/main/java/org/apache/shindig/protocol/JsonRpcServlet.java
    shindig/trunk/java/common/src/test/java/org/apache/shindig/common/servlet/HttpUtilTest.java
    shindig/trunk/java/common/src/test/java/org/apache/shindig/protocol/DataServiceServletTest.java
    shindig/trunk/java/common/src/test/java/org/apache/shindig/protocol/JsonRpcServletTest.java
    shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/RpcServletTest.java
    shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/dataservice/integration/AbstractLargeRestfulTests.java

Modified: shindig/trunk/UPGRADING
URL: http://svn.apache.org/viewvc/shindig/trunk/UPGRADING?rev=942261&r1=942260&r2=942261&view=diff
==============================================================================
--- shindig/trunk/UPGRADING (original)
+++ shindig/trunk/UPGRADING Fri May  7 22:51:16 2010
@@ -4,9 +4,19 @@ FROM 1.0.x TO 1.1.x
 Almost all interfaces have been updated from 1.0.x -> 1.1.x.  The 
 following information is not complete.
 
+== container.js config changes ==
+
+* gadgets.parentOrigins: Default ["*"]
+
+An array of valid origin domains for the container.
 
 == Java Interface Changes ==
 
+* AbstractContainerConfig
+
+Changed signature on getMap() and getList() to use Java
+generics.
+
 * SecurityTokenDecoder 
 
 The interface and implementation are replaced
@@ -15,6 +25,7 @@ with the new SecurityTokenCodec interfac
 You will need to adjust any custom SecurityToken decoders to 
 encode tokens as well as decode them.
 
+
 == Java Guice Changes ==
 
 1.1.x uses Guice 2.0 which allows for @Provides annotations and much more.

Modified: shindig/trunk/config/container.js
URL: http://svn.apache.org/viewvc/shindig/trunk/config/container.js?rev=942261&r1=942260&r2=942261&view=diff
==============================================================================
--- shindig/trunk/config/container.js (original)
+++ shindig/trunk/config/container.js Fri May  7 22:51:16 2010
@@ -60,6 +60,10 @@
 // DNS domain on which gadgets should render.
 "gadgets.lockedDomainSuffix" : "-a.example.com:8080",
 
+// Origins for CORS requests and/or Referer validation
+// Indicate a set of origins or an entry with * to indicate that all origins are allowed
+"gadgets.parentOrigins" : ["*"],
+
 // Various urls generated throughout the code base.
 // iframeBaseUri will automatically have the host inserted
 // if locked domain is enabled and the implementation supports it.

Modified: shindig/trunk/java/common/src/main/java/org/apache/shindig/common/servlet/HttpUtil.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/common/src/main/java/org/apache/shindig/common/servlet/HttpUtil.java?rev=942261&r1=942260&r2=942261&view=diff
==============================================================================
--- shindig/trunk/java/common/src/main/java/org/apache/shindig/common/servlet/HttpUtil.java (original)
+++ shindig/trunk/java/common/src/main/java/org/apache/shindig/common/servlet/HttpUtil.java Fri May  7 22:51:16 2010
@@ -18,10 +18,12 @@
  */
 package org.apache.shindig.common.servlet;
 
+import org.apache.commons.lang.StringUtils;
 import org.apache.shindig.common.util.TimeSource;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import java.util.Collection;
 import java.util.regex.Pattern;
 
 /**
@@ -129,4 +131,22 @@ public class HttpUtil {
     }
     return true;
   }
+
+
+  public static final String ACCESS_CONTROL_ALLOW_ORIGIN_HEADER = "Access-Control-Allow-Origin";
+
+  /**
+   * Set the header for Cross-Site Resource Sharing.
+   * @param resp HttpServletResponse to modify
+   * @param validOrigins a space separated list of Origins as defined by the html5 spec
+   * @see http://dev.w3.org/html5/spec/browsers.html#origin-0
+   */
+  public static void setCORSheader(HttpServletResponse resp, Collection<String> validOrigins) {
+    if (validOrigins == null) {
+      return;
+    }
+    for (String origin : validOrigins) {
+      resp.addHeader(ACCESS_CONTROL_ALLOW_ORIGIN_HEADER, origin);
+    }
+  }
 }
\ No newline at end of file

Modified: shindig/trunk/java/common/src/main/java/org/apache/shindig/config/AbstractContainerConfig.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/common/src/main/java/org/apache/shindig/config/AbstractContainerConfig.java?rev=942261&r1=942260&r2=942261&view=diff
==============================================================================
--- shindig/trunk/java/common/src/main/java/org/apache/shindig/config/AbstractContainerConfig.java (original)
+++ shindig/trunk/java/common/src/main/java/org/apache/shindig/config/AbstractContainerConfig.java Fri May  7 22:51:16 2010
@@ -53,19 +53,19 @@ public abstract class AbstractContainerC
   }
 
   @SuppressWarnings("unchecked")
-  public List<Object> getList(String container, String property) {
+  public <T> List<T> getList(String container, String property) {
     Object value = getProperty(container, property);
     if (value instanceof List) {
-      return (List<Object>) value;
+      return (List<T>) value;
     }
     return Collections.emptyList();
   }
 
   @SuppressWarnings("unchecked")
-  public Map<String, Object> getMap(String container, String property) {
+  public <T> Map<String, T> getMap(String container, String property) {
     Object value = getProperty(container, property);
     if (value instanceof Map) {
-      return (Map<String, Object>) value;
+      return (Map<String, T>) value;
     }
     return Collections.emptyMap();
   }

Modified: shindig/trunk/java/common/src/main/java/org/apache/shindig/config/ContainerConfig.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/common/src/main/java/org/apache/shindig/config/ContainerConfig.java?rev=942261&r1=942260&r2=942261&view=diff
==============================================================================
--- shindig/trunk/java/common/src/main/java/org/apache/shindig/config/ContainerConfig.java (original)
+++ shindig/trunk/java/common/src/main/java/org/apache/shindig/config/ContainerConfig.java Fri May  7 22:51:16 2010
@@ -79,11 +79,11 @@ public interface ContainerConfig {
    * @return The configuration property stored under the given name for the given container, or an
    * empty list if it is not defined or not a list.
    */
-  List<Object> getList(String container, String name);
+  <T> List<T> getList(String container, String name);
 
   /**
    * @return The configuration property stored under the given name for the given container, or an
    * empty map if it is not defined or not a map.
    */
-  Map<String, Object> getMap(String container, String name);
+  <T> Map<String, T> getMap(String container, String name);
 }

Modified: shindig/trunk/java/common/src/main/java/org/apache/shindig/protocol/ApiServlet.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/common/src/main/java/org/apache/shindig/protocol/ApiServlet.java?rev=942261&r1=942260&r2=942261&view=diff
==============================================================================
--- shindig/trunk/java/common/src/main/java/org/apache/shindig/protocol/ApiServlet.java (original)
+++ shindig/trunk/java/common/src/main/java/org/apache/shindig/protocol/ApiServlet.java Fri May  7 22:51:16 2010
@@ -17,9 +17,11 @@
  */
 package org.apache.shindig.protocol;
 
+import com.google.inject.Provider;
 import org.apache.shindig.auth.AuthInfo;
 import org.apache.shindig.auth.SecurityToken;
 import org.apache.shindig.common.servlet.InjectedServlet;
+import org.apache.shindig.config.ContainerConfig;
 import org.apache.shindig.protocol.conversion.BeanConverter;
 import org.apache.shindig.protocol.conversion.BeanJsonConverter;
 
@@ -93,6 +95,14 @@ public abstract class ApiServlet extends
     this.dispatcher = dispatcher;
   }
 
+  protected ContainerConfig containerConfig;
+
+  @Inject
+  public void setContainerConfig(ContainerConfig containerConfig) {
+    this.containerConfig = containerConfig;
+  }
+
+
   @Inject(optional = true)
   public void setDisallowUnknownContentTypes(
       @Named("shindig.api.disallow-unknown-content-types") boolean disallowUnknownContentTypes) {

Modified: shindig/trunk/java/common/src/main/java/org/apache/shindig/protocol/DataServiceServlet.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/common/src/main/java/org/apache/shindig/protocol/DataServiceServlet.java?rev=942261&r1=942260&r2=942261&view=diff
==============================================================================
--- shindig/trunk/java/common/src/main/java/org/apache/shindig/protocol/DataServiceServlet.java (original)
+++ shindig/trunk/java/common/src/main/java/org/apache/shindig/protocol/DataServiceServlet.java Fri May  7 22:51:16 2010
@@ -17,7 +17,11 @@
  */
 package org.apache.shindig.protocol;
 
+import com.google.inject.Inject;
+import com.google.inject.Provider;
 import org.apache.shindig.auth.SecurityToken;
+import org.apache.shindig.common.servlet.HttpUtil;
+import org.apache.shindig.config.ContainerConfig;
 import org.apache.shindig.protocol.conversion.BeanConverter;
 
 import com.google.common.collect.ImmutableMap;
@@ -103,6 +107,8 @@ public class DataServiceServlet extends 
       return;
     }
 
+    HttpUtil.setCORSheader(servletResponse, containerConfig.<String>getList(token.getContainer(), "gadgets.parentOrigins"));
+
     BeanConverter converter = getConverterForRequest(servletRequest);
 
     handleSingleRequest(servletRequest, servletResponse, token, converter);
@@ -169,7 +175,13 @@ public class DataServiceServlet extends 
         response = ImmutableMap.of("entry", response);
       }
 
+      // JSONP style callbacks
+      String callback =  (HttpUtil.isJSONP(servletRequest) && ContentTypes.OUTPUT_JSON_CONTENT_TYPE.equals(converter.getContentType())) ?
+          servletRequest.getParameter("callback") : null;
+
+      if (callback != null) writer.write(callback + "(");
       writer.write(converter.convertToString(response));
+      if (callback != null) writer.write(");\n");
     } else {
       sendError(servletResponse, responseItem);
     }

Modified: shindig/trunk/java/common/src/main/java/org/apache/shindig/protocol/JsonRpcServlet.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/common/src/main/java/org/apache/shindig/protocol/JsonRpcServlet.java?rev=942261&r1=942260&r2=942261&view=diff
==============================================================================
--- shindig/trunk/java/common/src/main/java/org/apache/shindig/protocol/JsonRpcServlet.java (original)
+++ shindig/trunk/java/common/src/main/java/org/apache/shindig/protocol/JsonRpcServlet.java Fri May  7 22:51:16 2010
@@ -89,6 +89,7 @@ public class JsonRpcServlet extends ApiS
       return;
     }
 
+    HttpUtil.setCORSheader(servletResponse, containerConfig.<String>getList(token.getContainer(), "gadgets.parentOrigins"));
 
     try {
       String content = null;
@@ -123,6 +124,7 @@ public class JsonRpcServlet extends ApiS
         JSONObject request = new JSONObject(content);
         dispatch(request, formData, servletRequest, servletResponse, token, callback);
       }
+      return;
     } catch (JSONException je) {
       sendJsonParseError(je, servletResponse);
     } catch (IllegalArgumentException e) {
@@ -189,7 +191,7 @@ public class JsonRpcServlet extends ApiS
 
     // Generate the output
     Writer writer = servletResponse.getWriter();
-    if (callback != null) writer.append(callback).append('(');
+    if (callback != null) writer.append(callback+'(');
     jsonConverter.append(writer, result);
     if (callback != null) writer.append(");\n");
   }
@@ -213,7 +215,7 @@ public class JsonRpcServlet extends ApiS
 
     // Generate the output
     Writer writer = servletResponse.getWriter();
-    if (callback != null) writer.append(callback).append('(');
+    if (callback != null) writer.append(callback+'(');
     jsonConverter.append(writer, result);
     if (callback != null) writer.append(");\n");
   }

Modified: shindig/trunk/java/common/src/test/java/org/apache/shindig/common/servlet/HttpUtilTest.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/common/src/test/java/org/apache/shindig/common/servlet/HttpUtilTest.java?rev=942261&r1=942260&r2=942261&view=diff
==============================================================================
--- shindig/trunk/java/common/src/test/java/org/apache/shindig/common/servlet/HttpUtilTest.java (original)
+++ shindig/trunk/java/common/src/test/java/org/apache/shindig/common/servlet/HttpUtilTest.java Fri May  7 22:51:16 2010
@@ -28,9 +28,11 @@ import org.apache.shindig.common.servlet
 import org.apache.shindig.common.util.DateUtil;
 import org.apache.shindig.common.util.FakeTimeSource;
 import org.easymock.classextension.EasyMock;
+import org.junit.Ignore;
 import org.junit.Test;
 
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 
 import javax.servlet.http.HttpServletResponse;
@@ -91,7 +93,26 @@ public class HttpUtilTest {
     HttpUtil.setNoCache(recorder);
     checkCacheControlHeaders(testStartTime, recorder, 0, true);
   }
-  
+
+  @Test
+  public void testCORSstar() {
+    HttpUtil.setCORSheader(recorder, Collections.singleton("*"));
+    assertEquals(recorder.getHeader(HttpUtil.ACCESS_CONTROL_ALLOW_ORIGIN_HEADER), "*");
+  }
+
+  @Test
+  public void testCORSnull() {
+     HttpUtil.setCORSheader(recorder, null);
+     assertEquals(recorder.getHeader(HttpUtil.ACCESS_CONTROL_ALLOW_ORIGIN_HEADER), null);
+   }
+
+   @Test
+   @Ignore("HttpServletResponseRecorder doesn't support multiple headers")
+   public void testCORSmultiple() {
+     HttpUtil.setCORSheader(recorder, Arrays.asList("http://foo.example.com", "http://bar.example.com"));
+     // TODO fix HttpServletResponseRecorder and add multi-header test here
+   }
+
   public static void checkCacheControlHeaders(long testStartTime,
       HttpServletResponseRecorder response, int ttl, boolean noProxy) {
 

Modified: shindig/trunk/java/common/src/test/java/org/apache/shindig/protocol/DataServiceServletTest.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/common/src/test/java/org/apache/shindig/protocol/DataServiceServletTest.java?rev=942261&r1=942260&r2=942261&view=diff
==============================================================================
--- shindig/trunk/java/common/src/test/java/org/apache/shindig/protocol/DataServiceServletTest.java (original)
+++ shindig/trunk/java/common/src/test/java/org/apache/shindig/protocol/DataServiceServletTest.java Fri May  7 22:51:16 2010
@@ -27,6 +27,7 @@ import org.apache.commons.lang.StringUti
 import org.apache.shindig.auth.AuthInfo;
 import org.apache.shindig.common.testing.FakeGadgetToken;
 import org.apache.shindig.common.testing.FakeHttpServletRequest;
+import org.apache.shindig.config.ContainerConfig;
 import org.apache.shindig.protocol.conversion.BeanConverter;
 import org.apache.shindig.protocol.conversion.BeanJsonConverter;
 import org.easymock.IMocksControl;
@@ -49,7 +50,7 @@ public class DataServiceServletTest exte
   private BeanJsonConverter jsonConverter;
   private BeanConverter xmlConverter;
   private BeanConverter atomConverter;
-
+  private ContainerConfig containerConfig;
 
   private IMocksControl mockControl = EasyMock.createNiceControl();
 
@@ -61,6 +62,7 @@ public class DataServiceServletTest exte
     jsonConverter = mockControl.createMock(BeanJsonConverter.class);
     xmlConverter = mockControl.createMock(BeanConverter.class);
     atomConverter = mockControl.createMock(BeanConverter.class);
+    containerConfig = mockControl.createMock(ContainerConfig.class);
 
     EasyMock.expect(jsonConverter.getContentType()).andReturn(
         ContentTypes.OUTPUT_JSON_CONTENT_TYPE).anyTimes();
@@ -68,12 +70,13 @@ public class DataServiceServletTest exte
         ContentTypes.OUTPUT_XML_CONTENT_TYPE).anyTimes();
     EasyMock.expect(atomConverter.getContentType()).andReturn(
         ContentTypes.OUTPUT_ATOM_CONTENT_TYPE).anyTimes();
-
+    
     HandlerRegistry registry = new DefaultHandlerRegistry(null, jsonConverter,
         new HandlerExecutionListener.NoOpHandler());
     registry.addHandlers(Sets.<Object>newHashSet(new TestHandler()));
 
     servlet.setHandlerRegistry(registry);
+    servlet.setContainerConfig(containerConfig);
 
     servlet.setBeanConverters(jsonConverter, xmlConverter, atomConverter);
   }

Modified: shindig/trunk/java/common/src/test/java/org/apache/shindig/protocol/JsonRpcServletTest.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/common/src/test/java/org/apache/shindig/protocol/JsonRpcServletTest.java?rev=942261&r1=942260&r2=942261&view=diff
==============================================================================
--- shindig/trunk/java/common/src/test/java/org/apache/shindig/protocol/JsonRpcServletTest.java (original)
+++ shindig/trunk/java/common/src/test/java/org/apache/shindig/protocol/JsonRpcServletTest.java Fri May  7 22:51:16 2010
@@ -24,6 +24,7 @@ import static org.easymock.classextensio
 
 import org.apache.shindig.common.JsonAssert;
 import org.apache.shindig.common.testing.FakeGadgetToken;
+import org.apache.shindig.config.ContainerConfig;
 import org.apache.shindig.protocol.conversion.BeanJsonConverter;
 import org.apache.shindig.protocol.multipart.FormDataItem;
 import org.apache.shindig.protocol.multipart.MultipartFormParser;
@@ -66,6 +67,7 @@ public class JsonRpcServletTest extends 
   private HttpServletResponse res;
   private JsonRpcServlet servlet;
   private MultipartFormParser multipartFormParser;
+  private ContainerConfig containerConfig;
 
   private final IMocksControl mockControl = EasyMock.createNiceControl();
 
@@ -78,6 +80,7 @@ public class JsonRpcServletTest extends 
     servlet = new JsonRpcServlet();
     req = mockControl.createMock(HttpServletRequest.class);
     res = mockControl.createMock(HttpServletResponse.class);
+    containerConfig = mockControl.createMock(ContainerConfig.class);
 
     multipartFormParser = mockControl.createMock(MultipartFormParser.class);
     EasyMock.expect(multipartFormParser.isMultipartContent(req)).andStubReturn(false);
@@ -91,6 +94,8 @@ public class JsonRpcServletTest extends 
 
     servlet.setHandlerRegistry(registry);
     servlet.setBeanConverters(converter, null, null);
+    servlet.setContainerConfig(containerConfig);
+
     handler.setMock(new TestHandler() {
       @Override
       public Object get(RequestItem req) {

Modified: shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/RpcServletTest.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/RpcServletTest.java?rev=942261&r1=942260&r2=942261&view=diff
==============================================================================
--- shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/RpcServletTest.java (original)
+++ shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/RpcServletTest.java Fri May  7 22:51:16 2010
@@ -26,10 +26,12 @@ import static org.easymock.classextensio
 
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.util.Collections;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.shindig.common.servlet.HttpUtil;
 import org.json.JSONException;
 import org.json.JSONObject;
 import org.junit.Assert;

Modified: shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/dataservice/integration/AbstractLargeRestfulTests.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/dataservice/integration/AbstractLargeRestfulTests.java?rev=942261&r1=942260&r2=942261&view=diff
==============================================================================
--- shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/dataservice/integration/AbstractLargeRestfulTests.java (original)
+++ shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/dataservice/integration/AbstractLargeRestfulTests.java Fri May  7 22:51:16 2010
@@ -21,6 +21,7 @@ import org.apache.shindig.auth.AuthInfo;
 import org.apache.shindig.common.EasyMockTestCase;
 import org.apache.shindig.common.testing.FakeGadgetToken;
 import org.apache.shindig.common.testing.FakeHttpServletRequest;
+import org.apache.shindig.config.ContainerConfig;
 import org.apache.shindig.protocol.DataServiceServlet;
 import org.apache.shindig.protocol.HandlerRegistry;
 import org.apache.shindig.protocol.conversion.BeanJsonConverter;
@@ -55,6 +56,7 @@ import javax.xml.stream.XMLStreamReader;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.PrintWriter;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -96,6 +98,9 @@ public abstract class AbstractLargeRestf
     dispatcher.addHandlers(injector.getInstance(Key.get(new TypeLiteral<Set<Object>>(){},
         Names.named("org.apache.shindig.social.handlers"))));
     servlet.setHandlerRegistry(dispatcher);
+    ContainerConfig containerConfig = EasyMock.createMock(ContainerConfig.class);
+    EasyMock.expect(containerConfig.<String>getList(null, "gadgets.parentOrigins")).andReturn(Collections.<String>singletonList("*"));
+    servlet.setContainerConfig(EasyMock.createMock(ContainerConfig.class));
     servlet.setBeanConverters(new BeanJsonConverter(injector),
         new BeanXStreamConverter(new XStream081Configuration(injector)),
         new BeanXStreamAtomConverter(new XStream081Configuration(injector)));