diff --git a/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/main/java/io/quarkus/resteasy/reactive/server/deployment/CustomResourceProducersGenerator.java b/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/main/java/io/quarkus/resteasy/reactive/server/deployment/CustomResourceProducersGenerator.java index 802da5d03397b..a5e08aefd1dbb 100644 --- a/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/main/java/io/quarkus/resteasy/reactive/server/deployment/CustomResourceProducersGenerator.java +++ b/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/main/java/io/quarkus/resteasy/reactive/server/deployment/CustomResourceProducersGenerator.java @@ -151,8 +151,8 @@ public static void generate(Map resourcesThatNeedCustomProd ResultHandle quarkusRestContextHandle = m.invokeVirtualMethod(getContextMethodCreator.getMethodDescriptor(), m.getThis()); ResultHandle extractorHandle = m.newInstance( - MethodDescriptor.ofConstructor(PathParamExtractor.class, int.class, boolean.class), - m.getMethodParam(0), m.load(false)); + MethodDescriptor.ofConstructor(PathParamExtractor.class, int.class, boolean.class, boolean.class), + m.getMethodParam(0), m.load(false), m.load(true)); ResultHandle resultHandle = m.invokeVirtualMethod(MethodDescriptor.ofMethod(PathParamExtractor.class, "extractParameter", Object.class, ResteasyReactiveRequestContext.class), extractorHandle, quarkusRestContextHandle); diff --git a/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/main/java/io/quarkus/resteasy/reactive/server/deployment/QuarkusServerEndpointIndexer.java b/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/main/java/io/quarkus/resteasy/reactive/server/deployment/QuarkusServerEndpointIndexer.java index 4271339ce3c8f..43b6427f271f6 100644 --- a/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/main/java/io/quarkus/resteasy/reactive/server/deployment/QuarkusServerEndpointIndexer.java +++ b/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/main/java/io/quarkus/resteasy/reactive/server/deployment/QuarkusServerEndpointIndexer.java @@ -10,6 +10,7 @@ import java.util.function.Predicate; import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.PathSegment; import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.ClassInfo; @@ -26,6 +27,7 @@ import org.jboss.resteasy.reactive.server.core.parameters.converters.NoopParameterConverter; import org.jboss.resteasy.reactive.server.core.parameters.converters.ParameterConverter; import org.jboss.resteasy.reactive.server.core.parameters.converters.ParameterConverterSupplier; +import org.jboss.resteasy.reactive.server.core.parameters.converters.PathSegmentParamConverter; import org.jboss.resteasy.reactive.server.core.parameters.converters.RuntimeResolvedConverter; import org.jboss.resteasy.reactive.server.processor.ServerEndpointIndexer; import org.jboss.resteasy.reactive.server.processor.ServerIndexedParameter; @@ -133,6 +135,8 @@ protected ParameterConverterSupplier extractConverter(String elementType, IndexV if (delegate == null) throw new RuntimeException("Failed to find converter for " + elementType); return delegate; + } else if (elementType.equals(PathSegment.class.getName())) { + return new PathSegmentParamConverter.Supplier(); } MethodDescriptor fromString = null; diff --git a/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/path/HelloResource.java b/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/path/HelloResource.java index c172e743f13df..900fd9752b11a 100644 --- a/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/path/HelloResource.java +++ b/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/path/HelloResource.java @@ -1,7 +1,11 @@ package io.quarkus.resteasy.reactive.server.test.path; +import java.util.List; + import javax.ws.rs.GET; import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.core.PathSegment; /** * Per spec: @@ -25,4 +29,10 @@ public String hello() { public String nested() { return "world hello"; } + + @GET + @Path("other/{keyword:.*}") + public String searchByKeywords(@PathParam("keyword") List keywords) { + return keywords.toString(); + } } diff --git a/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/path/RestPathTestCase.java b/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/path/RestPathTestCase.java index 96acfeb0d4fcc..66579e73e7c41 100644 --- a/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/path/RestPathTestCase.java +++ b/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/path/RestPathTestCase.java @@ -25,4 +25,11 @@ public void testRestPath() { RestAssured.when().get("/app/foo/hello").then().statusCode(200).body(Matchers.is("hello")); RestAssured.when().get("/app/foo/hello/nested").then().statusCode(200).body(Matchers.is("world hello")); } + + @Test + public void testListOfPathParams() { + RestAssured.basePath = "/"; + RestAssured.when().get("/app/foo/hello/other/bar/baz/boo/bob").then().statusCode(200) + .body(Matchers.is("[bar, baz, boo, bob]")); + } } diff --git a/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/parameters/PathParamExtractor.java b/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/parameters/PathParamExtractor.java index 3a018f4651cc5..60d592571dba9 100644 --- a/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/parameters/PathParamExtractor.java +++ b/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/parameters/PathParamExtractor.java @@ -1,5 +1,6 @@ package org.jboss.resteasy.reactive.server.core.parameters; +import java.util.List; import org.jboss.resteasy.reactive.common.util.Encode; import org.jboss.resteasy.reactive.server.core.ResteasyReactiveRequestContext; @@ -7,18 +8,24 @@ public class PathParamExtractor implements ParameterExtractor { private final int index; private final boolean encoded; + private final boolean single; - public PathParamExtractor(int index, boolean encoded) { + public PathParamExtractor(int index, boolean encoded, boolean single) { this.index = index; this.encoded = encoded; + this.single = single; } @Override public Object extractParameter(ResteasyReactiveRequestContext context) { String pathParam = context.getPathParam(index); if (encoded) { - return Encode.encodeQueryParam(pathParam); + pathParam = Encode.encodeQueryParam(pathParam); + } + if (single) { + return pathParam; + } else { + return List.of(pathParam.split("/")); } - return pathParam; } } diff --git a/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/startup/RuntimeResourceDeployment.java b/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/startup/RuntimeResourceDeployment.java index 3043567e1988e..51712d5cd9e07 100644 --- a/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/startup/RuntimeResourceDeployment.java +++ b/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/startup/RuntimeResourceDeployment.java @@ -538,7 +538,7 @@ public ParameterExtractor parameterExtractor(Map pathParameterI extractor = new NullParamExtractor(); } } else { - extractor = new PathParamExtractor(index, encoded); + extractor = new PathParamExtractor(index, encoded, single); } return extractor; case CONTEXT: