From 4780fdcaad081021e3890f39df5368891d923c2f Mon Sep 17 00:00:00 2001 From: Mike Neilson Date: Wed, 3 Sep 2025 18:02:45 +0000 Subject: [PATCH] Repsond to Options request with reasonable values. Fixes #1175. --- .../src/main/java/cwms/cda/ApiServlet.java | 6 ++ .../java/cwms/cda/api/BaseLineTestIT.java | 58 +++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 cwms-data-api/src/test/java/cwms/cda/api/BaseLineTestIT.java diff --git a/cwms-data-api/src/main/java/cwms/cda/ApiServlet.java b/cwms-data-api/src/main/java/cwms/cda/ApiServlet.java index c308bcb1c6..fb0e14b2fc 100644 --- a/cwms-data-api/src/main/java/cwms/cda/ApiServlet.java +++ b/cwms-data-api/src/main/java/cwms/cda/ApiServlet.java @@ -504,6 +504,12 @@ public void init() { ctx.json(errResponse); }) .routes(this::configureRoutes) + .options("/*", ctx -> { + ctx.header("Access-Control-Allow-Origin", "*"); // Allow requests from any origin + ctx.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS"); // Specify allowed methods + ctx.header("Access-Control-Allow-Headers", "Content-Type, Authorization"); // Specify allowed headers + ctx.status(200); // Respond with a 200 OK status + }) .javalinServlet(); logger.atInfo().log("Javalin initialized."); } diff --git a/cwms-data-api/src/test/java/cwms/cda/api/BaseLineTestIT.java b/cwms-data-api/src/test/java/cwms/cda/api/BaseLineTestIT.java new file mode 100644 index 0000000000..2b40648c96 --- /dev/null +++ b/cwms-data-api/src/test/java/cwms/cda/api/BaseLineTestIT.java @@ -0,0 +1,58 @@ +package cwms.cda.api; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; + +import javax.servlet.http.HttpServletResponse; + +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import fixtures.CwmsDataApiSetupCallback; +import io.restassured.filter.log.LogDetail; + +/** + * Location for tests that aren't specifically related to a given endpoint. + */ +@Tag("integration") +@ExtendWith(CwmsDataApiSetupCallback.class) +class BaseLineTestIT extends DataApiTestIT { + + @ParameterizedTest + @ValueSource(strings = {"/blobs/", "/timeseries", "/levels"}) + void test_options_handling_known_url(String url) throws Exception { + given() + .log().ifValidationFails(LogDetail.ALL,true) + .when() + .redirects().follow(true) + .redirects().max(3) + .options(url) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_OK)) + .header("Access-Control-Allow-Methods", equalTo("GET, POST, PUT, DELETE, OPTIONS")) + .header("Access-Control-Allow-Headers", equalTo("Content-Type, Authorization")); + } + + @ParameterizedTest + @ValueSource(strings = {"/flurgle/", "/blah/", "/levels-i-do-not-exist"}) + void test_options_handling_unknown_url(String url) throws Exception { + given() + .log().ifValidationFails(LogDetail.ALL,true) + .when() + .redirects().follow(true) + .redirects().max(3) + .options(url) + .then() + .log().ifValidationFails(LogDetail.ALL,true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_OK)) + .header("Access-Control-Allow-Methods", nullValue()) + .header("Access-Control-Allow-Headers", nullValue()); + } +}