Repository: camel
Updated Branches:
  refs/heads/master 25d1d418e -> 4763c62bb


CAMEL-10913: handling Access-Control-Allow-Credentials


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/4763c62b
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/4763c62b
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/4763c62b

Branch: refs/heads/master
Commit: 4763c62bbe3cf79f0781bbab8ff0a4335e586a57
Parents: 25d1d41
Author: Nicola Ferraro <ni.ferr...@gmail.com>
Authored: Tue Mar 14 12:56:23 2017 +0100
Committer: Nicola Ferraro <ni.ferr...@gmail.com>
Committed: Tue Mar 14 12:56:32 2017 +0100

----------------------------------------------------------------------
 .../model/rest/RestConfigurationDefinition.java |   8 ++
 .../camel/processor/RestBindingAdvice.java      |  11 ++
 .../FromRestGetCorsAllowCredentialsTest.java    | 100 +++++++++++++++++++
 3 files changed, 119 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/4763c62b/camel-core/src/main/java/org/apache/camel/model/rest/RestConfigurationDefinition.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/model/rest/RestConfigurationDefinition.java
 
b/camel-core/src/main/java/org/apache/camel/model/rest/RestConfigurationDefinition.java
index fe5327e..6dfd527 100644
--- 
a/camel-core/src/main/java/org/apache/camel/model/rest/RestConfigurationDefinition.java
+++ 
b/camel-core/src/main/java/org/apache/camel/model/rest/RestConfigurationDefinition.java
@@ -685,6 +685,14 @@ public class RestConfigurationDefinition {
         return this;
     }
 
+    /**
+     * Shortcut for setting the {@code Access-Control-Allow-Credentials} 
header.
+     */
+    public RestConfigurationDefinition corsAllowCredentials(boolean 
corsAllowCredentials) {
+        return corsHeaderProperty("Access-Control-Allow-Credentials", 
String.valueOf(corsAllowCredentials));
+    }
+
+
     // Implementation
     //-------------------------------------------------------------------------
 

http://git-wip-us.apache.org/repos/asf/camel/blob/4763c62b/camel-core/src/main/java/org/apache/camel/processor/RestBindingAdvice.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/processor/RestBindingAdvice.java 
b/camel-core/src/main/java/org/apache/camel/processor/RestBindingAdvice.java
index d14c0f4..84c63bc 100644
--- a/camel-core/src/main/java/org/apache/camel/processor/RestBindingAdvice.java
+++ b/camel-core/src/main/java/org/apache/camel/processor/RestBindingAdvice.java
@@ -415,11 +415,22 @@ public class RestBindingAdvice implements 
CamelInternalProcessorAdvice<Map<Strin
         if (maxAge == null) {
             maxAge = RestConfiguration.CORS_ACCESS_CONTROL_MAX_AGE;
         }
+        String allowCredentials = corsHeaders != null ? 
corsHeaders.get("Access-Control-Allow-Credentials") : null;
+
+        // Restrict the origin if credentials are allowed.
+        // https://www.w3.org/TR/cors/ - section 6.1, point 3
+        String origin = exchange.getIn().getHeader("Origin", String.class);
+        if ("true".equalsIgnoreCase(allowCredentials) && 
"*".equals(allowOrigin) && origin != null) {
+            allowOrigin = origin;
+        }
 
         msg.setHeader("Access-Control-Allow-Origin", allowOrigin);
         msg.setHeader("Access-Control-Allow-Methods", allowMethods);
         msg.setHeader("Access-Control-Allow-Headers", allowHeaders);
         msg.setHeader("Access-Control-Max-Age", maxAge);
+        if (allowCredentials != null) {
+            msg.setHeader("Access-Control-Allow-Credentials", 
allowCredentials);
+        }
     }
 
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/4763c62b/camel-core/src/test/java/org/apache/camel/component/rest/FromRestGetCorsAllowCredentialsTest.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/test/java/org/apache/camel/component/rest/FromRestGetCorsAllowCredentialsTest.java
 
b/camel-core/src/test/java/org/apache/camel/component/rest/FromRestGetCorsAllowCredentialsTest.java
new file mode 100644
index 0000000..0150f37
--- /dev/null
+++ 
b/camel-core/src/test/java/org/apache/camel/component/rest/FromRestGetCorsAllowCredentialsTest.java
@@ -0,0 +1,100 @@
+/**
+ * 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.camel.component.rest;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.impl.JndiRegistry;
+import org.apache.camel.spi.RestConfiguration;
+
+public class FromRestGetCorsAllowCredentialsTest extends ContextTestSupport {
+
+    @Override
+    protected JndiRegistry createRegistry() throws Exception {
+        JndiRegistry jndi = super.createRegistry();
+        jndi.bind("dummy-rest", new DummyRestConsumerFactory());
+        return jndi;
+    }
+
+    public void testCorsWithoutOrigin() throws Exception {
+        // the rest becomes routes and the input is a seda endpoint created by 
the DummyRestConsumerFactory
+        getMockEndpoint("mock:update").expectedMessageCount(1);
+
+        Exchange out = template.request("seda:post-say-bye", new Processor() {
+            @Override
+            public void process(Exchange exchange) throws Exception {
+                exchange.getIn().setBody("I was here");
+            }
+        });
+        assertNotNull(out);
+
+        assertEquals(RestConfiguration.CORS_ACCESS_CONTROL_ALLOW_ORIGIN, 
out.getOut().getHeader("Access-Control-Allow-Origin"));
+        assertEquals(RestConfiguration.CORS_ACCESS_CONTROL_ALLOW_METHODS, 
out.getOut().getHeader("Access-Control-Allow-Methods"));
+        assertEquals(RestConfiguration.CORS_ACCESS_CONTROL_ALLOW_HEADERS, 
out.getOut().getHeader("Access-Control-Allow-Headers"));
+        assertEquals(RestConfiguration.CORS_ACCESS_CONTROL_MAX_AGE, 
out.getOut().getHeader("Access-Control-Max-Age"));
+        assertEquals("true", 
out.getOut().getHeader("Access-Control-Allow-Credentials"));
+
+        assertMockEndpointsSatisfied();
+    }
+
+    public void testCorsWithOrigin() throws Exception {
+        // the rest becomes routes and the input is a seda endpoint created by 
the DummyRestConsumerFactory
+        getMockEndpoint("mock:update").expectedMessageCount(1);
+
+        Exchange out = template.request("seda:post-say-bye", new Processor() {
+            @Override
+            public void process(Exchange exchange) throws Exception {
+                exchange.getIn().setHeader("Origin", "mydomain");
+                exchange.getIn().setBody("I was here");
+            }
+        });
+        assertNotNull(out);
+
+        assertEquals(RestConfiguration.CORS_ACCESS_CONTROL_ALLOW_METHODS, 
out.getOut().getHeader("Access-Control-Allow-Methods"));
+        assertEquals(RestConfiguration.CORS_ACCESS_CONTROL_ALLOW_HEADERS, 
out.getOut().getHeader("Access-Control-Allow-Headers"));
+        assertEquals(RestConfiguration.CORS_ACCESS_CONTROL_MAX_AGE, 
out.getOut().getHeader("Access-Control-Max-Age"));
+        assertEquals("true", 
out.getOut().getHeader("Access-Control-Allow-Credentials"));
+        assertEquals("mydomain", 
out.getOut().getHeader("Access-Control-Allow-Origin"));
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                
restConfiguration().host("localhost").enableCORS(true).corsAllowCredentials(true);
+
+                rest("/say/hello")
+                        .get().to("direct:hello");
+
+                rest("/say/bye")
+                        .get().consumes("application/json").to("direct:bye")
+                        .post().to("mock:update");
+
+                from("direct:hello")
+                        .transform().constant("Hello World");
+
+                from("direct:bye")
+                        .transform().constant("Bye World");
+            }
+        };
+    }
+}

Reply via email to