Skip to content

Commit

Permalink
Merge pull request #28565 from Sgitario/28460
Browse files Browse the repository at this point in the history
Validate media types for sub resources in Resteasy Reactive
  • Loading branch information
gsmet committed Oct 15, 2022
2 parents 6094ed5 + bfbfea6 commit d8f27da
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 10 deletions.
Expand Up @@ -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;
Expand All @@ -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 {
Expand Down Expand Up @@ -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
Expand Down
@@ -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 {

Expand All @@ -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;
}
}
Expand Up @@ -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
Expand Down
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -29,30 +31,40 @@ public class RequestDeserializeHandler implements ServerRestHandler {

private final Class<?> type;
private final Type genericType;
private final MediaType mediaType;
private final List<MediaType> 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<MediaType> 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<MessageBodyReader<?>> readers = serialisers.findReaders(null, type, effectiveRequestType, RuntimeType.SERVER);
Expand Down

0 comments on commit d8f27da

Please sign in to comment.