From b3edfef44da798bb2a858b9948a52594635459da Mon Sep 17 00:00:00 2001 From: Sergey Beryozkin Date: Sun, 4 Dec 2022 20:14:51 +0000 Subject: [PATCH 1/2] Update CORS Access-Control-Allow-Headers test --- .../java/io/quarkus/vertx/http/cors/CORSHandlerTestCase.java | 4 ++-- .../deployment/src/test/resources/conf/cors-config.properties | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/cors/CORSHandlerTestCase.java b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/cors/CORSHandlerTestCase.java index d099842238f66..839d63e15e20b 100644 --- a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/cors/CORSHandlerTestCase.java +++ b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/cors/CORSHandlerTestCase.java @@ -22,7 +22,7 @@ public class CORSHandlerTestCase { public void corsPreflightTestServlet() { String origin = "http://custom.origin.quarkus"; String methods = "GET,POST"; - String headers = "X-Custom"; + String headers = "X-Custom, content-type"; given().header("Origin", origin) .header("Access-Control-Request-Method", methods) .header("Access-Control-Request-Headers", headers) @@ -40,7 +40,7 @@ public void corsPreflightTestServlet() { public void corsNoPreflightTestServlet() { String origin = "http://custom.origin.quarkus"; String methods = "GET,POST"; - String headers = "X-Custom"; + String headers = "x-custom, CONTENT-TYPE"; given().header("Origin", origin) .header("Access-Control-Request-Method", methods) .header("Access-Control-Request-Headers", headers) diff --git a/extensions/vertx-http/deployment/src/test/resources/conf/cors-config.properties b/extensions/vertx-http/deployment/src/test/resources/conf/cors-config.properties index d9a2687cc383d..f202ef1064bf6 100644 --- a/extensions/vertx-http/deployment/src/test/resources/conf/cors-config.properties +++ b/extensions/vertx-http/deployment/src/test/resources/conf/cors-config.properties @@ -2,3 +2,4 @@ quarkus.http.cors=true # whitespaces added to test that they are not taken into account config is parsed quarkus.http.cors.methods=GET, OPTIONS, POST quarkus.http.cors.access-control-allow-credentials=true +quarkus.http.cors.access-control-allow-headers=x-custom,CONTENT-TYPE From bd521fc1a2b7f83dea384202a18740ec4f07753d Mon Sep 17 00:00:00 2001 From: Sergey Beryozkin Date: Mon, 5 Dec 2022 14:08:11 +0000 Subject: [PATCH 2/2] Return allowed CORS headers in the letter case they were submitted in --- .../vertx/http/cors/CORSHandlerTestCase.java | 22 +++++++++++++++++-- .../resources/conf/cors-config.properties | 2 +- .../vertx/http/runtime/cors/CORSFilter.java | 13 ++++++----- 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/cors/CORSHandlerTestCase.java b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/cors/CORSHandlerTestCase.java index 839d63e15e20b..404627d4a32c3 100644 --- a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/cors/CORSHandlerTestCase.java +++ b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/cors/CORSHandlerTestCase.java @@ -1,6 +1,7 @@ package io.quarkus.vertx.http.cors; import static io.restassured.RestAssured.given; +import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.core.Is.is; import org.junit.jupiter.api.DisplayName; @@ -22,7 +23,7 @@ public class CORSHandlerTestCase { public void corsPreflightTestServlet() { String origin = "http://custom.origin.quarkus"; String methods = "GET,POST"; - String headers = "X-Custom, content-type"; + String headers = "X-Custom,content-type"; given().header("Origin", origin) .header("Access-Control-Request-Method", methods) .header("Access-Control-Request-Headers", headers) @@ -35,12 +36,29 @@ public void corsPreflightTestServlet() { .header("Access-Control-Allow-Headers", headers); } + @Test + public void corsPreflightTestUnmatchedHeader() { + String origin = "http://custom.origin.quarkus"; + String methods = "GET,POST"; + String headers = "X-Customs,content-types"; + given().header("Origin", origin) + .header("Access-Control-Request-Method", methods) + .header("Access-Control-Request-Headers", headers) + .when() + .options("/test").then() + .statusCode(200) + .header("Access-Control-Allow-Origin", origin) + .header("Access-Control-Allow-Methods", methods) + .header("Access-Control-Allow-Credentials", "true") + .header("Access-Control-Allow-Headers", nullValue()); + } + @Test @DisplayName("Handles a direct CORS request correctly") public void corsNoPreflightTestServlet() { String origin = "http://custom.origin.quarkus"; String methods = "GET,POST"; - String headers = "x-custom, CONTENT-TYPE"; + String headers = "x-custom,CONTENT-TYPE"; given().header("Origin", origin) .header("Access-Control-Request-Method", methods) .header("Access-Control-Request-Headers", headers) diff --git a/extensions/vertx-http/deployment/src/test/resources/conf/cors-config.properties b/extensions/vertx-http/deployment/src/test/resources/conf/cors-config.properties index f202ef1064bf6..59bdec217dfd2 100644 --- a/extensions/vertx-http/deployment/src/test/resources/conf/cors-config.properties +++ b/extensions/vertx-http/deployment/src/test/resources/conf/cors-config.properties @@ -2,4 +2,4 @@ quarkus.http.cors=true # whitespaces added to test that they are not taken into account config is parsed quarkus.http.cors.methods=GET, OPTIONS, POST quarkus.http.cors.access-control-allow-credentials=true -quarkus.http.cors.access-control-allow-headers=x-custom,CONTENT-TYPE +quarkus.http.cors.headers=x-custom,CONTENT-TYPE diff --git a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/cors/CORSFilter.java b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/cors/CORSFilter.java index 4a7fee1a14e4f..c5b476789e188 100644 --- a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/cors/CORSFilter.java +++ b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/cors/CORSFilter.java @@ -2,7 +2,9 @@ import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.regex.Pattern; @@ -98,24 +100,25 @@ private void processRequestedHeaders(HttpServerResponse response, String allowHe if (isConfiguredWithWildcard(corsConfig.headers)) { response.headers().set(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, allowHeadersValue); } else { - List requestedHeaders; + Map requestedHeaders; String[] allowedParts = COMMA_SEPARATED_SPLIT_REGEX.split(allowHeadersValue); - requestedHeaders = new ArrayList<>(allowedParts.length); + requestedHeaders = new HashMap<>(); for (String requestedHeader : allowedParts) { - requestedHeaders.add(requestedHeader.toLowerCase()); + requestedHeaders.put(requestedHeader.toLowerCase(), requestedHeader); } List corsConfigHeaders = corsConfig.headers.get(); StringBuilder allowedHeaders = new StringBuilder(); boolean isFirst = true; for (String configHeader : corsConfigHeaders) { - if (requestedHeaders.contains(configHeader.toLowerCase())) { + String configHeaderLowerCase = configHeader.toLowerCase(); + if (requestedHeaders.containsKey(configHeaderLowerCase)) { if (isFirst) { isFirst = false; } else { allowedHeaders.append(','); } - allowedHeaders.append(configHeader); + allowedHeaders.append(requestedHeaders.get(configHeaderLowerCase)); } }