From 898b038d2d4b1f12da8ae36f68e0135ba08a48b1 Mon Sep 17 00:00:00 2001 From: Georgios Andrianakis Date: Mon, 23 Sep 2024 14:32:49 +0300 Subject: [PATCH] Support @HEAD and @OPTIONS in sub-resources This is the same exact support as exists for normal Resource methods Fixes: #43422 --- .../handlers/ResourceLocatorHandler.java | 31 ++++++++++++++++--- .../resource/basic/ParameterSubResTest.java | 14 +++++++++ 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/handlers/ResourceLocatorHandler.java b/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/handlers/ResourceLocatorHandler.java index 0b3529f4f539d..83215887b91af 100644 --- a/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/handlers/ResourceLocatorHandler.java +++ b/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/handlers/ResourceLocatorHandler.java @@ -9,6 +9,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; +import jakarta.ws.rs.HttpMethod; import jakarta.ws.rs.WebApplicationException; import jakarta.ws.rs.container.CompletionCallback; import jakarta.ws.rs.core.Response; @@ -58,14 +59,34 @@ public void onComplete(Throwable throwable) { if (target == null) { throw new RuntimeException("Resource locator method returned object that was not a resource: " + locator); } + RequestMapper mapper = target.get(requestContext.getMethod()); boolean hadNullMethodMapper = false; if (mapper == null) { - mapper = target.get(null); //another layer of resource locators maybe - // we set this without checking if we matched, but we only use it after - // we check for a null mapper, so by the time we use it, it must have meant that - // we had a matcher for a null method - hadNullMethodMapper = true; + String requestMethod = requestContext.getMethod(); + if (requestMethod.equals(HttpMethod.HEAD)) { + mapper = target.get(HttpMethod.GET); + } else if (requestMethod.equals(HttpMethod.OPTIONS)) { + Set allowedMethods = new HashSet<>(); + for (String method : target.keySet()) { + if (method == null) { + continue; + } + allowedMethods.add(method); + } + allowedMethods.add(HttpMethod.OPTIONS); + allowedMethods.add(HttpMethod.HEAD); + requestContext.abortWith(Response.ok().allow(allowedMethods).build()); + return; + } + + if (mapper == null) { + mapper = target.get(null); //another layer of resource locators maybe + // we set this without checking if we matched, but we only use it after + // we check for a null mapper, so by the time we use it, it must have meant that + // we had a matcher for a null method + hadNullMethodMapper = true; + } } if (mapper == null) { throw new WebApplicationException(Response.status(Response.Status.METHOD_NOT_ALLOWED.getStatusCode()).build()); diff --git a/independent-projects/resteasy-reactive/server/vertx/src/test/java/org/jboss/resteasy/reactive/server/vertx/test/resource/basic/ParameterSubResTest.java b/independent-projects/resteasy-reactive/server/vertx/src/test/java/org/jboss/resteasy/reactive/server/vertx/test/resource/basic/ParameterSubResTest.java index 5f533daa56e6f..e4c8498852242 100644 --- a/independent-projects/resteasy-reactive/server/vertx/src/test/java/org/jboss/resteasy/reactive/server/vertx/test/resource/basic/ParameterSubResTest.java +++ b/independent-projects/resteasy-reactive/server/vertx/src/test/java/org/jboss/resteasy/reactive/server/vertx/test/resource/basic/ParameterSubResTest.java @@ -96,6 +96,20 @@ public void testSubResource() throws Exception { Assertions.assertEquals("Boo! - fred", response.readEntity(String.class), "Wrong content of response"); } + @Test + @DisplayName("Test Sub Resource - HEAD") + public void testSubResourceHead() throws Exception { + Response response = client.target(generateURL("/path/sub/fred")).request().head(); + Assertions.assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); + } + + @Test + @DisplayName("Test Sub Resource - OPTIONS") + public void testSubResourceOptions() throws Exception { + Response response = client.target(generateURL("/path/sub/fred")).request().options(); + Assertions.assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); + } + @Test @DisplayName("Test Return Sub Resource As Class") public void testReturnSubResourceAsClass() throws Exception {