Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validate media types for sub resources in Resteasy Reactive #28565

Merged
merged 1 commit into from
Oct 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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