From b5a8405d6c5d52c5bcf83b5b7df7e3476cce387a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Szynkiewicz?= Date: Thu, 7 Oct 2021 20:48:44 +0200 Subject: [PATCH] REST Client Reactive: support null file in multipart --- .../JaxrsClientReactiveProcessor.java | 20 ++++--- .../runtime/RestClientCDIDelegateBuilder.java | 1 - .../client/multipart/MultipartResource.java | 54 +++++++++++-------- .../multipart/MultipartResourceTest.java | 52 ++++++++++++++++++ 4 files changed, 97 insertions(+), 30 deletions(-) diff --git a/extensions/resteasy-reactive/jaxrs-client-reactive/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/JaxrsClientReactiveProcessor.java b/extensions/resteasy-reactive/jaxrs-client-reactive/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/JaxrsClientReactiveProcessor.java index ee0b30d5d974b..0e3eb72f9a804 100644 --- a/extensions/resteasy-reactive/jaxrs-client-reactive/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/JaxrsClientReactiveProcessor.java +++ b/extensions/resteasy-reactive/jaxrs-client-reactive/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/JaxrsClientReactiveProcessor.java @@ -1083,9 +1083,10 @@ private ResultHandle createMultipartForm(MethodCreator methodCreator, ResultHand "No @PartType annotation found on multipart form field of type File: " + formClass.name() + "." + field.name()); } - ResultHandle filePath = methodCreator.invokeVirtualMethod( + BytecodeCreator ifFileNotNull = methodCreator.ifNotNull(fieldValue).trueBranch(); + ResultHandle filePath = ifFileNotNull.invokeVirtualMethod( MethodDescriptor.ofMethod(File.class, "toPath", Path.class), fieldValue); - addFile(methodCreator, multipartForm, formParamName, partType, filePath); + addFile(ifFileNotNull, multipartForm, formParamName, partType, filePath); } else if (is(PATH, fieldClass, index)) { // and so is path if (partType == null) { @@ -1093,10 +1094,12 @@ private ResultHandle createMultipartForm(MethodCreator methodCreator, ResultHand "No @PartType annotation found on multipart form field of type Path: " + formClass.name() + "." + field.name()); } - addFile(methodCreator, multipartForm, formParamName, partType, fieldValue); + BytecodeCreator ifPathNotNull = methodCreator.ifNotNull(fieldValue).trueBranch(); + addFile(ifPathNotNull, multipartForm, formParamName, partType, fieldValue); } else if (is(BUFFER, fieldClass, index)) { // and buffer - addBuffer(methodCreator, multipartForm, formParamName, partType, fieldValue, field); + BytecodeCreator ifBufferNotNull = methodCreator.ifNotNull(fieldValue).trueBranch(); + addBuffer(ifBufferNotNull, multipartForm, formParamName, partType, fieldValue, field); } else { // assume POJO: addPojo(methodCreator, multipartForm, formParamName, partType, fieldValue, field); } @@ -1109,10 +1112,11 @@ private ResultHandle createMultipartForm(MethodCreator methodCreator, ResultHand throw new IllegalArgumentException("Array of unsupported type: " + componentType.name() + " on " + formClassType.name() + "." + field.name()); } - ResultHandle buffer = methodCreator.invokeStaticInterfaceMethod( + BytecodeCreator ifArrayNotNull = methodCreator.ifNotNull(fieldValue).trueBranch(); + ResultHandle buffer = ifArrayNotNull.invokeStaticInterfaceMethod( MethodDescriptor.ofMethod(Buffer.class, "buffer", Buffer.class, byte[].class), fieldValue); - addBuffer(methodCreator, multipartForm, formParamName, partType, buffer, field); + addBuffer(ifArrayNotNull, multipartForm, formParamName, partType, buffer, field); break; case PRIMITIVE: // primitives are converted to text and sent as attribute @@ -1145,7 +1149,7 @@ private void addPojo(MethodCreator methodCreator, AssignableResultHandle multipa * add file upload, see {@link QuarkusMultipartForm#binaryFileUpload(String, String, String, String)} and * {@link QuarkusMultipartForm#textFileUpload(String, String, String, String)} */ - private void addFile(MethodCreator methodCreator, AssignableResultHandle multipartForm, String formParamName, + private void addFile(BytecodeCreator methodCreator, AssignableResultHandle multipartForm, String formParamName, String partType, ResultHandle filePath) { ResultHandle fileNamePath = methodCreator.invokeInterfaceMethod(PATH_GET_FILENAME, filePath); ResultHandle fileName = methodCreator.invokeVirtualMethod(OBJECT_TO_STRING, fileNamePath); @@ -1209,7 +1213,7 @@ private void addString(MethodCreator methodCreator, AssignableResultHandle multi multipartForm, methodCreator.load(formParamName), fieldValue)); } - private void addBuffer(MethodCreator methodCreator, AssignableResultHandle multipartForm, String formParamName, + private void addBuffer(BytecodeCreator methodCreator, AssignableResultHandle multipartForm, String formParamName, String partType, ResultHandle buffer, FieldInfo field) { if (partType == null) { throw new IllegalArgumentException( diff --git a/extensions/resteasy-reactive/rest-client-reactive/runtime/src/main/java/io/quarkus/rest/client/reactive/runtime/RestClientCDIDelegateBuilder.java b/extensions/resteasy-reactive/rest-client-reactive/runtime/src/main/java/io/quarkus/rest/client/reactive/runtime/RestClientCDIDelegateBuilder.java index b3fb164f97403..a43318d192056 100644 --- a/extensions/resteasy-reactive/rest-client-reactive/runtime/src/main/java/io/quarkus/rest/client/reactive/runtime/RestClientCDIDelegateBuilder.java +++ b/extensions/resteasy-reactive/rest-client-reactive/runtime/src/main/java/io/quarkus/rest/client/reactive/runtime/RestClientCDIDelegateBuilder.java @@ -300,7 +300,6 @@ private void configureBaseUrl(RestClientBuilder builder) { clientConfigByConfigKey().uri); if (propertyOptional.isEmpty()) { - // mstodo is the url there string? propertyOptional = oneOf(clientConfigByClassName().url, clientConfigByConfigKey().url); } 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 4a040d7b96301..7f9a5fc29232f 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 @@ -14,6 +14,7 @@ import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.MediaType; @@ -75,9 +76,11 @@ public String sendByteArrayWithPojo(@RestQuery @DefaultValue("true") Boolean wit @Consumes(MediaType.TEXT_PLAIN) @Produces(MediaType.TEXT_PLAIN) @Blocking - public String sendByteArray() { + public String sendByteArray(@QueryParam("nullFile") @DefaultValue("false") boolean nullFile) { WithByteArrayAsBinaryFile data = new WithByteArrayAsBinaryFile(); - data.file = HELLO_WORLD.getBytes(UTF_8); + if (!nullFile) { + data.file = HELLO_WORLD.getBytes(UTF_8); + } data.fileName = GREETING_TXT; return client.sendByteArrayAsBinaryFile(data); } @@ -87,9 +90,11 @@ public String sendByteArray() { @Consumes(MediaType.TEXT_PLAIN) @Produces(MediaType.TEXT_PLAIN) @Blocking - public String sendBuffer() { + public String sendBuffer(@QueryParam("nullFile") @DefaultValue("false") boolean nullFile) { WithBufferAsBinaryFile data = new WithBufferAsBinaryFile(); - data.file = Buffer.buffer(HELLO_WORLD); + if (!nullFile) { + data.file = Buffer.buffer(HELLO_WORLD); + } data.fileName = GREETING_TXT; return client.sendBufferAsBinaryFile(data); } @@ -99,16 +104,19 @@ public String sendBuffer() { @Consumes(MediaType.TEXT_PLAIN) @Produces(MediaType.TEXT_PLAIN) @Blocking - public String sendFileAsBinary() throws IOException { - File tempFile = File.createTempFile("quarkus-test", ".bin"); - tempFile.deleteOnExit(); + public String sendFileAsBinary(@QueryParam("nullFile") @DefaultValue("false") boolean nullFile) throws IOException { + WithFileAsBinaryFile data = new WithFileAsBinaryFile(); - try (FileOutputStream fileOutputStream = new FileOutputStream(tempFile)) { - fileOutputStream.write(HELLO_WORLD.getBytes()); - } + if (!nullFile) { + File tempFile = File.createTempFile("quarkus-test", ".bin"); + tempFile.deleteOnExit(); - WithFileAsBinaryFile data = new WithFileAsBinaryFile(); - data.file = tempFile; + try (FileOutputStream fileOutputStream = new FileOutputStream(tempFile)) { + fileOutputStream.write(HELLO_WORLD.getBytes()); + } + + data.file = tempFile; + } data.fileName = GREETING_TXT; return client.sendFileAsBinaryFile(data); } @@ -118,16 +126,19 @@ public String sendFileAsBinary() throws IOException { @Consumes(MediaType.TEXT_PLAIN) @Produces(MediaType.TEXT_PLAIN) @Blocking - public String sendPathAsBinary() throws IOException { - File tempFile = File.createTempFile("quarkus-test", ".bin"); - tempFile.deleteOnExit(); + public String sendPathAsBinary(@QueryParam("nullFile") @DefaultValue("false") boolean nullFile) throws IOException { + WithPathAsBinaryFile data = new WithPathAsBinaryFile(); - try (FileOutputStream fileOutputStream = new FileOutputStream(tempFile)) { - fileOutputStream.write(HELLO_WORLD.getBytes()); - } + if (!nullFile) { + File tempFile = File.createTempFile("quarkus-test", ".bin"); + tempFile.deleteOnExit(); - WithPathAsBinaryFile data = new WithPathAsBinaryFile(); - data.file = tempFile.toPath(); + try (FileOutputStream fileOutputStream = new FileOutputStream(tempFile)) { + fileOutputStream.write(HELLO_WORLD.getBytes()); + } + + data.file = tempFile.toPath(); + } data.fileName = GREETING_TXT; return client.sendPathAsBinaryFile(data); } @@ -198,7 +209,8 @@ public String sendPathAsText() throws IOException { @Path("/echo/binary") @Consumes(MediaType.MULTIPART_FORM_DATA) public String consumeMultipart(@MultipartForm MultipartBodyWithBinaryFile body) { - return String.format("fileOk:%s,nameOk:%s", containsHelloWorld(body.file), GREETING_TXT.equals(body.fileName)); + return String.format("fileOk:%s,nameOk:%s", body.file == null ? "null" : containsHelloWorld(body.file), + GREETING_TXT.equals(body.fileName)); } @POST 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 129166a254bfd..40dc80cd53147 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 @@ -22,6 +22,19 @@ public void shouldSendByteArrayAsBinaryFile() { // @formatter:on } + @Test + public void shouldSendNullByteArrayAsBinaryFile() { + // @formatter:off + given() + .queryParam("nullFile", "true") + .header("Content-Type", "text/plain") + .when().get("/client/byte-array-as-binary-file") + .then() + .statusCode(200) + .body(equalTo("fileOk:null,nameOk:true")); + // @formatter:on + } + @Test public void shouldSendBufferAsBinaryFile() { // @formatter:off @@ -34,6 +47,19 @@ public void shouldSendBufferAsBinaryFile() { // @formatter:on } + @Test + public void shouldSendNullBufferAsBinaryFile() { + // @formatter:off + given() + .queryParam("nullFile", "true") + .header("Content-Type", "text/plain") + .when().get("/client/buffer-as-binary-file") + .then() + .statusCode(200) + .body(equalTo("fileOk:null,nameOk:true")); + // @formatter:on + } + @Test public void shouldSendFileAsBinaryFile() { // @formatter:off @@ -46,6 +72,19 @@ public void shouldSendFileAsBinaryFile() { // @formatter:on } + @Test + public void shouldSendNullFileAsBinaryFile() { + // @formatter:off + given() + .queryParam("nullFile", "true") + .header("Content-Type", "text/plain") + .when().get("/client/file-as-binary-file") + .then() + .statusCode(200) + .body(equalTo("fileOk:null,nameOk:true")); + // @formatter:on + } + @Test public void shouldSendPathAsBinaryFile() { // @formatter:off @@ -58,6 +97,19 @@ public void shouldSendPathAsBinaryFile() { // @formatter:on } + @Test + public void shouldSendNullPathAsBinaryFile() { + // @formatter:off + given() + .queryParam("nullFile", "true") + .header("Content-Type", "text/plain") + .when().get("/client/path-as-binary-file") + .then() + .statusCode(200) + .body(equalTo("fileOk:null,nameOk:true")); + // @formatter:on + } + @Test public void shouldSendByteArrayAsTextFile() { // @formatter:off