Repository: camel Updated Branches: refs/heads/camel-2.14.x a0100ba07 -> 4cbee5f11 refs/heads/master 8cfabc840 -> 7cbd69884
CAMEL-8133: rest-dsl make it easy to enable and configure CORS. Also fixed an issue with the skip option. Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/7cbd6988 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/7cbd6988 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/7cbd6988 Branch: refs/heads/master Commit: 7cbd69884385eb340e74dc215c4247deff7c2ef2 Parents: 8cfabc8 Author: Claus Ibsen <[email protected]> Authored: Mon Dec 8 18:31:27 2014 +0100 Committer: Claus Ibsen <[email protected]> Committed: Mon Dec 8 18:31:27 2014 +0100 ---------------------------------------------------------------------- .../camel/model/rest/RestBindingDefinition.java | 29 ++++++-- .../model/rest/RestConfigurationDefinition.java | 53 +++++++++++++ .../apache/camel/model/rest/RestDefinition.java | 35 ++++++++- .../apache/camel/model/rest/VerbDefinition.java | 11 +++ .../processor/binding/RestBindingProcessor.java | 63 +++++++++++++++- .../org/apache/camel/spi/RestConfiguration.java | 51 +++++++++++++ .../rest/FromRestGetCorsCustomTest.java | 78 ++++++++++++++++++++ .../component/rest/FromRestGetCorsTest.java | 77 +++++++++++++++++++ 8 files changed, 390 insertions(+), 7 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/7cbd6988/camel-core/src/main/java/org/apache/camel/model/rest/RestBindingDefinition.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/model/rest/RestBindingDefinition.java b/camel-core/src/main/java/org/apache/camel/model/rest/RestBindingDefinition.java index 3f07d26..abe2a06 100644 --- a/camel-core/src/main/java/org/apache/camel/model/rest/RestBindingDefinition.java +++ b/camel-core/src/main/java/org/apache/camel/model/rest/RestBindingDefinition.java @@ -54,6 +54,9 @@ public class RestBindingDefinition extends NoOutputDefinition<RestBindingDefinit @XmlAttribute private Boolean skipBindingOnErrorCode; + @XmlAttribute + private Boolean enableCORS; + @Override public String toString() { return "RestBinding"; @@ -69,18 +72,26 @@ public class RestBindingDefinition extends NoOutputDefinition<RestBindingDefinit CamelContext context = routeContext.getCamelContext(); - // the default binding mode can be overridden per rest verb + // these options can be overriden per rest verb String mode = context.getRestConfiguration().getBindingMode().name(); if (bindingMode != null) { mode = bindingMode.name(); } + boolean cors = context.getRestConfiguration().isEnableCORS(); + if (enableCORS != null) { + cors = enableCORS; + } + boolean skip = context.getRestConfiguration().isSkipBindingOnErrorCode(); + if (skipBindingOnErrorCode != null) { + skip = skipBindingOnErrorCode; + } - // skip by default - boolean skip = skipBindingOnErrorCode == null || skipBindingOnErrorCode; + // cors headers + Map<String, String> corsHeaders = context.getRestConfiguration().getCorsHeaders(); if (mode == null || "off".equals(mode)) { // binding mode is off, so create a off mode binding processor - return new RestBindingProcessor(null, null, null, null, consumes, produces, mode, skip); + return new RestBindingProcessor(null, null, null, null, consumes, produces, mode, skip, cors, corsHeaders); } // setup json data format @@ -182,7 +193,7 @@ public class RestBindingDefinition extends NoOutputDefinition<RestBindingDefinit context.addService(outJaxb); } - return new RestBindingProcessor(json, jaxb, outJson, outJaxb, consumes, produces, mode, skip); + return new RestBindingProcessor(json, jaxb, outJson, outJaxb, consumes, produces, mode, skip, cors, corsHeaders); } private void setAdditionalConfiguration(CamelContext context, DataFormat dataFormat) throws Exception { @@ -242,4 +253,12 @@ public class RestBindingDefinition extends NoOutputDefinition<RestBindingDefinit public void setSkipBindingOnErrorCode(Boolean skipBindingOnErrorCode) { this.skipBindingOnErrorCode = skipBindingOnErrorCode; } + + public Boolean getEnableCORS() { + return enableCORS; + } + + public void setEnableCORS(Boolean enableCORS) { + this.enableCORS = enableCORS; + } } http://git-wip-us.apache.org/repos/asf/camel/blob/7cbd6988/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 50d3879..b033dc6 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 @@ -62,6 +62,9 @@ public class RestConfigurationDefinition { private Boolean skipBindingOnErrorCode; @XmlAttribute + private Boolean enableCORS; + + @XmlAttribute private String jsonDataFormat; @XmlAttribute @@ -79,6 +82,9 @@ public class RestConfigurationDefinition { @XmlElement(name = "dataFormatProperty") private List<RestPropertyDefinition> dataFormatProperties = new ArrayList<RestPropertyDefinition>(); + @XmlElement(name = "corsHeaders") + private List<RestPropertyDefinition> corsHeaders = new ArrayList<RestPropertyDefinition>(); + public String getComponent() { return component; } @@ -143,6 +149,14 @@ public class RestConfigurationDefinition { this.skipBindingOnErrorCode = skipBindingOnErrorCode; } + public Boolean getEnableCORS() { + return enableCORS; + } + + public void setEnableCORS(Boolean enableCORS) { + this.enableCORS = enableCORS; + } + public String getJsonDataFormat() { return jsonDataFormat; } @@ -191,6 +205,14 @@ public class RestConfigurationDefinition { this.dataFormatProperties = dataFormatProperties; } + public List<RestPropertyDefinition> getCorsHeaders() { + return corsHeaders; + } + + public void setCorsHeaders(List<RestPropertyDefinition> corsHeaders) { + this.corsHeaders = corsHeaders; + } + // Fluent API //------------------------------------------------------------------------- @@ -270,6 +292,14 @@ public class RestConfigurationDefinition { } /** + * To specify whether to enable CORS which means Camel will automatic include CORS in the HTTP headers in the response. + */ + public RestConfigurationDefinition enableCORS(boolean enableCORS) { + setEnableCORS(enableCORS); + return this; + } + + /** * To use a specific json data format * <p/> * <b>Important:</b> This option is only for setting a custom name of the data format, not to refer to an existing data format instance. @@ -337,6 +367,17 @@ public class RestConfigurationDefinition { return this; } + /** + * For configuring CORS headers + */ + public RestConfigurationDefinition corsHeaderProperty(String key, String value) { + RestPropertyDefinition prop = new RestPropertyDefinition(); + prop.setKey(key); + prop.setValue(value); + getCorsHeaders().add(prop); + return this; + } + // Implementation //------------------------------------------------------------------------- @@ -373,6 +414,9 @@ public class RestConfigurationDefinition { if (skipBindingOnErrorCode != null) { answer.setSkipBindingOnErrorCode(skipBindingOnErrorCode); } + if (enableCORS != null) { + answer.setEnableCORS(enableCORS); + } if (jsonDataFormat != null) { answer.setJsonDataFormat(jsonDataFormat); } @@ -415,6 +459,15 @@ public class RestConfigurationDefinition { } answer.setDataFormatProperties(props); } + if (!corsHeaders.isEmpty()) { + Map<String, String> props = new HashMap<String, String>(); + for (RestPropertyDefinition prop : corsHeaders) { + String key = prop.getKey(); + String value = CamelContextHelper.parseText(context, prop.getValue()); + props.put(key, value); + } + answer.setCorsHeaders(props); + } return answer; } http://git-wip-us.apache.org/repos/asf/camel/blob/7cbd6988/camel-core/src/main/java/org/apache/camel/model/rest/RestDefinition.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/model/rest/RestDefinition.java b/camel-core/src/main/java/org/apache/camel/model/rest/RestDefinition.java index 479f830..64128cd 100644 --- a/camel-core/src/main/java/org/apache/camel/model/rest/RestDefinition.java +++ b/camel-core/src/main/java/org/apache/camel/model/rest/RestDefinition.java @@ -56,6 +56,9 @@ public class RestDefinition extends OptionalIdentifiedDefinition<RestDefinition> @XmlAttribute private Boolean skipBindingOnErrorCode; + @XmlAttribute + private Boolean enableCORS; + @XmlElementRef private List<VerbDefinition> verbs = new ArrayList<VerbDefinition>(); @@ -111,7 +114,15 @@ public class RestDefinition extends OptionalIdentifiedDefinition<RestDefinition> public void setSkipBindingOnErrorCode(Boolean skipBindingOnErrorCode) { this.skipBindingOnErrorCode = skipBindingOnErrorCode; } - + + public Boolean getEnableCORS() { + return enableCORS; + } + + public void setEnableCORS(Boolean enableCORS) { + this.enableCORS = enableCORS; + } + // Fluent API //------------------------------------------------------------------------- @@ -305,6 +316,18 @@ public class RestDefinition extends OptionalIdentifiedDefinition<RestDefinition> return this; } + public RestDefinition enableCORS(boolean enableCORS) { + if (getVerbs().isEmpty()) { + this.enableCORS = enableCORS; + } else { + // add on last verb as that is how the Java DSL works + VerbDefinition verb = getVerbs().get(getVerbs().size() - 1); + verb.setEnableCORS(enableCORS); + } + + return this; + } + /** * Routes directly to the given endpoint. * <p/> @@ -405,6 +428,16 @@ public class RestDefinition extends OptionalIdentifiedDefinition<RestDefinition> } else { binding.setBindingMode(getBindingMode()); } + if (verb.getSkipBindingOnErrorCode() != null) { + binding.setSkipBindingOnErrorCode(verb.getSkipBindingOnErrorCode()); + } else { + binding.setSkipBindingOnErrorCode(getSkipBindingOnErrorCode()); + } + if (verb.getEnableCORS() != null) { + binding.setEnableCORS(verb.getEnableCORS()); + } else { + binding.setEnableCORS(getEnableCORS()); + } route.getOutputs().add(0, binding); // create the from endpoint uri which is using the rest component http://git-wip-us.apache.org/repos/asf/camel/blob/7cbd6988/camel-core/src/main/java/org/apache/camel/model/rest/VerbDefinition.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/model/rest/VerbDefinition.java b/camel-core/src/main/java/org/apache/camel/model/rest/VerbDefinition.java index 4ba401c..af56af1 100644 --- a/camel-core/src/main/java/org/apache/camel/model/rest/VerbDefinition.java +++ b/camel-core/src/main/java/org/apache/camel/model/rest/VerbDefinition.java @@ -51,6 +51,9 @@ public class VerbDefinition extends OptionalIdentifiedDefinition<VerbDefinition> private Boolean skipBindingOnErrorCode; @XmlAttribute + private Boolean enableCORS; + + @XmlAttribute private String type; @XmlAttribute @@ -129,6 +132,14 @@ public class VerbDefinition extends OptionalIdentifiedDefinition<VerbDefinition> this.skipBindingOnErrorCode = skipBindingOnErrorCode; } + public Boolean getEnableCORS() { + return enableCORS; + } + + public void setEnableCORS(Boolean enableCORS) { + this.enableCORS = enableCORS; + } + public String getType() { return type; } http://git-wip-us.apache.org/repos/asf/camel/blob/7cbd6988/camel-core/src/main/java/org/apache/camel/processor/binding/RestBindingProcessor.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/processor/binding/RestBindingProcessor.java b/camel-core/src/main/java/org/apache/camel/processor/binding/RestBindingProcessor.java index 9be0118..8a0de0d 100644 --- a/camel-core/src/main/java/org/apache/camel/processor/binding/RestBindingProcessor.java +++ b/camel-core/src/main/java/org/apache/camel/processor/binding/RestBindingProcessor.java @@ -17,14 +17,17 @@ package org.apache.camel.processor.binding; import java.util.Locale; +import java.util.Map; import org.apache.camel.AsyncCallback; import org.apache.camel.AsyncProcessor; import org.apache.camel.Exchange; +import org.apache.camel.Message; import org.apache.camel.Route; import org.apache.camel.processor.MarshalProcessor; import org.apache.camel.processor.UnmarshalProcessor; import org.apache.camel.spi.DataFormat; +import org.apache.camel.spi.RestConfiguration; import org.apache.camel.support.ServiceSupport; import org.apache.camel.support.SynchronizationAdapter; import org.apache.camel.util.AsyncProcessorHelper; @@ -49,10 +52,14 @@ public class RestBindingProcessor extends ServiceSupport implements AsyncProcess private final String produces; private final String bindingMode; private final boolean skipBindingOnErrorCode; + private final boolean enableCORS; + private final Map<String, String> corsHeaders; public RestBindingProcessor(DataFormat jsonDataFormat, DataFormat xmlDataFormat, DataFormat outJsonDataFormat, DataFormat outXmlDataFormat, - String consumes, String produces, String bindingMode, boolean skipBindingOnErrorCode) { + String consumes, String produces, String bindingMode, + boolean skipBindingOnErrorCode, boolean enableCORS, + Map<String, String> corsHeaders) { if (jsonDataFormat != null) { this.jsonUnmarshal = new UnmarshalProcessor(jsonDataFormat); @@ -84,6 +91,8 @@ public class RestBindingProcessor extends ServiceSupport implements AsyncProcess this.produces = produces; this.bindingMode = bindingMode; this.skipBindingOnErrorCode = skipBindingOnErrorCode; + this.enableCORS = enableCORS; + this.corsHeaders = corsHeaders; } @Override @@ -93,6 +102,10 @@ public class RestBindingProcessor extends ServiceSupport implements AsyncProcess @Override public boolean process(Exchange exchange, final AsyncCallback callback) { + if (enableCORS) { + exchange.addOnCompletion(new RestBindingCORSOnCompletion(corsHeaders)); + } + if (bindingMode == null || "off".equals(bindingMode)) { // binding is off callback.done(true); @@ -339,6 +352,54 @@ public class RestBindingProcessor extends ServiceSupport implements AsyncProcess exchange.setException(e); } } + + @Override + public String toString() { + return "RestBindingMarshalOnCompletion"; + } + } + + private final class RestBindingCORSOnCompletion extends SynchronizationAdapter { + + private final Map<String, String> corsHeaders; + + private RestBindingCORSOnCompletion(Map<String, String> corsHeaders) { + this.corsHeaders = corsHeaders; + } + + @Override + public void onAfterRoute(Route route, Exchange exchange) { + // add the CORS headers after routing, but before the consumer writes the response + Message msg = exchange.hasOut() ? exchange.getOut() : exchange.getIn(); + + // use default value if none has been configured + String allowOrigin = corsHeaders != null ? corsHeaders.get("Access-Control-Allow-Origin") : null; + if (allowOrigin == null) { + allowOrigin = RestConfiguration.CORS_ACCESS_CONTROL_ALLOW_ORIGIN; + } + String allowMethods = corsHeaders != null ? corsHeaders.get("Access-Control-Allow-Methods") : null; + if (allowMethods == null) { + allowMethods = RestConfiguration.CORS_ACCESS_CONTROL_ALLOW_METHODS; + } + String allowHeaders = corsHeaders != null ? corsHeaders.get("Access-Control-Allow-Headers") : null; + if (allowHeaders == null) { + allowHeaders = RestConfiguration.CORS_ACCESS_CONTROL_ALLOW_HEADERS; + } + String maxAge = corsHeaders != null ? corsHeaders.get("Access-Control-Max-Age") : null; + if (maxAge == null) { + maxAge = RestConfiguration.CORS_ACCESS_CONTROL_MAX_AGE; + } + + 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); + } + + @Override + public String toString() { + return "RestBindingCORSOnCompletion"; + } } } http://git-wip-us.apache.org/repos/asf/camel/blob/7cbd6988/camel-core/src/main/java/org/apache/camel/spi/RestConfiguration.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/spi/RestConfiguration.java b/camel-core/src/main/java/org/apache/camel/spi/RestConfiguration.java index 50d64f7..5daecd9 100644 --- a/camel-core/src/main/java/org/apache/camel/spi/RestConfiguration.java +++ b/camel-core/src/main/java/org/apache/camel/spi/RestConfiguration.java @@ -24,6 +24,11 @@ import java.util.Map; */ public class RestConfiguration { + public static final String CORS_ACCESS_CONTROL_ALLOW_ORIGIN = "*"; + public static final String CORS_ACCESS_CONTROL_ALLOW_METHODS = "GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, CONNECT, PATCH"; + public static final String CORS_ACCESS_CONTROL_MAX_AGE = "3600"; + public static final String CORS_ACCESS_CONTROL_ALLOW_HEADERS = "Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers"; + public enum RestBindingMode { auto, off, json, xml, json_xml } @@ -40,12 +45,14 @@ public class RestConfiguration { private RestHostNameResolver restHostNameResolver = RestHostNameResolver.localHostName; private RestBindingMode bindingMode = RestBindingMode.off; private boolean skipBindingOnErrorCode = true; + private boolean enableCORS; private String jsonDataFormat; private String xmlDataFormat; private Map<String, Object> componentProperties; private Map<String, Object> endpointProperties; private Map<String, Object> consumerProperties; private Map<String, Object> dataFormatProperties; + private Map<String, String> corsHeaders; /** * Gets the name of the Camel component to use as the REST consumer @@ -198,6 +205,8 @@ public class RestConfiguration { * Whether to skip binding output if there is a custom HTTP error code, and instead use the response body as-is. * <p/> * This option is default <tt>true</tt>. + * + * @return whether to skip binding on error code */ public boolean isSkipBindingOnErrorCode() { return skipBindingOnErrorCode; @@ -207,12 +216,36 @@ public class RestConfiguration { * Whether to skip binding output if there is a custom HTTP error code, and instead use the response body as-is. * <p/> * This option is default <tt>true</tt>. + * + * @param skipBindingOnErrorCode whether to skip binding on error code */ public void setSkipBindingOnErrorCode(boolean skipBindingOnErrorCode) { this.skipBindingOnErrorCode = skipBindingOnErrorCode; } /** + * To specify whether to enable CORS which means Camel will automatic include CORS in the HTTP headers in the response. + * <p/> + * This option is default <tt>false</tt> + * + * @return whether CORS is enabled or not + */ + public boolean isEnableCORS() { + return enableCORS; + } + + /** + * To specify whether to enable CORS which means Camel will automatic include CORS in the HTTP headers in the response. + * <p/> + * This option is default <tt>false</tt> + * + * @param enableCORS <tt>true</tt> to enable CORS + */ + public void setEnableCORS(boolean enableCORS) { + this.enableCORS = enableCORS; + } + + /** * Gets the name of the json data format. * <p/> * <b>Important:</b> This option is only for setting a custom name of the data format, not to refer to an existing data format instance. @@ -327,4 +360,22 @@ public class RestConfiguration { public void setDataFormatProperties(Map<String, Object> dataFormatProperties) { this.dataFormatProperties = dataFormatProperties; } + + /** + * Gets the CORS headers to use if CORS has been enabled. + * + * @return the CORS headers + */ + public Map<String, String> getCorsHeaders() { + return corsHeaders; + } + + /** + * Sets the CORS headers to use if CORS has been enabled. + * + * @param corsHeaders the CORS headers + */ + public void setCorsHeaders(Map<String, String> corsHeaders) { + this.corsHeaders = corsHeaders; + } } http://git-wip-us.apache.org/repos/asf/camel/blob/7cbd6988/camel-core/src/test/java/org/apache/camel/component/rest/FromRestGetCorsCustomTest.java ---------------------------------------------------------------------- diff --git a/camel-core/src/test/java/org/apache/camel/component/rest/FromRestGetCorsCustomTest.java b/camel-core/src/test/java/org/apache/camel/component/rest/FromRestGetCorsCustomTest.java new file mode 100644 index 0000000..997fbbf --- /dev/null +++ b/camel-core/src/test/java/org/apache/camel/component/rest/FromRestGetCorsCustomTest.java @@ -0,0 +1,78 @@ +/** + * 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 FromRestGetCorsCustomTest extends ContextTestSupport { + + @Override + protected JndiRegistry createRegistry() throws Exception { + JndiRegistry jndi = super.createRegistry(); + jndi.bind("dummy-rest", new DummyRestConsumerFactory()); + return jndi; + } + + public void testCors() 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(out.getOut().getHeader("Access-Control-Allow-Origin"), "myserver"); + assertEquals(out.getOut().getHeader("Access-Control-Allow-Methods"), RestConfiguration.CORS_ACCESS_CONTROL_ALLOW_METHODS); + assertEquals(out.getOut().getHeader("Access-Control-Allow-Headers"), RestConfiguration.CORS_ACCESS_CONTROL_ALLOW_HEADERS); + assertEquals(out.getOut().getHeader("Access-Control-Max-Age"), "180"); + + assertMockEndpointsSatisfied(); + } + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + restConfiguration().enableCORS(true).corsHeaderProperty("Access-Control-Allow-Origin", "myserver"); + restConfiguration().enableCORS(true).corsHeaderProperty("Access-Control-Max-Age", "180"); + + 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"); + } + }; + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/7cbd6988/camel-core/src/test/java/org/apache/camel/component/rest/FromRestGetCorsTest.java ---------------------------------------------------------------------- diff --git a/camel-core/src/test/java/org/apache/camel/component/rest/FromRestGetCorsTest.java b/camel-core/src/test/java/org/apache/camel/component/rest/FromRestGetCorsTest.java new file mode 100644 index 0000000..b0b213c --- /dev/null +++ b/camel-core/src/test/java/org/apache/camel/component/rest/FromRestGetCorsTest.java @@ -0,0 +1,77 @@ +/** + * 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 FromRestGetCorsTest extends ContextTestSupport { + + @Override + protected JndiRegistry createRegistry() throws Exception { + JndiRegistry jndi = super.createRegistry(); + jndi.bind("dummy-rest", new DummyRestConsumerFactory()); + return jndi; + } + + public void testCors() 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(out.getOut().getHeader("Access-Control-Allow-Origin"), RestConfiguration.CORS_ACCESS_CONTROL_ALLOW_ORIGIN); + assertEquals(out.getOut().getHeader("Access-Control-Allow-Methods"), RestConfiguration.CORS_ACCESS_CONTROL_ALLOW_METHODS); + assertEquals(out.getOut().getHeader("Access-Control-Allow-Headers"), RestConfiguration.CORS_ACCESS_CONTROL_ALLOW_HEADERS); + assertEquals(out.getOut().getHeader("Access-Control-Max-Age"), RestConfiguration.CORS_ACCESS_CONTROL_MAX_AGE); + + assertMockEndpointsSatisfied(); + } + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + restConfiguration().enableCORS(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"); + } + }; + } +}
