diff --git a/extensions/resteasy-reactive/jaxrs-client-reactive/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/JaxrsClientReactiveProcessor.java b/extensions/resteasy-reactive/jaxrs-client-reactive/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/JaxrsClientReactiveProcessor.java index eb2d502468585..951e5103a2c89 100644 --- a/extensions/resteasy-reactive/jaxrs-client-reactive/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/JaxrsClientReactiveProcessor.java +++ b/extensions/resteasy-reactive/jaxrs-client-reactive/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/JaxrsClientReactiveProcessor.java @@ -9,6 +9,7 @@ import static org.jboss.resteasy.reactive.common.processor.EndpointIndexer.extractProducesConsumesValues; import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.COMPLETION_STAGE; import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.CONSUMES; +import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.ENCODED; import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.FORM_PARAM; import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.MULTI; import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.OBJECT; @@ -58,6 +59,7 @@ import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.MultivaluedHashMap; import jakarta.ws.rs.core.MultivaluedMap; +import jakarta.ws.rs.core.UriBuilder; import jakarta.ws.rs.ext.ParamConverter; import jakarta.ws.rs.ext.ParamConverterProvider; @@ -100,6 +102,7 @@ import org.jboss.resteasy.reactive.common.core.GenericTypeMapping; import org.jboss.resteasy.reactive.common.core.ResponseBuilderFactory; import org.jboss.resteasy.reactive.common.core.Serialisers; +import org.jboss.resteasy.reactive.common.jaxrs.UriBuilderImpl; import org.jboss.resteasy.reactive.common.model.MaybeRestClientInterface; import org.jboss.resteasy.reactive.common.model.MethodParameter; import org.jboss.resteasy.reactive.common.model.ParameterType; @@ -806,15 +809,21 @@ A more full example of generated client (with sub-resource) can is at the bottom MethodDescriptor constructorDesc = MethodDescriptor.ofConstructor(name, WebTarget.class.getName(), List.class); try (ClassRestClientContext classContext = new ClassRestClientContext(name, constructorDesc, generatedClasses, RestClientBase.class, Closeable.class.getName(), restClientInterface.getClassName())) { - classContext.constructor.invokeSpecialMethod(MethodDescriptor.ofConstructor(RestClientBase.class, List.class), classContext.constructor.getThis(), classContext.constructor.getMethodParam(1)); - AssignableResultHandle baseTarget = classContext.constructor.createVariable(WebTarget.class); + AssignableResultHandle baseTarget = classContext.constructor.createVariable(WebTargetImpl.class); + if (restClientInterface.isEncoded()) { + classContext.constructor.assign(baseTarget, + disableEncodingForWebTarget(classContext.constructor, classContext.constructor.getMethodParam(0))); + } else { + classContext.constructor.assign(baseTarget, classContext.constructor.getMethodParam(0)); + } + classContext.constructor.assign(baseTarget, - classContext.constructor.invokeInterfaceMethod( - MethodDescriptor.ofMethod(WebTarget.class, "path", WebTarget.class, String.class), - classContext.constructor.getMethodParam(0), + classContext.constructor.invokeVirtualMethod( + MethodDescriptor.ofMethod(WebTargetImpl.class, "path", WebTargetImpl.class, String.class), + baseTarget, classContext.constructor.load(restClientInterface.getPath()))); FieldDescriptor baseTargetField = classContext.classCreator .getFieldCreator("baseTarget", WebTargetImpl.class.getName()) @@ -893,6 +902,9 @@ A more full example of generated client (with sub-resource) can is at the bottom AssignableResultHandle methodTarget = methodCreator.createVariable(WebTarget.class); methodCreator.assign(methodTarget, methodCreator.readInstanceField(webTargetForMethod, methodCreator.getThis())); + if (!restClientInterface.isEncoded() && method.isEncoded()) { + methodCreator.assign(methodTarget, disableEncodingForWebTarget(methodCreator, methodTarget)); + } Integer bodyParameterIdx = null; Map invocationBuilderEnrichers = new HashMap<>(); @@ -903,8 +915,20 @@ A more full example of generated client (with sub-resource) can is at the bottom AssignableResultHandle formParams = null; + boolean lastEncodingEnabledByParam = true; for (int paramIdx = 0; paramIdx < method.getParameters().length; ++paramIdx) { MethodParameter param = method.getParameters()[paramIdx]; + if (!restClientInterface.isEncoded() && !method.isEncoded()) { + boolean needsDisabling = isParamAlreadyEncoded(param); + if (lastEncodingEnabledByParam && needsDisabling) { + methodCreator.assign(methodTarget, disableEncodingForWebTarget(methodCreator, methodTarget)); + lastEncodingEnabledByParam = false; + } else if (!lastEncodingEnabledByParam && !needsDisabling) { + methodCreator.assign(methodTarget, enableEncodingForWebTarget(methodCreator, methodTarget)); + lastEncodingEnabledByParam = true; + } + } + if (param.parameterType == ParameterType.QUERY) { //TODO: converters @@ -1080,6 +1104,40 @@ A more full example of generated client (with sub-resource) can is at the bottom } + /** + * The @Encoded annotation is only supported in path/query/matrix/form params. + */ + private boolean isParamAlreadyEncoded(MethodParameter param) { + return param.encoded + && (param.parameterType == ParameterType.PATH + || param.parameterType == ParameterType.QUERY + || param.parameterType == ParameterType.FORM + || param.parameterType == ParameterType.MATRIX); + } + + private ResultHandle disableEncodingForWebTarget(BytecodeCreator creator, ResultHandle baseTarget) { + return setEncodingForWebTarget(creator, baseTarget, false); + } + + private ResultHandle enableEncodingForWebTarget(BytecodeCreator creator, ResultHandle baseTarget) { + return setEncodingForWebTarget(creator, baseTarget, true); + } + + private ResultHandle setEncodingForWebTarget(BytecodeCreator creator, ResultHandle baseTarget, boolean encode) { + ResultHandle webTarget = creator.invokeVirtualMethod( + MethodDescriptor.ofMethod(WebTargetImpl.class, "clone", WebTargetImpl.class), baseTarget); + + ResultHandle uriBuilderImpl = creator.invokeVirtualMethod( + MethodDescriptor.ofMethod(WebTargetImpl.class, "getUriBuilderUnsafe", UriBuilderImpl.class), + webTarget); + + creator.invokeVirtualMethod( + MethodDescriptor.ofMethod(UriBuilderImpl.class, "encode", UriBuilder.class, boolean.class), + uriBuilderImpl, creator.load(encode)); + + return webTarget; + } + private boolean isMultipart(String[] consumes, MethodParameter[] methodParameters) { if (consumes != null) { for (String mimeType : consumes) { @@ -1201,8 +1259,16 @@ private void handleSubResourceMethod(List AssignableResultHandle constructorTarget = createWebTargetForMethod(ownerContext.constructor, ownerTarget, method); + boolean encodingEnabled = true; + FieldDescriptor forMethodTargetDesc = ownerContext.classCreator .getFieldCreator("targetInOwner" + methodIndex, WebTargetImpl.class).getFieldDescriptor(); + if (subInterface.hasDeclaredAnnotation(ENCODED)) { + ownerContext.constructor.assign(constructorTarget, + disableEncodingForWebTarget(ownerContext.constructor, constructorTarget)); + encodingEnabled = false; + } + ownerContext.constructor.writeInstanceField(forMethodTargetDesc, ownerContext.constructor.getThis(), constructorTarget); @@ -1214,9 +1280,26 @@ private void handleSubResourceMethod(List AssignableResultHandle client = createRestClientField(name, ownerContext.classCreator, ownerMethod); AssignableResultHandle webTarget = ownerMethod.createVariable(WebTarget.class); ownerMethod.assign(webTarget, ownerMethod.readInstanceField(forMethodTargetDesc, ownerMethod.getThis())); + + if (encodingEnabled && method.isEncoded()) { + ownerMethod.assign(webTarget, disableEncodingForWebTarget(ownerMethod, webTarget)); + } + // Setup Path param from current method + boolean lastEncodingEnabledByParam = true; for (int i = 0; i < method.getParameters().length; i++) { MethodParameter param = method.getParameters()[i]; + if (encodingEnabled && !method.isEncoded()) { + boolean needsDisabling = isParamAlreadyEncoded(param); + if (lastEncodingEnabledByParam && needsDisabling) { + ownerMethod.assign(webTarget, disableEncodingForWebTarget(ownerMethod, webTarget)); + lastEncodingEnabledByParam = false; + } else if (!lastEncodingEnabledByParam && !needsDisabling) { + ownerMethod.assign(webTarget, enableEncodingForWebTarget(ownerMethod, webTarget)); + lastEncodingEnabledByParam = true; + } + } + if (param.parameterType == ParameterType.PATH) { ResultHandle paramValue = ownerMethod.getMethodParam(i); // methodTarget = methodTarget.resolveTemplate(paramname, paramvalue); @@ -1310,17 +1393,34 @@ private void handleSubResourceMethod(List AssignableResultHandle methodTarget = subMethodCreator.createVariable(WebTarget.class); subMethodCreator.assign(methodTarget, subMethodCreator.readInstanceField(subMethodTarget, subMethodCreator.getThis())); + if (encodingEnabled && subMethod.isEncoded()) { + subMethodCreator.assign(methodTarget, disableEncodingForWebTarget(subMethodCreator, methodTarget)); + } ResultHandle bodyParameterValue = null; AssignableResultHandle formParams = null; Map invocationBuilderEnrichers = new HashMap<>(); + boolean lastEncodingEnabledBySubParam = true; int inheritedParamIndex = 0; for (SubResourceParameter subParamField : subParamFields) { inheritedParamIndex++; MethodParameter param = subParamField.methodParameter; ResultHandle paramValue = subMethodCreator.readInstanceField(subParamField.field, subMethodCreator.getThis()); + if (encodingEnabled && !subMethod.isEncoded()) { + boolean needsDisabling = isParamAlreadyEncoded(param); + if (lastEncodingEnabledBySubParam && needsDisabling) { + subMethodCreator.assign(methodTarget, + disableEncodingForWebTarget(subMethodCreator, methodTarget)); + lastEncodingEnabledBySubParam = false; + } else if (!lastEncodingEnabledBySubParam && !needsDisabling) { + subMethodCreator.assign(methodTarget, + enableEncodingForWebTarget(subMethodCreator, methodTarget)); + lastEncodingEnabledBySubParam = true; + } + } + if (param.parameterType == ParameterType.QUERY) { //TODO: converters @@ -1435,6 +1535,19 @@ private void handleSubResourceMethod(List // handle sub-method parameters: for (int paramIdx = 0; paramIdx < subMethod.getParameters().length; ++paramIdx) { MethodParameter param = subMethod.getParameters()[paramIdx]; + if (encodingEnabled && !subMethod.isEncoded()) { + boolean needsDisabling = isParamAlreadyEncoded(param); + if (lastEncodingEnabledBySubParam && needsDisabling) { + subMethodCreator.assign(methodTarget, + disableEncodingForWebTarget(subMethodCreator, methodTarget)); + lastEncodingEnabledBySubParam = false; + } else if (!lastEncodingEnabledBySubParam && !needsDisabling) { + subMethodCreator.assign(methodTarget, + enableEncodingForWebTarget(subMethodCreator, methodTarget)); + lastEncodingEnabledBySubParam = true; + } + } + if (param.parameterType == ParameterType.QUERY) { //TODO: converters @@ -2338,7 +2451,17 @@ private void addSubBeanParamData(MethodInfo jandexMethod, BytecodeCreator method BytecodeCreator invoEnricher = invocationBuilderEnricher.ifNotNull(invocationBuilderEnricher.getMethodParam(1)) .trueBranch(); + boolean encodingEnabled = true; for (Item item : beanParamItems) { + + if (encodingEnabled && item.isEncoded()) { + creator.assign(target, disableEncodingForWebTarget(creator, target)); + encodingEnabled = false; + } else if (!encodingEnabled && !item.isEncoded()) { + creator.assign(target, enableEncodingForWebTarget(creator, target)); + encodingEnabled = true; + } + switch (item.type()) { case BEAN_PARAM: BeanParamItem beanParamItem = (BeanParamItem) item; diff --git a/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/encoded/ClientWithPathParamAndEncodedTest.java b/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/encoded/ClientWithPathParamAndEncodedTest.java new file mode 100644 index 0000000000000..c049ca116964d --- /dev/null +++ b/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/encoded/ClientWithPathParamAndEncodedTest.java @@ -0,0 +1,159 @@ +package io.quarkus.rest.client.reactive.encoded; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.net.URI; + +import jakarta.ws.rs.Encoded; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.QueryParam; + +import org.eclipse.microprofile.rest.client.RestClientBuilder; +import org.jboss.resteasy.reactive.ClientWebApplicationException; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.test.QuarkusUnitTest; +import io.quarkus.test.common.http.TestHTTPResource; + +public class ClientWithPathParamAndEncodedTest { + + @RegisterExtension + static final QuarkusUnitTest TEST = new QuarkusUnitTest(); + + @TestHTTPResource + URI baseUri; + + @Test + public void testClientWithoutEncoded() { + ClientWithoutEncoded client = RestClientBuilder.newBuilder() + .baseUri(baseUri) + .build(ClientWithoutEncoded.class); + ClientWebApplicationException ex = assertThrows(ClientWebApplicationException.class, () -> client.call("a/b")); + assertTrue(ex.getMessage().contains("Not Found")); + } + + @Test + public void testClientWithEncodedInParameter() { + ClientWithEncodedInParameter client = RestClientBuilder.newBuilder() + .baseUri(baseUri) + .build(ClientWithEncodedInParameter.class); + assertEquals("Hello A/B", client.call("a/b")); + assertEquals("Hello A/B/C", client.sub().call("b/c")); + } + + @Test + public void testClientWithEncodedInMethod() { + ClientWithEncodedInMethod client = RestClientBuilder.newBuilder() + .baseUri(baseUri) + .build(ClientWithEncodedInMethod.class); + assertEquals("Hello A/B", client.call("a/b")); + assertEquals("Hello A/B/C", client.sub1().call("b/c")); + assertEquals("Hello A/B/C", client.sub2().call("b/c")); + assertEquals("Hello A/B/C", client.sub3().call("b/c")); + } + + @Test + public void testClientWithEncodedInClass() { + ClientWithEncodedInClass client = RestClientBuilder.newBuilder() + .baseUri(baseUri) + .build(ClientWithEncodedInClass.class); + assertEquals("Hello A/B", client.call("a/b")); + assertEquals("Hello A/B/C", client.sub().call("b/c")); + } + + @Path("/server") + public interface ClientWithoutEncoded { + @GET + @Path("/{path}") + String call(@PathParam("path") String path); + + @GET + @Path("/{path}") + String callWithQuery(@PathParam("path") String path, @QueryParam("query") String query); + } + + @Path("/server") + public interface ClientWithEncodedInParameter { + @GET + @Path("/{path}") + String call(@Encoded @PathParam("path") String path); + + @Path("/a") + SubClientWithEncodedInParameter sub(); + } + + @Path("/server") + public interface ClientWithEncodedInMethod { + @Encoded + @GET + @Path("/{path}") + String call(@PathParam("path") String path); + + @Encoded + @Path("/a") + SubClientWithoutEncoded sub1(); + + @Path("/a") + SubClientWithEncodedInMethod sub2(); + + @Path("/a") + SubClientWithEncodedInClass sub3(); + } + + @Encoded + @Path("/server") + public interface ClientWithEncodedInClass { + @GET + @Path("/{path}") + String call(@PathParam("path") String path); + + @Path("/a") + SubClientWithoutEncoded sub(); + } + + public interface SubClientWithoutEncoded { + @GET + @Path("/{path}") + String call(@PathParam("path") String path); + } + + public interface SubClientWithEncodedInMethod { + @Encoded + @GET + @Path("/{path}") + String call(@PathParam("path") String path); + } + + @Encoded + public interface SubClientWithEncodedInClass { + @GET + @Path("/{path}") + String call(@PathParam("path") String path); + } + + public interface SubClientWithEncodedInParameter { + @GET + @Path("/{path}") + String call(@Encoded @PathParam("path") String path); + } + + @Path("/server") + static class Resource { + @GET + @Path("/a/b") + public String get() { + return "Hello A/B"; + } + + @GET + @Path("/a/b/c") + public String getForSubResource() { + return "Hello A/B/C"; + } + } +} diff --git a/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/encoded/ClientWithQueryParamAndEncodedTest.java b/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/encoded/ClientWithQueryParamAndEncodedTest.java new file mode 100644 index 0000000000000..b7be2bd57674b --- /dev/null +++ b/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/encoded/ClientWithQueryParamAndEncodedTest.java @@ -0,0 +1,149 @@ +package io.quarkus.rest.client.reactive.encoded; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.net.URI; + +import jakarta.ws.rs.Encoded; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.core.UriInfo; + +import org.eclipse.microprofile.rest.client.RestClientBuilder; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.test.QuarkusUnitTest; +import io.quarkus.test.common.http.TestHTTPResource; + +public class ClientWithQueryParamAndEncodedTest { + + @RegisterExtension + static final QuarkusUnitTest TEST = new QuarkusUnitTest(); + + @TestHTTPResource + URI baseUri; + + @Test + public void testClientWithoutEncoded() { + ClientWithoutEncoded client = RestClientBuilder.newBuilder() + .baseUri(baseUri) + .build(ClientWithoutEncoded.class); + assertEquals("Hello query=%2524value", client.call("%24value")); + } + + @Test + public void testClientWithEncodedInParameter() { + ClientWithEncodedInParameter client = RestClientBuilder.newBuilder() + .baseUri(baseUri) + .build(ClientWithEncodedInParameter.class); + assertEquals("Hello query=%24value", client.call("%24value")); + assertEquals("Hello query1=%2524value&query2=%24value&query3=%2524value", + client.call("%24value", "%24value", "%24value")); + assertEquals("Hello subQuery=%24value", client.sub().call("%24value")); + } + + @Test + public void testClientWithEncodedInMethod() { + ClientWithEncodedInMethod client = RestClientBuilder.newBuilder() + .baseUri(baseUri) + .build(ClientWithEncodedInMethod.class); + assertEquals("Hello query=%24value", client.call("%24value")); + assertEquals("Hello subQuery=%24value", client.sub1().call("%24value")); + assertEquals("Hello subQuery=%24value", client.sub2().call("%24value")); + assertEquals("Hello subQuery=%24value", client.sub3().call("%24value")); + } + + @Test + public void testClientWithEncodedInClass() { + ClientWithEncodedInClass client = RestClientBuilder.newBuilder() + .baseUri(baseUri) + .build(ClientWithEncodedInClass.class); + assertEquals("Hello query=%24value", client.call("%24value")); + assertEquals("Hello subQuery=%24value", client.sub().call("%24value")); + } + + @Path("/server") + public interface ClientWithoutEncoded { + @GET + String call(@QueryParam("query") String query); + } + + @Path("/server") + public interface ClientWithEncodedInParameter { + @GET + String call(@Encoded @QueryParam("query") String query); + + @GET + String call(@QueryParam("query1") String query1, @Encoded @QueryParam("query2") String query2, + @QueryParam("query3") String query3); + + @Path("/a") + SubClientWithEncodedInParameter sub(); + } + + @Path("/server") + public interface ClientWithEncodedInMethod { + @Encoded + @GET + String call(@QueryParam("query") String query); + + @Encoded + @Path("/a") + SubClientWithoutEncoded sub1(); + + @Path("/a") + SubClientWithEncodedInMethod sub2(); + + @Path("/a") + SubClientWithEncodedInClass sub3(); + } + + @Encoded + @Path("/server") + public interface ClientWithEncodedInClass { + @GET + String call(@QueryParam("query") String query); + + @Path("/a") + SubClientWithoutEncoded sub(); + } + + public interface SubClientWithoutEncoded { + @GET + String call(@QueryParam("subQuery") String subQuery); + } + + @Encoded + public interface SubClientWithEncodedInClass { + @GET + String call(@QueryParam("subQuery") String subQuery); + } + + public interface SubClientWithEncodedInMethod { + @Encoded + @GET + String call(@QueryParam("subQuery") String subQuery); + } + + public interface SubClientWithEncodedInParameter { + @GET + String call(@Encoded @QueryParam("subQuery") String subQuery); + } + + @Path("/server") + static class Resource { + @GET + public String get(@Context UriInfo uriInfo) { + return "Hello " + uriInfo.getRequestUri().getRawQuery(); + } + + @GET + @Path("/a") + public String getFromA(@Context UriInfo uriInfo) { + return "Hello " + uriInfo.getRequestUri().getRawQuery(); + } + } +} diff --git a/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/beanparam/BeanParamItem.java b/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/beanparam/BeanParamItem.java index 35abc4465f858..cad40a43b17d8 100644 --- a/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/beanparam/BeanParamItem.java +++ b/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/beanparam/BeanParamItem.java @@ -7,7 +7,7 @@ public class BeanParamItem extends Item { private final String className; public BeanParamItem(String fieldName, List items, String className, ValueExtractor extractor) { - super(fieldName, ItemType.BEAN_PARAM, extractor); + super(fieldName, ItemType.BEAN_PARAM, false, extractor); this.items = items; this.className = className; } diff --git a/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/beanparam/BeanParamParser.java b/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/beanparam/BeanParamParser.java index b85ccd9813516..fa2a9595cf73c 100644 --- a/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/beanparam/BeanParamParser.java +++ b/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/beanparam/BeanParamParser.java @@ -2,6 +2,7 @@ import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.BEAN_PARAM; import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.COOKIE_PARAM; +import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.ENCODED; import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.FORM_PARAM; import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.HEADER_PARAM; import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.PATH_PARAM; @@ -62,19 +63,23 @@ private static List parseInternal(ClassInfo beanParamClass, IndexView inde resultList.addAll(paramItemsForFieldsAndMethods(beanParamClass, QUERY_PARAM, (annotationValue, fieldInfo) -> new QueryParamItem(fieldInfo.name(), annotationValue, + fieldInfo.hasDeclaredAnnotation(ENCODED), new FieldExtractor(null, fieldInfo.name(), fieldInfo.declaringClass().name().toString()), fieldInfo.type()), (annotationValue, getterMethod) -> new QueryParamItem(getterMethod.name(), annotationValue, + getterMethod.hasDeclaredAnnotation(ENCODED), new GetterExtractor(getterMethod), getterMethod.returnType()))); resultList.addAll(paramItemsForFieldsAndMethods(beanParamClass, REST_QUERY_PARAM, (annotationValue, fieldInfo) -> new QueryParamItem(fieldInfo.name(), annotationValue != null ? annotationValue : fieldInfo.name(), + fieldInfo.hasDeclaredAnnotation(ENCODED), new FieldExtractor(null, fieldInfo.name(), fieldInfo.declaringClass().name().toString()), fieldInfo.type()), (annotationValue, getterMethod) -> new QueryParamItem(getterMethod.name(), annotationValue != null ? annotationValue : getterName(getterMethod), + getterMethod.hasDeclaredAnnotation(ENCODED), new GetterExtractor(getterMethod), getterMethod.returnType()))); @@ -139,32 +144,33 @@ private static List parseInternal(ClassInfo beanParamClass, IndexView inde resultList.addAll(paramItemsForFieldsAndMethods(beanParamClass, PATH_PARAM, (annotationValue, fieldInfo) -> new PathParamItem(fieldInfo.name(), annotationValue, - fieldInfo.type().name().toString(), + fieldInfo.type().name().toString(), fieldInfo.hasDeclaredAnnotation(ENCODED), new FieldExtractor(null, fieldInfo.name(), fieldInfo.declaringClass().name().toString())), (annotationValue, getterMethod) -> new PathParamItem(getterMethod.name(), annotationValue, - getterMethod.returnType().name().toString(), + getterMethod.returnType().name().toString(), getterMethod.hasDeclaredAnnotation(ENCODED), new GetterExtractor(getterMethod)))); resultList.addAll(paramItemsForFieldsAndMethods(beanParamClass, REST_PATH_PARAM, (annotationValue, fieldInfo) -> new PathParamItem(fieldInfo.name(), annotationValue != null ? annotationValue : fieldInfo.name(), fieldInfo.type().name().toString(), + fieldInfo.hasDeclaredAnnotation(ENCODED), new FieldExtractor(null, fieldInfo.name(), fieldInfo.declaringClass().name().toString())), (annotationValue, getterMethod) -> new PathParamItem(getterMethod.name(), annotationValue != null ? annotationValue : getterName(getterMethod), - getterMethod.returnType().name().toString(), + getterMethod.returnType().name().toString(), getterMethod.hasDeclaredAnnotation(ENCODED), new GetterExtractor(getterMethod)))); resultList.addAll(paramItemsForFieldsAndMethods(beanParamClass, FORM_PARAM, (annotationValue, fieldInfo) -> new FormParamItem(fieldInfo.name(), annotationValue, fieldInfo.type().name().toString(), AsmUtil.getSignature(fieldInfo.type()), fieldInfo.name(), - partType(fieldInfo), fileName(fieldInfo), + partType(fieldInfo), fileName(fieldInfo), fieldInfo.hasDeclaredAnnotation(ENCODED), new FieldExtractor(null, fieldInfo.name(), fieldInfo.declaringClass().name().toString())), (annotationValue, getterMethod) -> new FormParamItem(getterMethod.name(), annotationValue, getterMethod.returnType().name().toString(), AsmUtil.getSignature(getterMethod.returnType()), getterMethod.name(), - partType(getterMethod), fileName(getterMethod), + partType(getterMethod), fileName(getterMethod), getterMethod.hasDeclaredAnnotation(ENCODED), new GetterExtractor(getterMethod)))); resultList.addAll(paramItemsForFieldsAndMethods(beanParamClass, REST_FORM_PARAM, @@ -172,14 +178,14 @@ private static List parseInternal(ClassInfo beanParamClass, IndexView inde annotationValue != null ? annotationValue : fieldInfo.name(), fieldInfo.type().name().toString(), AsmUtil.getSignature(fieldInfo.type()), fieldInfo.name(), - partType(fieldInfo), fileName(fieldInfo), + partType(fieldInfo), fileName(fieldInfo), fieldInfo.hasDeclaredAnnotation(ENCODED), new FieldExtractor(null, fieldInfo.name(), fieldInfo.declaringClass().name().toString())), (annotationValue, getterMethod) -> new FormParamItem(getterMethod.name(), annotationValue != null ? annotationValue : getterName(getterMethod), getterMethod.returnType().name().toString(), AsmUtil.getSignature(getterMethod.returnType()), getterMethod.name(), - partType(getterMethod), fileName(getterMethod), + partType(getterMethod), fileName(getterMethod), getterMethod.hasDeclaredAnnotation(ENCODED), new GetterExtractor(getterMethod)))); return resultList; diff --git a/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/beanparam/CookieParamItem.java b/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/beanparam/CookieParamItem.java index ba068e0ad463f..10768d8376158 100644 --- a/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/beanparam/CookieParamItem.java +++ b/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/beanparam/CookieParamItem.java @@ -5,7 +5,7 @@ public class CookieParamItem extends Item { private final String paramType; public CookieParamItem(String fieldName, String cookieName, ValueExtractor extractor, String paramType) { - super(fieldName, ItemType.COOKIE, extractor); + super(fieldName, ItemType.COOKIE, false, extractor); this.cookieName = cookieName; this.paramType = paramType; } diff --git a/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/beanparam/FormParamItem.java b/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/beanparam/FormParamItem.java index 60c2fe9d3ccb0..2fada96647f7c 100644 --- a/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/beanparam/FormParamItem.java +++ b/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/beanparam/FormParamItem.java @@ -12,8 +12,9 @@ public class FormParamItem extends Item { public FormParamItem(String fieldName, String formParamName, String paramType, String paramSignature, String sourceName, String mimeType, String fileName, + boolean encoded, ValueExtractor valueExtractor) { - super(fieldName, ItemType.FORM_PARAM, valueExtractor); + super(fieldName, ItemType.FORM_PARAM, encoded, valueExtractor); this.formParamName = formParamName; this.paramType = paramType; this.paramSignature = paramSignature; diff --git a/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/beanparam/HeaderParamItem.java b/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/beanparam/HeaderParamItem.java index 61b417b3865ff..79c6adaf83c18 100644 --- a/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/beanparam/HeaderParamItem.java +++ b/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/beanparam/HeaderParamItem.java @@ -5,7 +5,7 @@ public class HeaderParamItem extends Item { private final String paramType; public HeaderParamItem(String fieldName, String headerName, ValueExtractor extractor, String paramType) { - super(fieldName, ItemType.HEADER_PARAM, extractor); + super(fieldName, ItemType.HEADER_PARAM, false, extractor); this.headerName = headerName; this.paramType = paramType; } diff --git a/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/beanparam/Item.java b/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/beanparam/Item.java index 1ef10511912ad..6cef2386dad8c 100644 --- a/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/beanparam/Item.java +++ b/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/beanparam/Item.java @@ -7,11 +7,13 @@ public abstract class Item { private final String fieldName; private final ItemType type; + private final boolean encoded; private final ValueExtractor valueExtractor; - public Item(String fieldName, ItemType type, ValueExtractor valueExtractor) { + public Item(String fieldName, ItemType type, boolean encoded, ValueExtractor valueExtractor) { this.fieldName = fieldName; this.type = type; + this.encoded = encoded; this.valueExtractor = valueExtractor; } @@ -23,6 +25,10 @@ public ItemType type() { return type; } + public boolean isEncoded() { + return encoded; + } + public ResultHandle extract(BytecodeCreator methodCreator, ResultHandle param) { return valueExtractor.extract(methodCreator, param); } diff --git a/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/beanparam/PathParamItem.java b/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/beanparam/PathParamItem.java index 474052a4f0a39..6ca98452dfc92 100644 --- a/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/beanparam/PathParamItem.java +++ b/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/beanparam/PathParamItem.java @@ -5,8 +5,9 @@ public class PathParamItem extends Item { private final String pathParamName; private final String paramType; - public PathParamItem(String fieldName, String pathParamName, String paramType, ValueExtractor valueExtractor) { - super(fieldName, ItemType.PATH_PARAM, valueExtractor); + public PathParamItem(String fieldName, String pathParamName, String paramType, boolean encoded, + ValueExtractor valueExtractor) { + super(fieldName, ItemType.PATH_PARAM, encoded, valueExtractor); this.pathParamName = pathParamName; this.paramType = paramType; } diff --git a/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/beanparam/QueryParamItem.java b/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/beanparam/QueryParamItem.java index a3b83a979d817..56641b51c69f7 100644 --- a/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/beanparam/QueryParamItem.java +++ b/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/beanparam/QueryParamItem.java @@ -7,8 +7,8 @@ public class QueryParamItem extends Item { private final String name; private final Type valueType; - public QueryParamItem(String fieldName, String name, ValueExtractor extractor, Type valueType) { - super(fieldName, ItemType.QUERY_PARAM, extractor); + public QueryParamItem(String fieldName, String name, boolean encoded, ValueExtractor extractor, Type valueType) { + super(fieldName, ItemType.QUERY_PARAM, encoded, extractor); this.name = name; this.valueType = valueType; } diff --git a/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/scanning/ClientEndpointIndexer.java b/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/scanning/ClientEndpointIndexer.java index eaba90c22749c..550902548acae 100644 --- a/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/scanning/ClientEndpointIndexer.java +++ b/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/scanning/ClientEndpointIndexer.java @@ -1,6 +1,7 @@ package org.jboss.resteasy.reactive.client.processor.scanning; import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON; +import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.ENCODED; import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.JSONP_JSON_ARRAY; import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.JSONP_JSON_NUMBER; import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.JSONP_JSON_OBJECT; @@ -64,6 +65,7 @@ public MaybeRestClientInterface createClientProxy(ClassInfo classInfo, try { RestClientInterface clazz = new RestClientInterface(); clazz.setClassName(classInfo.name().toString()); + clazz.setEncoded(classInfo.hasDeclaredAnnotation(ENCODED)); if (path != null) { if (!path.startsWith("/")) { path = "/" + path; diff --git a/independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/EndpointIndexer.java b/independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/EndpointIndexer.java index e52a18d68850a..1ecf00262239b 100644 --- a/independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/EndpointIndexer.java +++ b/independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/EndpointIndexer.java @@ -756,6 +756,7 @@ private ResourceMethod createResourceMethod(ClassInfo currentClassInfo, ClassInf .setRunOnVirtualThread(runOnVirtualThread) .setSuspended(suspended) .setSse(sse) + .setEncoded(currentMethodInfo.hasDeclaredAnnotation(ENCODED)) .setStreamElementType(streamElementType) .setFormParamRequired(formParamRequired) .setFileFormNames(fileFormNames) diff --git a/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/jaxrs/UriBuilderImpl.java b/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/jaxrs/UriBuilderImpl.java index 710bff12906e2..94a860b34fd34 100644 --- a/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/jaxrs/UriBuilderImpl.java +++ b/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/jaxrs/UriBuilderImpl.java @@ -66,6 +66,7 @@ public boolean containsKey(Object key) { private String fragment; private String ssp; private String authority; + private boolean encode = true; private MultiQueryParamMode queryParamMode = MultiQueryParamMode.MULTI_PAIRS; @@ -81,6 +82,7 @@ public UriBuilder clone() { impl.ssp = ssp; impl.authority = authority; impl.queryParamMode = queryParamMode; + impl.encode = encode; return impl; } @@ -350,6 +352,11 @@ public UriBuilder port(int port) throws IllegalArgumentException { return this; } + public UriBuilder encode(boolean encode) { + this.encode = encode; + return this; + } + protected static String paths(boolean encode, String basePath, String... segments) { String path = basePath; if (path == null) @@ -385,7 +392,7 @@ protected static String paths(boolean encode, String basePath, String... segment public UriBuilder path(String segment) throws IllegalArgumentException { if (segment == null) throw new IllegalArgumentException("path is null"); - path = paths(true, path, segment); + path = paths(encode, path, segment); return this; } @@ -429,7 +436,7 @@ public UriBuilder path(Method method) throws IllegalArgumentException { } Path ann = method.getAnnotation(Path.class); if (ann != null) { - path = paths(true, path, ann.value()); + path = paths(encode, path, ann.value()); } else { throw new IllegalArgumentException("Method not annotated with @Path"); } @@ -552,7 +559,7 @@ private CharSequence buildCharSequence(Map paramMap, b } if (path != null) { StringBuilder tmp = new StringBuilder(); - replaceParameter(paramMap, fromEncodedMap, isTemplate, path, tmp, encodeSlash); + replaceParameter(paramMap, fromEncodedMap, isTemplate, path, tmp, encode, encodeSlash); if (userInfo != null || host != null) { if (tmp.length() > 0 && tmp.charAt(0) != '/') builder.append("/"); @@ -605,6 +612,11 @@ public static Matcher createUriParamMatcher(String string) { protected StringBuilder replaceParameter(Map paramMap, boolean fromEncodedMap, boolean isTemplate, String string, StringBuilder builder, boolean encodeSlash) { + return replaceParameter(paramMap, fromEncodedMap, isTemplate, string, builder, true, encodeSlash); + } + + protected StringBuilder replaceParameter(Map paramMap, boolean fromEncodedMap, boolean isTemplate, + String string, StringBuilder builder, boolean encode, boolean encodeSlash) { if (string.indexOf('{') == -1) { return builder.append(string); } @@ -624,7 +636,11 @@ protected StringBuilder replaceParameter(Map paramMap, } Object value = paramMap.get(param); String stringValue = value != null ? value.toString() : null; - if (stringValue != null) { + if (stringValue == null) { + throw new IllegalArgumentException("Template parameter null: " + param); + } + + if (encode) { if (!fromEncodedMap) { if (encodeSlash) stringValue = Encode.encodePathSegmentAsIs(stringValue); @@ -636,11 +652,10 @@ protected StringBuilder replaceParameter(Map paramMap, else stringValue = Encode.encodePathSaveEncodings(stringValue); } - builder.append(stringValue); - start = matcher.end(); - } else { - throw new IllegalArgumentException("Template parameter null: " + param); } + + builder.append(stringValue); + start = matcher.end(); } builder.append(string, start, string.length()); return builder; @@ -882,29 +897,29 @@ public UriBuilder clientQueryParam(String name, Object... values) throws Illegal if (values == null) throw new IllegalArgumentException("Values parameter is null"); + String queryParamName = encode ? Encode.encodeQueryParamAsIs(name) : name; if (queryParamMode == MultiQueryParamMode.COMMA_SEPARATED) { - sb.append(Encode.encodeQueryParamAsIs(name)).append("="); + sb.append(queryParamName).append("="); } for (Object value : values) { if (value == null) throw new IllegalArgumentException("Value is null"); sb.append(prefix); + String queryParamValue = encode ? Encode.encodeQueryParamAsIs(value.toString()) : value.toString(); switch (queryParamMode) { case MULTI_PAIRS: prefix = "&"; - sb.append(Encode.encodeQueryParamAsIs(name)).append("=") - .append(Encode.encodeQueryParamAsIs(value.toString())); + sb.append(queryParamName).append("=").append(queryParamValue); break; case COMMA_SEPARATED: prefix = ","; - sb.append(Encode.encodeQueryParamAsIs(value.toString())); + sb.append(queryParamValue); break; case ARRAY_PAIRS: prefix = "&"; String queryParamConnector = arrayPairsConnector(values); - sb.append(Encode.encodeQueryParamAsIs(name)).append(queryParamConnector) - .append(Encode.encodeQueryParamAsIs(value.toString())); + sb.append(queryParamName).append(queryParamConnector).append(queryParamValue); break; } } @@ -927,28 +942,29 @@ public UriBuilder queryParam(String name, Object... values) throws IllegalArgume if (values == null) throw new IllegalArgumentException("Values parameter is null"); + String queryParamName = encode ? Encode.encodeQueryParam(name) : name; if (queryParamMode == MultiQueryParamMode.COMMA_SEPARATED) { - sb.append(Encode.encodeQueryParam(name)).append("="); + sb.append(queryParamName).append("="); } for (Object value : values) { if (value == null) throw new IllegalArgumentException("Value is null"); sb.append(prefix); + String queryParamValue = encode ? Encode.encodeQueryParam(value.toString()) : value.toString(); switch (queryParamMode) { case MULTI_PAIRS: prefix = "&"; - sb.append(Encode.encodeQueryParam(name)).append("=").append(Encode.encodeQueryParam(value.toString())); + sb.append(queryParamName).append("=").append(queryParamValue); break; case COMMA_SEPARATED: prefix = ","; - sb.append(Encode.encodeQueryParam(value.toString())); + sb.append(queryParamValue); break; case ARRAY_PAIRS: prefix = "&"; String queryParamConnector = arrayPairsConnector(values); - sb.append(Encode.encodeQueryParam(name)).append(queryParamConnector) - .append(Encode.encodeQueryParam(value.toString())); + sb.append(queryParamName).append(queryParamConnector).append(queryParamValue); break; } } diff --git a/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/model/ResourceMethod.java b/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/model/ResourceMethod.java index 37baf4b5c0d4f..90d07e3d351d4 100644 --- a/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/model/ResourceMethod.java +++ b/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/model/ResourceMethod.java @@ -72,13 +72,15 @@ public class ResourceMethod { private List subResourceMethods; + private boolean encoded; + public ResourceMethod() { } public ResourceMethod(String httpMethod, String path, String[] produces, String streamElementType, String[] consumes, Set nameBindingNames, String name, String returnType, String simpleReturnType, MethodParameter[] parameters, boolean blocking, boolean suspended, boolean isSse, boolean isFormParamRequired, - List subResourceMethods) { + List subResourceMethods, boolean encoded) { this.httpMethod = httpMethod; this.path = path; this.produces = produces; @@ -94,6 +96,7 @@ public ResourceMethod(String httpMethod, String path, String[] produces, String this.isSse = isSse; this.isFormParamRequired = isFormParamRequired; this.subResourceMethods = subResourceMethods; + this.encoded = encoded; } public boolean isResourceLocator() { @@ -244,6 +247,15 @@ public String getStreamElementType() { return streamElementType; } + public boolean isEncoded() { + return encoded; + } + + public ResourceMethod setEncoded(boolean encoded) { + this.encoded = encoded; + return this; + } + @Override public String toString() { if (httpMethod != null) diff --git a/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/model/RestClientInterface.java b/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/model/RestClientInterface.java index cdbcb3e63c7c8..63e16560010db 100644 --- a/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/model/RestClientInterface.java +++ b/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/model/RestClientInterface.java @@ -26,6 +26,8 @@ public class RestClientInterface { private Set pathParameters = new HashSet<>(); + private boolean encoded = false; + public String getClassName() { return className; } @@ -60,4 +62,13 @@ public RestClientInterface setPathParameters(Set pathParameters) { this.pathParameters = pathParameters; return this; } + + public boolean isEncoded() { + return encoded; + } + + public RestClientInterface setEncoded(boolean encoded) { + this.encoded = encoded; + return this; + } } diff --git a/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/model/ServerResourceMethod.java b/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/model/ServerResourceMethod.java index 89c406a8837e6..9c8620e9da341 100644 --- a/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/model/ServerResourceMethod.java +++ b/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/model/ServerResourceMethod.java @@ -26,9 +26,10 @@ public ServerResourceMethod(String httpMethod, String path, String[] produces, S Set nameBindingNames, String name, String returnType, String simpleReturnType, MethodParameter[] parameters, boolean blocking, boolean suspended, boolean sse, boolean formParamRequired, List subResourceMethods, Supplier invoker, Set methodAnnotationNames, - List handlerChainCustomizers, ParameterExtractor customerParameterExtractor) { + List handlerChainCustomizers, ParameterExtractor customerParameterExtractor, + boolean encoded) { super(httpMethod, path, produces, streamElementType, consumes, nameBindingNames, name, returnType, simpleReturnType, - parameters, blocking, suspended, sse, formParamRequired, subResourceMethods); + parameters, blocking, suspended, sse, formParamRequired, subResourceMethods, encoded); this.invoker = invoker; this.methodAnnotationNames = methodAnnotationNames; this.handlerChainCustomizers = handlerChainCustomizers;