diff --git a/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/simple/SimpleQuarkusRestTestCase.java b/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/simple/SimpleQuarkusRestTestCase.java index 51ef18e647cc1..9dea4e08961c7 100644 --- a/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/simple/SimpleQuarkusRestTestCase.java +++ b/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/simple/SimpleQuarkusRestTestCase.java @@ -8,6 +8,7 @@ import java.util.function.Supplier; +import org.apache.http.HttpStatus; import org.hamcrest.Matchers; import org.jboss.shrinkwrap.api.ShrinkWrap; import org.jboss.shrinkwrap.api.spec.JavaArchive; @@ -19,6 +20,7 @@ import io.quarkus.test.QuarkusUnitTest; import io.restassured.RestAssured; +import io.restassured.http.ContentType; import io.restassured.http.Headers; public class SimpleQuarkusRestTestCase { @@ -107,6 +109,12 @@ public void testSubResource() { .then().body(Matchers.equalTo("otherSub")); RestAssured.get("/simple/sub") .then().body(Matchers.equalTo("sub")); + + RestAssured.with() + .contentType(ContentType.JSON) + .body("{\"test\": true}") + .patch("/simple/sub/patch/text") + .then().statusCode(HttpStatus.SC_UNSUPPORTED_MEDIA_TYPE); } @Test diff --git a/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/simple/SubResource.java b/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/simple/SubResource.java index 00b37fdf42c6c..e1546a77d6fc8 100644 --- a/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/simple/SubResource.java +++ b/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/simple/SubResource.java @@ -1,7 +1,10 @@ package io.quarkus.resteasy.reactive.server.test.simple; +import javax.ws.rs.Consumes; import javax.ws.rs.GET; +import javax.ws.rs.PATCH; import javax.ws.rs.Path; +import javax.ws.rs.core.MediaType; public class SubResource { @@ -15,4 +18,11 @@ public String sub() { public String otherPath() { return "otherSub"; } + + @Path("patch/text") + @PATCH + @Consumes(MediaType.TEXT_PLAIN) + public String patchWithTextPlain(String patch) { + return "test-value: " + patch; + } } 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 67118258789de..1ca909d8bd1b9 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 @@ -312,8 +312,8 @@ public RuntimeResource buildResourceMethod(ResourceClass clazz, // we only need to parse the signature and create generic type when the declared type differs from the type genericType = TypeSignatureParser.parse(bodyParameter.signature); } - handlers.add(new RequestDeserializeHandler(typeClass, genericType, - consumesMediaTypes.isEmpty() ? null : consumesMediaTypes.get(0), serialisers, bodyParameterIndex)); + handlers.add(new RequestDeserializeHandler(typeClass, genericType, consumesMediaTypes, serialisers, + bodyParameterIndex)); } // given that we may inject form params in the endpoint we need to make sure we read the body before diff --git a/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/handlers/RequestDeserializeHandler.java b/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/handlers/RequestDeserializeHandler.java index 0203a0285b238..701946a95ca5c 100644 --- a/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/handlers/RequestDeserializeHandler.java +++ b/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/handlers/RequestDeserializeHandler.java @@ -3,6 +3,7 @@ import java.io.IOException; import java.lang.annotation.Annotation; import java.lang.reflect.Type; +import java.util.Collections; import java.util.List; import javax.ws.rs.BadRequestException; @@ -17,6 +18,7 @@ import javax.ws.rs.ext.ReaderInterceptor; import org.jboss.logging.Logger; +import org.jboss.resteasy.reactive.common.util.MediaTypeHelper; import org.jboss.resteasy.reactive.server.core.ResteasyReactiveRequestContext; import org.jboss.resteasy.reactive.server.core.ServerSerialisers; import org.jboss.resteasy.reactive.server.jaxrs.ReaderInterceptorContextImpl; @@ -29,30 +31,40 @@ public class RequestDeserializeHandler implements ServerRestHandler { private final Class type; private final Type genericType; - private final MediaType mediaType; + private final List acceptableMediaTypes; private final ServerSerialisers serialisers; private final int parameterIndex; - public RequestDeserializeHandler(Class type, Type genericType, MediaType mediaType, ServerSerialisers serialisers, + public RequestDeserializeHandler(Class type, Type genericType, List acceptableMediaTypes, + ServerSerialisers serialisers, int parameterIndex) { this.type = type; this.genericType = genericType; - this.mediaType = mediaType; + this.acceptableMediaTypes = acceptableMediaTypes; this.serialisers = serialisers; this.parameterIndex = parameterIndex; } @Override public void handle(ResteasyReactiveRequestContext requestContext) throws Exception { - MediaType effectiveRequestType = mediaType; - String requestTypeString = requestContext.serverRequest().getRequestHeader(HttpHeaders.CONTENT_TYPE); - if (requestTypeString != null) { + MediaType effectiveRequestType = null; + Object requestType = requestContext.getHeader(HttpHeaders.CONTENT_TYPE, true); + if (requestType != null) { try { - effectiveRequestType = MediaType.valueOf(requestTypeString); + effectiveRequestType = MediaType.valueOf((String) requestType); } catch (Exception e) { throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST).build()); } - } else if (effectiveRequestType == null) { + + // We need to verify media type for sub-resources, this mimics what is done in {@code ClassRoutingHandler} + if (MediaTypeHelper.getFirstMatch( + acceptableMediaTypes, + Collections.singletonList(effectiveRequestType)) == null) { + throw new NotSupportedException("The content-type header value did not match the value in @Consumes"); + } + } else if (!acceptableMediaTypes.isEmpty()) { + effectiveRequestType = acceptableMediaTypes.get(0); + } else { effectiveRequestType = MediaType.APPLICATION_OCTET_STREAM_TYPE; } List> readers = serialisers.findReaders(null, type, effectiveRequestType, RuntimeType.SERVER);