diff --git a/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/providers/serialisers/InputStreamMessageBodyHandler.java b/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/providers/serialisers/InputStreamMessageBodyHandler.java index aba7b355d230af..2c5aff1a0f6b52 100644 --- a/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/providers/serialisers/InputStreamMessageBodyHandler.java +++ b/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/providers/serialisers/InputStreamMessageBodyHandler.java @@ -23,12 +23,20 @@ public InputStream readFrom(Class<InputStream> type, Type genericType, Annotatio @Override public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { + return doWriteTo(type); + } + + protected boolean doWriteTo(Class<?> type) { return InputStream.class.isAssignableFrom(type); } @Override public void writeTo(InputStream inputStream, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException { + doWriteTo(inputStream, entityStream); + } + + protected void doWriteTo(InputStream inputStream, OutputStream entityStream) throws IOException { try { byte[] buffer = new byte[8192]; int c; diff --git a/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/providers/serialisers/ServerInputStreamMessageBodyHandler.java b/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/providers/serialisers/ServerInputStreamMessageBodyHandler.java index c643e6d16f675a..2eeec6eeb2d93f 100644 --- a/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/providers/serialisers/ServerInputStreamMessageBodyHandler.java +++ b/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/providers/serialisers/ServerInputStreamMessageBodyHandler.java @@ -10,11 +10,12 @@ import org.jboss.resteasy.reactive.common.providers.serialisers.InputStreamMessageBodyHandler; 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; @Provider public class ServerInputStreamMessageBodyHandler extends InputStreamMessageBodyHandler - implements ServerMessageBodyReader<InputStream> { + implements ServerMessageBodyReader<InputStream>, ServerMessageBodyWriter<InputStream> { @Override public boolean isReadable(Class<?> type, Type genericType, ResteasyReactiveResourceInfo lazyMethod, MediaType mediaType) { @@ -33,4 +34,15 @@ public long getSize(InputStream inputStream, Class<?> type, Type genericType, An return -1; } + @Override + public boolean isWriteable(Class<?> type, Type genericType, ResteasyReactiveResourceInfo target, + MediaType mediaType) { + return doWriteTo(type); + } + + @Override + public void writeResponse(InputStream is, Type genericType, ServerRequestContext context) + throws WebApplicationException, IOException { + doWriteTo(is, context.getOrCreateOutputStream()); + } } diff --git a/integration-tests/rest-client-reactive-multipart/src/main/java/io/quarkus/it/rest/client/multipart/MultipartResource.java b/integration-tests/rest-client-reactive-multipart/src/main/java/io/quarkus/it/rest/client/multipart/MultipartResource.java index a24fb95c3cc986..5006915153eaeb 100644 --- a/integration-tests/rest-client-reactive-multipart/src/main/java/io/quarkus/it/rest/client/multipart/MultipartResource.java +++ b/integration-tests/rest-client-reactive-multipart/src/main/java/io/quarkus/it/rest/client/multipart/MultipartResource.java @@ -3,8 +3,10 @@ import static java.nio.charset.StandardCharsets.UTF_8; import java.io.File; +import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; import java.nio.file.Files; import java.util.ArrayList; import java.util.List; @@ -25,6 +27,7 @@ import org.jboss.resteasy.reactive.MultipartForm; import org.jboss.resteasy.reactive.PartType; import org.jboss.resteasy.reactive.RestQuery; +import org.jboss.resteasy.reactive.RestResponse; import io.quarkus.it.rest.client.multipart.MultipartClient.FileWithPojo; import io.quarkus.it.rest.client.multipart.MultipartClient.Pojo; @@ -141,12 +144,7 @@ public String sendFileAsBinary(@QueryParam("nullFile") @DefaultValue("false") bo WithFileAsBinaryFile data = new WithFileAsBinaryFile(); if (!nullFile) { - File tempFile = File.createTempFile("quarkus-test", ".bin"); - tempFile.deleteOnExit(); - - try (FileOutputStream fileOutputStream = new FileOutputStream(tempFile)) { - fileOutputStream.write(HELLO_WORLD.getBytes()); - } + File tempFile = createTempHelloWorldFile(); data.file = tempFile; } @@ -163,12 +161,7 @@ public String sendPathAsBinary(@QueryParam("nullFile") @DefaultValue("false") bo WithPathAsBinaryFile data = new WithPathAsBinaryFile(); if (!nullFile) { - File tempFile = File.createTempFile("quarkus-test", ".bin"); - tempFile.deleteOnExit(); - - try (FileOutputStream fileOutputStream = new FileOutputStream(tempFile)) { - fileOutputStream.write(HELLO_WORLD.getBytes()); - } + File tempFile = createTempHelloWorldFile(); data.file = tempFile.toPath(); } @@ -206,12 +199,7 @@ public String sendBufferAsTextFile() { @Produces(MediaType.TEXT_PLAIN) @Blocking public String sendFileAsText() throws IOException { - File tempFile = File.createTempFile("quarkus-test", ".bin"); - tempFile.deleteOnExit(); - - try (FileOutputStream fileOutputStream = new FileOutputStream(tempFile)) { - fileOutputStream.write(HELLO_WORLD.getBytes()); - } + File tempFile = createTempHelloWorldFile(); WithFileAsTextFile data = new WithFileAsTextFile(); data.file = tempFile; @@ -225,12 +213,7 @@ public String sendFileAsText() throws IOException { @Produces(MediaType.TEXT_PLAIN) @Blocking public String sendPathAsText() throws IOException { - File tempFile = File.createTempFile("quarkus-test", ".bin"); - tempFile.deleteOnExit(); - - try (FileOutputStream fileOutputStream = new FileOutputStream(tempFile)) { - fileOutputStream.write(HELLO_WORLD.getBytes()); - } + File tempFile = createTempHelloWorldFile(); WithPathAsTextFile data = new WithPathAsTextFile(); data.file = tempFile.toPath(); @@ -276,17 +259,33 @@ public String consumeBinaryWithPojo(@MultipartForm MultipartBodyWithBinaryFileAn @Path("/produces/multipart") @Produces(MediaType.MULTIPART_FORM_DATA) public MultipartBodyWithTextFile produceMultipart() throws IOException { + File tempFile = createTempHelloWorldFile(); + + MultipartBodyWithTextFile data = new MultipartBodyWithTextFile(); + data.file = tempFile; + data.number = String.valueOf(NUMBER); + return data; + } + + @GET + @Path("/produces/input-stream-rest-response") + public RestResponse<? extends InputStream> produceInputStreamRestResponse() throws IOException { + File tempFile = createTempHelloWorldFile(); + FileInputStream is = new FileInputStream(tempFile); + return RestResponse.ResponseBuilder + .ok(is) + .type(MediaType.TEXT_PLAIN_TYPE) + .build(); + } + + private File createTempHelloWorldFile() throws IOException { File tempFile = File.createTempFile("quarkus-test", ".bin"); tempFile.deleteOnExit(); try (FileOutputStream fileOutputStream = new FileOutputStream(tempFile)) { fileOutputStream.write(HELLO_WORLD.getBytes()); } - - MultipartBodyWithTextFile data = new MultipartBodyWithTextFile(); - data.file = tempFile; - data.number = String.valueOf(NUMBER); - return data; + return tempFile; } private boolean containsHelloWorld(File file) { diff --git a/integration-tests/rest-client-reactive-multipart/src/test/java/io/quarkus/it/rest/client/multipart/MultipartResourceTest.java b/integration-tests/rest-client-reactive-multipart/src/test/java/io/quarkus/it/rest/client/multipart/MultipartResourceTest.java index 8c8d995b56b08b..da4fcb1882f548 100644 --- a/integration-tests/rest-client-reactive-multipart/src/test/java/io/quarkus/it/rest/client/multipart/MultipartResourceTest.java +++ b/integration-tests/rest-client-reactive-multipart/src/test/java/io/quarkus/it/rest/client/multipart/MultipartResourceTest.java @@ -229,6 +229,15 @@ public void shouldProperlyHandleOctetStreamFile() { // @formatter:on } + @Test + public void shouldProducesInputStreamRestResponse() { + RestAssured.get("/produces/input-stream-rest-response") + .then() + .contentType(ContentType.TEXT) + .statusCode(200) + .body(equalTo("HELLO WORLD")); + } + private void assertMultipartResponseContains(String response, String name, String contentType, Object value) { String[] lines = response.split("--"); assertThat(lines).anyMatch(line -> line.contains(String.format(EXPECTED_CONTENT_DISPOSITION_PART, name))