This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-spring-boot.git
The following commit(s) were added to refs/heads/main by this push:
new 85209822dc1 CAMEL-21461: platform-http - add CORS support (#1299)
85209822dc1 is described below
commit 85209822dc1e34f024486de12a7c37efe4e82479
Author: Rinaldo Pitzer JĂșnior <[email protected]>
AuthorDate: Fri Dec 6 05:27:17 2024 -0300
CAMEL-21461: platform-http - add CORS support (#1299)
---
.../springboot/CamelRequestHandlerMapping.java | 80 +++++++-
.../SpringBootPlatformHttpCorsCredentialsTest.java | 201 +++++++++++++++++++++
.../springboot/SpringBootPlatformHttpCorsTest.java | 137 +++++++++-----
...java => SpringBootPlatformHttpOptionsTest.java} | 112 ++++++------
.../src/test/resources/application.properties | 5 +-
5 files changed, 417 insertions(+), 118 deletions(-)
diff --git
a/components-starter/camel-platform-http-starter/src/main/java/org/apache/camel/component/platform/http/springboot/CamelRequestHandlerMapping.java
b/components-starter/camel-platform-http-starter/src/main/java/org/apache/camel/component/platform/http/springboot/CamelRequestHandlerMapping.java
index 33f43b30e8f..9eb332f45c4 100644
---
a/components-starter/camel-platform-http-starter/src/main/java/org/apache/camel/component/platform/http/springboot/CamelRequestHandlerMapping.java
+++
b/components-starter/camel-platform-http-starter/src/main/java/org/apache/camel/component/platform/http/springboot/CamelRequestHandlerMapping.java
@@ -23,8 +23,10 @@ import
org.apache.camel.component.platform.http.PlatformHttpComponent;
import org.apache.camel.component.platform.http.PlatformHttpEndpoint;
import org.apache.camel.component.platform.http.PlatformHttpListener;
import org.apache.camel.component.platform.http.spi.PlatformHttpEngine;
+import org.apache.camel.spi.RestConfiguration;
import org.apache.camel.util.ReflectionHelper;
import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
@@ -32,13 +34,20 @@ import org.springframework.web.util.ServletRequestPathUtils;
import java.lang.reflect.Method;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
public class CamelRequestHandlerMapping extends RequestMappingHandlerMapping
implements PlatformHttpListener {
private final PlatformHttpComponent component;
private final PlatformHttpEngine engine;
+ private CorsConfiguration corsConfiguration;
+
public CamelRequestHandlerMapping(PlatformHttpComponent component,
PlatformHttpEngine engine) {
this.component = component;
this.engine = engine;
@@ -67,6 +76,55 @@ public class CamelRequestHandlerMapping extends
RequestMappingHandlerMapping imp
return null;
}
+ @Override
+ protected CorsConfiguration initCorsConfiguration(Object handler, Method
method, RequestMappingInfo mappingInfo) {
+ RestConfiguration restConfiguration =
component.getCamelContext().getRestConfiguration();
+
+ if (!restConfiguration.isEnableCORS()) {
+ // CORS disabled for camel
+ return null;
+ }
+
+ if (corsConfiguration == null) {
+ Map<String, String> corsHeaders =
restConfiguration.getCorsHeaders();
+ corsConfiguration = createCorsConfiguration(corsHeaders != null ?
corsHeaders : Collections.emptyMap());
+ }
+ return corsConfiguration;
+ }
+
+ @Override
+ protected CorsConfiguration getCorsConfiguration(Object handler,
HttpServletRequest request) {
+ return super.getCorsConfiguration(handler, request);
+ }
+
+ private CorsConfiguration createCorsConfiguration(Map<String, String>
corsHeaders) {
+ CorsConfiguration config = new CorsConfiguration();
+
+ String allowedOrigin = corsHeaders.get("Access-Control-Allow-Origin");
+ config.addAllowedOrigin(allowedOrigin != null ? allowedOrigin :
RestConfiguration.CORS_ACCESS_CONTROL_ALLOW_ORIGIN);
+
+ String allowMethodsStr =
corsHeaders.get("Access-Control-Allow-Methods");
+ allowMethodsStr = allowMethodsStr != null ? allowMethodsStr :
RestConfiguration.CORS_ACCESS_CONTROL_ALLOW_METHODS;
+ for (String allowMethod : allowMethodsStr.split(",")) {
+ config.addAllowedMethod(allowMethod.trim());
+ }
+
+ String allowHeadersStr =
corsHeaders.get("Access-Control-Allow-Headers");
+ allowHeadersStr = allowHeadersStr != null ? allowHeadersStr :
RestConfiguration.CORS_ACCESS_CONTROL_ALLOW_HEADERS;
+ for (String allowHeader : allowHeadersStr.split(",")) {
+ config.addAllowedHeader(allowHeader.trim());
+ }
+
+ String maxAgeStr = corsHeaders.get("Access-Control-Max-Age");
+ Long maxAge = maxAgeStr != null ? Long.parseLong(maxAgeStr) :
Long.parseLong(RestConfiguration.CORS_ACCESS_CONTROL_MAX_AGE);
+ config.setMaxAge(maxAge);
+
+ String allowCredentials =
corsHeaders.get("Access-Control-Allow-Credentials");
+ config.setAllowCredentials(Boolean.parseBoolean(allowCredentials));
+
+ return config;
+ }
+
@Override
protected HandlerMethod getHandlerInternal(HttpServletRequest request)
throws Exception {
ServletRequestPathUtils.parseAndCache(request);
@@ -81,7 +139,6 @@ public class CamelRequestHandlerMapping extends
RequestMappingHandlerMapping imp
for (RequestMappingInfo info : requestMappingInfos) {
// Needed in case of context reload
unregisterMapping(info);
-
registerMapping(info, model.getConsumer(), m);
}
}
@@ -100,20 +157,31 @@ public class CamelRequestHandlerMapping extends
RequestMappingHandlerMapping imp
if (verbs == null && model.getConsumer() != null) {
PlatformHttpEndpoint endpoint = (PlatformHttpEndpoint)
model.getConsumer().getEndpoint();
verbs = endpoint.getHttpMethodRestrict();
-
- for (RequestMethod rm : RequestMethod.values()) {
- createRequestMappingInfo(model, rm, result);
+ if (verbs == null) {
+ Collections.addAll(methods, RequestMethod.values());
}
}
if (verbs != null) {
for (String v : model.getVerbs().split(",")) {
RequestMethod rm = RequestMethod.resolve(v);
methods.add(rm);
-
- createRequestMappingInfo(model, rm, result);
}
}
+ if (component.getCamelContext().getRestConfiguration().isEnableCORS())
{
+ // when CORS is enabled Camel adds OPTIONS by default in
httpMethodsRestrict
+ // which causes multiple registration of OPTIONS endpoints in
spring.
+ // this causes issues when unregistering endpoints because others
share
+ // the same handler (the consumer) so they get unregistered as
well.
+ // removing the OPTIONS mappings maintains the intended behavior
+ // of this verb while avoiding this issue.
+ methods.remove(RequestMethod.OPTIONS);
+ }
+
+ for (RequestMethod rm : methods) {
+ createRequestMappingInfo(model, rm, result);
+ }
+
return result;
}
diff --git
a/components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpCorsCredentialsTest.java
b/components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpCorsCredentialsTest.java
new file mode 100644
index 00000000000..b7a60072a3e
--- /dev/null
+++
b/components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpCorsCredentialsTest.java
@@ -0,0 +1,201 @@
+/*
+ * 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.platform.http.springboot;
+
+import io.restassured.RestAssured;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.spi.RestConfiguration;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import
org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration;
+import
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.web.server.LocalServerPort;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+
+import static io.restassured.RestAssured.given;
+import static org.hamcrest.Matchers.*;
+
+@EnableAutoConfiguration(exclude = {OAuth2ClientAutoConfiguration.class,
SecurityAutoConfiguration.class})
+@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
+@CamelSpringBootTest
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
classes = { CamelAutoConfiguration.class,
+ SpringBootPlatformHttpCorsCredentialsTest.class,
SpringBootPlatformHttpCorsCredentialsTest.TestConfiguration.class,
+ PlatformHttpComponentAutoConfiguration.class,
SpringBootPlatformHttpAutoConfiguration.class, })
+public class SpringBootPlatformHttpCorsCredentialsTest {
+
+ @LocalServerPort
+ private Integer port;
+
+ @BeforeEach
+ void setUp() {
+ RestAssured.port = port;
+ RestAssured.enableLoggingOfRequestAndResponseIfValidationFails();
+ }
+
+ @Configuration
+ public static class TestConfiguration {
+ @Bean
+ public RouteBuilder springBootPlatformHttpRestDSLRouteBuilder() {
+ return new RouteBuilder() {
+ @Override
+ public void configure() {
+ restConfiguration().component("platform-http")
+ .enableCORS(true)
+ .corsAllowCredentials(true)
+ .corsHeaderProperty("Access-Control-Allow-Origin",
"http://custom.origin.springboot");
+
+ rest("/rest")
+ .get().to("direct:restGet")
+
.post().consumes("application/json").to("direct:restPost");
+
+ from("direct:restPost")
+ .transform().constant("corsPost");
+
+ from("direct:restGet")
+ .transform().constant("corsGet");
+ }
+ };
+ }
+ }
+
+ @Test
+ public void get() {
+ given()
+ .when()
+ .get("/rest")
+ .then()
+ .statusCode(200)
+ .body(equalTo("corsGet"));
+ }
+
+ @Test
+ public void post() {
+ given()
+ .header("Content-type","application/json")
+ .when()
+ .post("/rest")
+ .then()
+ .statusCode(200)
+ .body(equalTo("corsPost"));
+ }
+
+ @Test
+ public void options() {
+ final String origin = "http://custom.origin.springboot";
+ final String method = "POST";
+ final String headers = "X-Requested-With";
+
+ given()
+ .header("Origin", origin)
+ .header("Access-Control-Request-Method", method)
+ .header("Access-Control-Request-Headers", headers)
+ .when()
+ .options("/rest")
+ .then()
+ .statusCode(200)
+ .header("Access-Control-Allow-Origin", origin)
+ .header("Access-Control-Allow-Methods", containsString(method))
+ .header("Access-Control-Allow-Headers", containsString(headers))
+ .header("Access-Control-Allow-Credentials", "true")
+ .header("Access-Control-Max-Age",
RestConfiguration.CORS_ACCESS_CONTROL_MAX_AGE)
+ .body(emptyString());
+ }
+
+ @Test
+ public void getForbiddenOrigin() {
+ final String origin = "http://custom2.origin.springboot";
+
+ given()
+ .header("Origin", origin)
+ .when()
+ .get("/rest")
+ .then()
+ .statusCode(403);
+ }
+
+ @Test
+ public void postForbiddenOrigin() {
+ final String origin = "http://custom2.origin.springboot";
+
+ given()
+ .header("Origin", origin)
+ .header("Content-type","application/json")
+ .when()
+ .post("/rest")
+ .then()
+ .statusCode(403);
+ }
+
+ @Test
+ public void optionsForbiddenOrigin() {
+ final String origin = "http://custom2.origin.springboot";
+
+ given()
+ .header("Origin", origin)
+ .when()
+ .options("/rest")
+ .then()
+ .header("Access-Control-Allow-Origin",
not(containsString(origin)));
+ }
+
+ @Test
+ public void optionsForbiddenMethod() {
+ String method = "DELETE";
+
+ given()
+ .header("Access-Control-Request-Method", method)
+ .when()
+ .options("/rest")
+ .then()
+ .header("Access-Control-Allow-Methods",
not(containsString(method)));
+ }
+
+ @Test
+ public void optionsForbiddenHeader() {
+ String header = "X-Custom-Header";
+
+ given()
+ .header("Access-Control-Request-Headers", header)
+ .when()
+ .options("/rest")
+ .then()
+ .header("Access-Control-Allow-Headers",
not(containsString(header)));
+ }
+
+ @Test
+ public void optionNonCors() {
+ given()
+ .when()
+ .options("/rest")
+ .then()
+ .statusCode(200)
+ .header("Allow", containsString("OPTIONS"))
+ .header("Allow", containsString("GET"))
+ .header("Allow", containsString("POST"))
+ .header("Allow", containsString("HEAD"))
+ .header("Allow", not(containsString("PATCH")))
+ .header("Allow", not(containsString("PUT")))
+ .header("Allow", not(containsString("DELETE")));
+ }
+
+}
diff --git
a/components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpCorsTest.java
b/components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpCorsTest.java
index 61ad34fecfb..fd7e3cd7f35 100644
---
a/components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpCorsTest.java
+++
b/components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpCorsTest.java
@@ -17,7 +17,6 @@
package org.apache.camel.component.platform.http.springboot;
import io.restassured.RestAssured;
-import org.apache.camel.CamelContext;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.spi.RestConfiguration;
import org.apache.camel.spring.boot.CamelAutoConfiguration;
@@ -25,18 +24,19 @@ import
org.apache.camel.test.spring.junit5.CamelSpringBootTest;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import
org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration;
import
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.annotation.DirtiesContext;
import static io.restassured.RestAssured.given;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.emptyString;
+import static org.hamcrest.Matchers.not;
@EnableAutoConfiguration(exclude = {OAuth2ClientAutoConfiguration.class,
SecurityAutoConfiguration.class})
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
@@ -46,33 +46,17 @@ import static io.restassured.RestAssured.given;
PlatformHttpComponentAutoConfiguration.class,
SpringBootPlatformHttpAutoConfiguration.class, })
public class SpringBootPlatformHttpCorsTest {
- @Autowired
- TestRestTemplate restTemplate;
-
- @Autowired
- CamelContext camelContext;
-
@LocalServerPort
private Integer port;
@BeforeEach
void setUp() {
RestAssured.port = port;
+ RestAssured.enableLoggingOfRequestAndResponseIfValidationFails();
}
@Configuration
public static class TestConfiguration {
-
-// @Bean
-// public WebMvcConfigurer corsConfigurer() {
-// return new WebMvcConfigurer() {
-// @Override
-// public void addCorsMappings(CorsRegistry registry) {
-// registry.addMapping("/**");
-// }
-// };
-// }
-
@Bean
public RouteBuilder springBootPlatformHttpRestDSLRouteBuilder() {
return new RouteBuilder() {
@@ -81,14 +65,12 @@ public class SpringBootPlatformHttpCorsTest {
restConfiguration().component("platform-http").enableCORS(true);
rest("/rest")
- .post()
- .consumes("application/json")
- .to("direct:rest");
+
.post().consumes("application/json").to("direct:rest");
from("direct:rest")
.setBody(simple("Hello ${body}"));
- from("platform-http:/cors")
+ from("platform-http:/cors?httpMethodRestrict=GET,POST")
.transform().constant("cors");
}
};
@@ -96,39 +78,96 @@ public class SpringBootPlatformHttpCorsTest {
}
@Test
- @Disabled("Test is failing, work in progress")
- public void cors() {
+ public void get() {
+ given()
+ .when()
+ .get("/cors")
+ .then()
+ .statusCode(200);
+ }
+
+ @Test
+ public void post() {
+ given()
+ .header("Content-type","application/json")
+ .when()
+ .post("/rest")
+ .then()
+ .statusCode(200);
+ }
+
+ @Test
+ public void options() {
final String origin = "http://custom.origin.springboot";
- final String methods = "GET,POST";
- final String headers = "X-Custom";
+ final String method = "POST";
+ final String headers = "X-Requested-With";
given()
- .header("Origin", origin)
- .header("Access-Control-Request-Method", methods)
- .header("Access-Control-Request-Headers", headers)
- .when()
- .get("/cors")
- .then()
- .statusCode(200)
- .header("Access-Control-Allow-Origin", origin)
- .header("Access-Control-Allow-Methods", methods)
- .header("Access-Control-Allow-Headers", headers);
+ .header("Origin", origin)
+ .header("Access-Control-Request-Method", method)
+ .header("Access-Control-Request-Headers", headers)
+ .when()
+ .options("/rest")
+ .then()
+ .statusCode(200)
+ .header("Access-Control-Allow-Origin", "*")
+ .header("Access-Control-Allow-Methods", containsString(method))
+ .header("Access-Control-Allow-Headers", containsString(headers))
+ .header("Access-Control-Max-Age",
RestConfiguration.CORS_ACCESS_CONTROL_MAX_AGE)
+ .body(emptyString());
}
@Test
- @Disabled("Test is failing, work in progress")
- public void corsWithConsumes() {
+ public void optionsSecondEndPoint() {
final String origin = "http://custom.origin.springboot";
+ final String method = "POST";
+ final String headers = "X-Requested-With";
+
+ given()
+ .header("Origin", origin)
+ .header("Access-Control-Request-Method", method)
+ .header("Access-Control-Request-Headers", headers)
+ .when()
+ .options("/cors")
+ .then()
+ .statusCode(200)
+ .header("Access-Control-Allow-Origin", "*")
+ .header("Access-Control-Allow-Methods", containsString(method))
+ .header("Access-Control-Allow-Headers", containsString(headers))
+ .header("Access-Control-Max-Age",
RestConfiguration.CORS_ACCESS_CONTROL_MAX_AGE)
+ .body(emptyString());
+ }
+
+ @Test
+ public void optionNonCORS() {
+ given()
+ .when()
+ .options("/rest")
+ .then()
+ .statusCode(200)
+ .header("Allow", containsString("OPTIONS"))
+ .header("Allow", not(containsString("GET")))
+ .header("Allow", containsString("POST"))
+ .header("Allow", not(containsString("HEAD")))
+ .header("Allow", not(containsString("PATCH")))
+ .header("Allow", not(containsString("PUT")))
+ .header("Allow", not(containsString("DELETE")));
+ }
+ @Test
+ public void optionNonCorsSecondEndpoint() {
given()
- .header("Origin", origin)
- .when()
- .options("/rest")
- .then()
- .statusCode(204)
- .header("Access-Control-Allow-Origin",
RestConfiguration.CORS_ACCESS_CONTROL_ALLOW_ORIGIN)
- .header("Access-Control-Allow-Methods",
RestConfiguration.CORS_ACCESS_CONTROL_ALLOW_METHODS)
- .header("Access-Control-Allow-Headers",
RestConfiguration.CORS_ACCESS_CONTROL_ALLOW_HEADERS)
- .header("Access-Control-Max-Age",
RestConfiguration.CORS_ACCESS_CONTROL_MAX_AGE);
+ .when()
+ .options("/cors")
+ .then()
+ .statusCode(200)
+ .header("Allow", containsString("OPTIONS"))
+ .header("Allow", containsString("GET"))
+ .header("Allow", containsString("POST"))
+ .header("Allow", containsString("HEAD"))
+ .header("Allow", not(containsString("PATCH")))
+ .header("Allow", not(containsString("PUT")))
+ .header("Allow", not(containsString("DELETE")));
}
+
}
diff --git
a/components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpCorsTest.java
b/components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpOptionsTest.java
similarity index 51%
copy from
components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpCorsTest.java
copy to
components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpOptionsTest.java
index 61ad34fecfb..036dd359cf1 100644
---
a/components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpCorsTest.java
+++
b/components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpOptionsTest.java
@@ -17,40 +17,30 @@
package org.apache.camel.component.platform.http.springboot;
import io.restassured.RestAssured;
-import org.apache.camel.CamelContext;
import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.spi.RestConfiguration;
import org.apache.camel.spring.boot.CamelAutoConfiguration;
import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import
org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration;
import
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.annotation.DirtiesContext;
import static io.restassured.RestAssured.given;
+import static org.hamcrest.Matchers.*;
@EnableAutoConfiguration(exclude = {OAuth2ClientAutoConfiguration.class,
SecurityAutoConfiguration.class})
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
@CamelSpringBootTest
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
classes = { CamelAutoConfiguration.class,
- SpringBootPlatformHttpCorsTest.class,
SpringBootPlatformHttpCorsTest.TestConfiguration.class,
+ SpringBootPlatformHttpOptionsTest.class,
SpringBootPlatformHttpOptionsTest.TestConfiguration.class,
PlatformHttpComponentAutoConfiguration.class,
SpringBootPlatformHttpAutoConfiguration.class, })
-public class SpringBootPlatformHttpCorsTest {
-
- @Autowired
- TestRestTemplate restTemplate;
-
- @Autowired
- CamelContext camelContext;
+public class SpringBootPlatformHttpOptionsTest {
@LocalServerPort
private Integer port;
@@ -58,77 +48,77 @@ public class SpringBootPlatformHttpCorsTest {
@BeforeEach
void setUp() {
RestAssured.port = port;
+ RestAssured.enableLoggingOfRequestAndResponseIfValidationFails();
}
@Configuration
public static class TestConfiguration {
-
-// @Bean
-// public WebMvcConfigurer corsConfigurer() {
-// return new WebMvcConfigurer() {
-// @Override
-// public void addCorsMappings(CorsRegistry registry) {
-// registry.addMapping("/**");
-// }
-// };
-// }
-
@Bean
public RouteBuilder springBootPlatformHttpRestDSLRouteBuilder() {
return new RouteBuilder() {
@Override
public void configure() {
-
restConfiguration().component("platform-http").enableCORS(true);
+
restConfiguration().component("platform-http").enableCORS(false);
rest("/rest")
- .post()
- .consumes("application/json")
- .to("direct:rest");
-
- from("direct:rest")
- .setBody(simple("Hello ${body}"));
+ .get().to("direct:get")
+ .post().to("direct:post");
+ from("direct:get").transform().constant("get");
+ from("direct:post").transform().constant("post");
- from("platform-http:/cors")
- .transform().constant("cors");
+
from("platform-http:/restRestricted?httpMethodRestrict=GET,PUT").transform().constant("restricted");
+
from("platform-http:/restDefault").transform().constant("default");
}
};
}
}
@Test
- @Disabled("Test is failing, work in progress")
- public void cors() {
- final String origin = "http://custom.origin.springboot";
- final String methods = "GET,POST";
- final String headers = "X-Custom";
-
+ public void optionsRest() {
given()
- .header("Origin", origin)
- .header("Access-Control-Request-Method", methods)
- .header("Access-Control-Request-Headers", headers)
- .when()
- .get("/cors")
- .then()
- .statusCode(200)
- .header("Access-Control-Allow-Origin", origin)
- .header("Access-Control-Allow-Methods", methods)
- .header("Access-Control-Allow-Headers", headers);
+ .when()
+ .options("/rest")
+ .then()
+ .statusCode(200)
+ .header("Allow", containsString("OPTIONS"))
+ .header("Allow", containsString("GET"))
+ .header("Allow", containsString("POST"))
+ .header("Allow", containsString("HEAD"))
+ .header("Allow", not(containsString("PATCH")))
+ .header("Allow", not(containsString("PUT")))
+ .header("Allow", not(containsString("DELETE")));
}
@Test
- @Disabled("Test is failing, work in progress")
- public void corsWithConsumes() {
- final String origin = "http://custom.origin.springboot";
+ public void optionsRestRestricted() {
+ given()
+ .when()
+ .options("/restRestricted")
+ .then()
+ .statusCode(200)
+ .header("Allow", containsString("OPTIONS"))
+ .header("Allow", containsString("GET"))
+ .header("Allow", not(containsString("POST")))
+ .header("Allow", containsString("HEAD"))
+ .header("Allow", not(containsString("PATCH")))
+ .header("Allow", containsString("PUT"))
+ .header("Allow", not(containsString("DELETE")));
+ }
+ @Test
+ public void optionsRestDefault() {
given()
- .header("Origin", origin)
- .when()
- .options("/rest")
- .then()
- .statusCode(204)
- .header("Access-Control-Allow-Origin",
RestConfiguration.CORS_ACCESS_CONTROL_ALLOW_ORIGIN)
- .header("Access-Control-Allow-Methods",
RestConfiguration.CORS_ACCESS_CONTROL_ALLOW_METHODS)
- .header("Access-Control-Allow-Headers",
RestConfiguration.CORS_ACCESS_CONTROL_ALLOW_HEADERS)
- .header("Access-Control-Max-Age",
RestConfiguration.CORS_ACCESS_CONTROL_MAX_AGE);
+ .when()
+ .options("/restDefault")
+ .then()
+ .statusCode(200)
+ .header("Allow", containsString("OPTIONS"))
+ .header("Allow", containsString("GET"))
+ .header("Allow", containsString("POST"))
+ .header("Allow", containsString("HEAD"))
+ .header("Allow", containsString("PATCH"))
+ .header("Allow", containsString("PUT"))
+ .header("Allow", containsString("DELETE"));
}
+
}
diff --git
a/components-starter/camel-platform-http-starter/src/test/resources/application.properties
b/components-starter/camel-platform-http-starter/src/test/resources/application.properties
index 21f8569b457..f3183eb5542 100644
---
a/components-starter/camel-platform-http-starter/src/test/resources/application.properties
+++
b/components-starter/camel-platform-http-starter/src/test/resources/application.properties
@@ -15,5 +15,6 @@
## limitations under the License.
## ---------------------------------------------------------------------------
-#logging.level.org.springframework.web: DEBUG
-#logging.level.org.springframework.boot.web: DEBUG
\ No newline at end of file
+#logging.level.org.springframework.web=TRACE
+#logging.level.org.springframework.boot.web=TRACE
+#spring.mvc.log-request-details=true