Skip to content

Commit

Permalink
Allow usage of other multipart types in Reactive REST Client
Browse files Browse the repository at this point in the history
Fixes: #28026
  • Loading branch information
geoand committed Mar 3, 2023
1 parent 9c3141f commit 55e4353
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import jakarta.inject.Inject;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.FormParam;
import jakarta.ws.rs.HeaderParam;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.core.MediaType;
Expand Down Expand Up @@ -139,6 +140,17 @@ void shouldSendFromMultiEmittingOutsideEventLoop() {
assertThat(result).isEqualTo("myFile");
}

@Test
public void shouldPropertySetContentType() {
Client client = RestClientBuilder.newBuilder().baseUri(baseUri).build(Client.class);

ClientForm form = new ClientForm();
form.file = Multi.createBy().repeating().supplier(() -> (byte) 4).atMost(100);

assertThat(client.postMultipartToType(form)).startsWith("multipart/form-data");
assertThat(client.postMultipartMixedToType(form)).startsWith("multipart/mixed");
}

private void delayedEmit(AtomicLong i, MultiEmitter<? super Byte> em) {
vertx.setTimer(100, id -> {
long index = i.getAndIncrement();
Expand Down Expand Up @@ -190,6 +202,12 @@ public String uploadEmpty(@MultipartForm FormWithTwoFiles form) {
+ verifyFile(form.file2, 100, position -> (byte) 7);
}

@Path("type")
@POST
public String contentType(@HeaderParam("Content-Type") String contentType) {
return contentType;
}

private String verifyFile(FileUpload upload, int expectedSize, Function<Integer, Byte> expectedByte) {
var uploadedFile = upload.uploadedFile();
int size;
Expand Down Expand Up @@ -270,6 +288,16 @@ public interface Client {
@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
String postEmpty(@MultipartForm ClientForm form);

@Path("/type")
@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
String postMultipartToType(@MultipartForm ClientForm clientForm);

@Path("/type")
@POST
@Consumes("multipart/mixed")
String postMultipartMixedToType(@MultipartForm ClientForm clientForm);
}

public static class ClientForm {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import org.jboss.resteasy.reactive.common.core.Serialisers;
import org.jboss.resteasy.reactive.common.util.MultivaluedTreeMap;

import io.netty.handler.codec.http.HttpHeaderValues;
import io.netty.handler.codec.http.LastHttpContent;
import io.netty.handler.codec.http.multipart.InterfaceHttpData;
import io.smallrye.mutiny.Multi;
Expand Down Expand Up @@ -484,6 +485,19 @@ private QuarkusMultipartFormUpload setMultipartHeadersAndPrepareBody(HttpClientR
headerMap.put(multipartHeader, multipartHeaders.getAll(multipartHeader));
}

if (state.getEntity().getVariant() != null) {
Variant v = state.getEntity().getVariant();
String variantContentType = v.getMediaType().toString();
String multipartContentType = headerMap.getFirst(HttpHeaders.CONTENT_TYPE);
if (multipartContentType.startsWith(HttpHeaderValues.MULTIPART_FORM_DATA.toString())
&& !variantContentType.startsWith(HttpHeaderValues.MULTIPART_FORM_DATA.toString())) {
// this is a total hack whose purpose is to allow the @Consumes annotation to override the media type
int semicolonIndex = multipartContentType.indexOf(';');
headerMap.put(HttpHeaders.CONTENT_TYPE,
List.of(variantContentType + multipartContentType.substring(semicolonIndex)));
}
}

setVertxHeaders(httpClientRequest, headerMap);
return multipartFormUpload;
}
Expand Down

0 comments on commit 55e4353

Please sign in to comment.