Skip to content

Commit

Permalink
Merge pull request #40022 from geoand/#40019
Browse files Browse the repository at this point in the history
Take MediaType set in pre-match filter into account during serialization
  • Loading branch information
gastaldi authored Apr 11, 2024
2 parents 6b171d0 + 4f86368 commit bb6da8e
Show file tree
Hide file tree
Showing 3 changed files with 242 additions and 126 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,18 @@ public void handle(ResteasyReactiveRequestContext requestContext) throws Excepti
//TODO?
return;
}
MediaType res = mediaTypeList.negotiateProduces(requestContext.serverRequest().getRequestHeader(HttpHeaders.ACCEPT))
.getKey();
MediaType res = null;
List<String> accepts = requestContext.getHttpHeaders().getRequestHeader(HttpHeaders.ACCEPT);
for (String accept : accepts) {
res = mediaTypeList.negotiateProduces(accept).getKey();
if (res != null) {
break;
}
}
if (res == null) { // fallback for some tests
res = mediaTypeList.negotiateProduces(requestContext.serverRequest().getRequestHeader(HttpHeaders.ACCEPT))
.getKey();
}
if (res == null) {
throw new WebApplicationException(Response
.notAcceptable(Variant.mediaTypes(mediaTypeList.getSortedMediaTypes()).build())
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
package org.jboss.resteasy.reactive.server.vertx.test.matching;

import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;

import java.io.IOException;
import java.io.OutputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.function.Supplier;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.WebApplicationException;
import jakarta.ws.rs.container.ContainerRequestContext;
import jakarta.ws.rs.container.ContainerRequestFilter;
import jakarta.ws.rs.container.PreMatching;
import jakarta.ws.rs.core.HttpHeaders;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.ext.Provider;

import org.jboss.resteasy.reactive.server.spi.ResteasyReactiveResourceInfo;
import org.jboss.resteasy.reactive.server.spi.ServerMessageBodyWriter;
import org.jboss.resteasy.reactive.server.spi.ServerRequestContext;
import org.jboss.resteasy.reactive.server.vertx.test.framework.ResteasyReactiveUnitTest;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

public class PreMatchAcceptInHeaderTest {

@RegisterExtension
static ResteasyReactiveUnitTest test = new ResteasyReactiveUnitTest()
.setArchiveProducer(new Supplier<>() {
@Override
public JavaArchive get() {
return ShrinkWrap.create(JavaArchive.class);
}
});

@Test
void browserDefault() {
given().accept("text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8")
.when()
.get("test")
.then()
.statusCode(200)
.body(containsString("<html>"));
}

@Test
void text() {
given().accept("text/plain")
.when()
.get("test")
.then()
.statusCode(200)
.body(equalTo("text"));
}

@Test
void html() {
given().accept("text/html")
.when()
.get("test")
.then()
.statusCode(200)
.body(containsString("<html>"));
}

@Test
void json() {
given().accept("application/json")
.when()
.get("test")
.then()
.statusCode(406);
}

@Test
void setAcceptToTextInFilter() {
given().accept("application/json")
.header("x-set-accept-to-text", "true")
.when()
.get("test")
.then()
.statusCode(200)
.body(equalTo("text"));
}

@Test
void entityJsonWithoutAcceptToTextInFilter() {
given().accept("application/json")
.when()
.get("test/entity")
.then()
.statusCode(200)
.body(containsString("\"text\""));
}

@Test
void entityTextWithoutAcceptToTextInFilter() {
given().accept("text/plain")
.when()
.get("test/entity")
.then()
.statusCode(200)
.body(equalTo("text"));
}

@Test
void entityTextWithAcceptToTextInFilter() {
given().accept("application/json")
.header("x-set-accept-to-text", "true")
.when()
.get("test/entity")
.then()
.statusCode(200)
.body(equalTo("text"));
}

@Path("/test")
public static class Resource {

@GET
@Produces(MediaType.TEXT_PLAIN)
public String text() {
return "text";
}

@GET
@Produces(MediaType.TEXT_HTML)
public String html() {
return """
<html>
<head>
</head>
<body>
Hello World
</body>
</html>
""";
}

@GET
@Path("entity")
@Produces({ MediaType.TEXT_PLAIN, MediaType.APPLICATION_JSON })
public Entity entity() {
return new Entity("text");
}
}

public record Entity(String value) {
}

@PreMatching
@Provider
public static class SetAcceptHeaderFilter implements ContainerRequestFilter {

@Override
public void filter(ContainerRequestContext requestContext) {
MultivaluedMap<String, String> headers = requestContext.getHeaders();
if ("true".equals(headers.getFirst("x-set-accept-to-text"))) {
headers.putSingle(HttpHeaders.ACCEPT, MediaType.TEXT_PLAIN);
}
}
}

@Provider
@Produces(MediaType.TEXT_PLAIN)
public static class DummyTextMessageBodyWriter implements ServerMessageBodyWriter<Object> {

@Override
public boolean isWriteable(Class<?> type, Type genericType, ResteasyReactiveResourceInfo target,
MediaType mediaType) {
return Entity.class.equals(type);
}

@Override
public void writeResponse(Object o, Type genericType, ServerRequestContext context)
throws WebApplicationException, IOException {
context.serverResponse().end(((Entity) o).value());
}

@Override
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
return Entity.class.equals(type);
}

@Override
public void writeTo(Object o, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
throws IOException, WebApplicationException {
throw new IllegalStateException("should not be called");
}
}

@Provider
@Produces(MediaType.APPLICATION_JSON)
public static class DummyJsonMessageBodyWriter implements ServerMessageBodyWriter<Object> {

@Override
public boolean isWriteable(Class<?> type, Type genericType, ResteasyReactiveResourceInfo target,
MediaType mediaType) {
return Entity.class.equals(type);
}

@Override
public void writeResponse(Object o, Type genericType, ServerRequestContext context)
throws WebApplicationException, IOException {
context.serverResponse().end("{\"value\":\"" + ((Entity) o).value() + "\"}");
}

@Override
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
return Entity.class.equals(type);
}

@Override
public void writeTo(Object o, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
throws IOException, WebApplicationException {
throw new IllegalStateException("should not be called");
}
}
}

0 comments on commit bb6da8e

Please sign in to comment.