-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Resteasy Reactive: Fix support media types with suffixes
Given a media type with suffix, for example: "application/test+json". Before these changes, Resteasy Reactive was trying to find the writer/reader using only the suffix. For example, with a media type "application/test+json", it would only use "json" to locate the right writer/reader. Spite of this has been working well so far, if users provide a custom writer/reader for a concrete media type with suffix: ```java @Provider @produces("text/test+suffix") public static class SuffixMessageBodyWriter implements ServerMessageBodyWriter<Object> { @OverRide public boolean isWriteable(Class<?> type, Type genericType, ResteasyReactiveResourceInfo target, MediaType mediaType) { // ... } @OverRide public void writeResponse(Object o, Type genericType, ServerRequestContext context) { // ... } // ... } ``` The above writer will never be used. After these changes, we will use the media type with suffix, plus the split parts of the suffix. For example, if the media type with suffix is: "application/test+json", it will try to find the best writer/reader for "application/test+json", "application/test" and then "application/json" (In this order). Fix #15982 (cherry picked from commit d6a5178)
- Loading branch information
Showing
11 changed files
with
363 additions
and
55 deletions.
There are no files selected for viewing
216 changes: 216 additions & 0 deletions
216
...uarkus/resteasy/reactive/server/test/resource/basic/MediaTypesWithSuffixHandlingTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,216 @@ | ||
package io.quarkus.resteasy.reactive.server.test.resource.basic; | ||
|
||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.io.OutputStream; | ||
import java.lang.annotation.Annotation; | ||
import java.lang.reflect.Type; | ||
import java.nio.charset.StandardCharsets; | ||
|
||
import javax.ws.rs.Consumes; | ||
import javax.ws.rs.GET; | ||
import javax.ws.rs.Path; | ||
import javax.ws.rs.Produces; | ||
import javax.ws.rs.WebApplicationException; | ||
import javax.ws.rs.core.MediaType; | ||
import javax.ws.rs.core.MultivaluedMap; | ||
import javax.ws.rs.ext.Provider; | ||
|
||
import org.hamcrest.Matchers; | ||
import org.jboss.resteasy.reactive.server.spi.ResteasyReactiveResourceInfo; | ||
import org.jboss.resteasy.reactive.server.spi.ServerMessageBodyReader; | ||
import org.jboss.resteasy.reactive.server.spi.ServerMessageBodyWriter; | ||
import org.jboss.resteasy.reactive.server.spi.ServerRequestContext; | ||
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; | ||
|
||
import io.quarkus.test.QuarkusUnitTest; | ||
import io.restassured.RestAssured; | ||
|
||
public class MediaTypesWithSuffixHandlingTest { | ||
|
||
@RegisterExtension | ||
static QuarkusUnitTest testExtension = new QuarkusUnitTest() | ||
.setArchiveProducer(() -> { | ||
JavaArchive archive = ShrinkWrap.create(JavaArchive.class); | ||
archive.addClasses(TestResource.class, NoSuffixMessageBodyWriter.class, SuffixMessageBodyWriter.class); | ||
return archive; | ||
}); | ||
|
||
@Test | ||
public void testWriterWithoutSuffix() { | ||
RestAssured.get("/test/writer/with-no-suffix") | ||
.then() | ||
.statusCode(200) | ||
.body(Matchers.equalTo("result - no suffix writer")); | ||
} | ||
|
||
@Test | ||
public void testReaderWithoutSuffix() { | ||
RestAssured.get("/test/reader/with-no-suffix") | ||
.then() | ||
.statusCode(200) | ||
.body(Matchers.equalTo("from reader - result")); | ||
} | ||
|
||
@Test | ||
public void testWriterWithSuffix() { | ||
RestAssured.get("/test/writer/with-suffix") | ||
.then() | ||
.statusCode(200) | ||
.body(Matchers.equalTo("result - suffix writer")); | ||
} | ||
|
||
@Test | ||
public void testReaderWithSuffix() { | ||
RestAssured.get("/test/reader/with-suffix") | ||
.then() | ||
.statusCode(200) | ||
.body(Matchers.equalTo("from reader suffix - result")); | ||
} | ||
|
||
@Path("/test") | ||
public static class TestResource { | ||
|
||
@GET | ||
@Path("/writer/with-no-suffix") | ||
@Produces("text/test") | ||
public String writerSimple() { | ||
return "result"; | ||
} | ||
|
||
@GET | ||
@Path("/writer/with-suffix") | ||
@Produces("text/test+suffix") | ||
public String writerSuffix() { | ||
return "result"; | ||
} | ||
|
||
@GET | ||
@Path("/reader/with-no-suffix") | ||
@Consumes("text/test") | ||
public String readerSimple(Object fromReader) { | ||
return fromReader + " - result"; | ||
} | ||
|
||
@GET | ||
@Path("/reader/with-suffix") | ||
@Consumes("text/test+suffix") | ||
public String readerSuffix(Object fromReader) { | ||
return fromReader + " - result"; | ||
} | ||
} | ||
|
||
@Provider | ||
@Consumes("text/test") | ||
@Produces("text/test") | ||
public static class NoSuffixMessageBodyWriter implements ServerMessageBodyWriter<Object>, ServerMessageBodyReader<Object> { | ||
|
||
@Override | ||
public boolean isWriteable(Class<?> type, Type genericType, ResteasyReactiveResourceInfo target, MediaType mediaType) { | ||
return true; | ||
} | ||
|
||
@Override | ||
public void writeResponse(Object o, Type genericType, ServerRequestContext context) | ||
throws WebApplicationException, IOException { | ||
String response = (String) o; | ||
response += " - no suffix writer"; | ||
context.getOrCreateOutputStream().write(response.getBytes(StandardCharsets.UTF_8)); | ||
} | ||
|
||
@Override | ||
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { | ||
throw new IllegalStateException("should never have been called"); | ||
} | ||
|
||
@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 never have been called"); | ||
} | ||
|
||
@Override | ||
public boolean isReadable(Class<?> type, Type genericType, ResteasyReactiveResourceInfo lazyMethod, | ||
MediaType mediaType) { | ||
return true; | ||
} | ||
|
||
@Override | ||
public Object readFrom(Class<Object> type, Type genericType, MediaType mediaType, | ||
ServerRequestContext context) throws WebApplicationException { | ||
return "from reader"; | ||
} | ||
|
||
@Override | ||
public boolean isReadable(Class<?> aClass, Type type, Annotation[] annotations, MediaType mediaType) { | ||
throw new IllegalStateException("should never have been called"); | ||
} | ||
|
||
@Override | ||
public Object readFrom(Class<Object> aClass, Type type, Annotation[] annotations, MediaType mediaType, | ||
MultivaluedMap<String, String> multivaluedMap, InputStream inputStream) | ||
throws WebApplicationException { | ||
throw new IllegalStateException("should never have been called"); | ||
} | ||
} | ||
|
||
@Provider | ||
@Consumes("text/test+suffix") | ||
@Produces("text/test+suffix") | ||
public static class SuffixMessageBodyWriter implements ServerMessageBodyWriter<Object>, ServerMessageBodyReader<Object> { | ||
|
||
@Override | ||
public boolean isWriteable(Class<?> type, Type genericType, ResteasyReactiveResourceInfo target, MediaType mediaType) { | ||
return true; | ||
} | ||
|
||
@Override | ||
public void writeResponse(Object o, Type genericType, ServerRequestContext context) | ||
throws WebApplicationException, IOException { | ||
String response = (String) o; | ||
response += " - suffix writer"; | ||
context.getOrCreateOutputStream().write(response.getBytes(StandardCharsets.UTF_8)); | ||
} | ||
|
||
@Override | ||
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { | ||
throw new IllegalStateException("should never have been called"); | ||
} | ||
|
||
@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 never have been called"); | ||
} | ||
|
||
@Override | ||
public boolean isReadable(Class<?> type, Type genericType, ResteasyReactiveResourceInfo lazyMethod, | ||
MediaType mediaType) { | ||
return true; | ||
} | ||
|
||
@Override | ||
public Object readFrom(Class<Object> type, Type genericType, MediaType mediaType, | ||
ServerRequestContext context) throws WebApplicationException { | ||
return "from reader suffix"; | ||
} | ||
|
||
@Override | ||
public boolean isReadable(Class<?> aClass, Type type, Annotation[] annotations, MediaType mediaType) { | ||
throw new IllegalStateException("should never have been called"); | ||
} | ||
|
||
@Override | ||
public Object readFrom(Class<Object> aClass, Type type, Annotation[] annotations, MediaType mediaType, | ||
MultivaluedMap<String, String> multivaluedMap, InputStream inputStream) | ||
throws WebApplicationException { | ||
throw new IllegalStateException("should never have been called"); | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.