Skip to content

Commit

Permalink
Properly implement ClientRequestContext#setEntity
Browse files Browse the repository at this point in the history
This method can be called by filters to override
the entity being sent by the JAX-RS client and
before this commit we were not properly handling
the case where either the entity was set to null
or only the body of the entity was being set
(and not the media type).

Fixes: quarkusio#33738
  • Loading branch information
geoand committed Jun 1, 2023
1 parent 8d4b3d1 commit 5ce027b
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 8 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package io.quarkus.rest.client.reactive.provider;

import static org.assertj.core.api.Assertions.assertThat;

import java.io.IOException;
import java.net.URI;

import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.client.ClientRequestContext;
import jakarta.ws.rs.client.ClientRequestFilter;

import org.eclipse.microprofile.rest.client.RestClientBuilder;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.test.QuarkusUnitTest;
import io.quarkus.test.common.http.TestHTTPResource;

public class EntitySettingRequestFilterTest {

@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.withApplicationRoot((jar) -> jar.addClasses(Resource.class, Client.class, EntityRequestFilter.class));

@TestHTTPResource
URI baseUri;

@Test
void testNullEntity() {
Client client = RestClientBuilder.newBuilder().baseUri(baseUri).register(new EntityRequestFilter(null))
.build(Client.class);
assertThat(client.call("ignored")).isEqualTo("null");
}

@Test
void testNonNullEntity() {
Client client = RestClientBuilder.newBuilder().baseUri(baseUri).register(new EntityRequestFilter("foo"))
.build(Client.class);
assertThat(client.call("ignored")).isEqualTo("foo");
}

@Path("/")
public static class Resource {
@POST
public String returnHeaders(String body) {
if ((body == null) || body.isEmpty()) {
return "null";
}
return body;
}
}

public interface Client {

@Path("/")
@POST
String call(String body);
}

public static class EntityRequestFilter implements ClientRequestFilter {

private final String entity;

public EntityRequestFilter(String entity) {
this.entity = entity;
}

@Override
public void filter(ClientRequestContext context) throws IOException {
context.setEntity(entity);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,12 @@ public Locale getLanguage() {

@Override
public MediaType getMediaType() {
if (restClientRequestContext.entity == null) {
return null;
}
// those come from the entity
return restClientRequestContext.entity != null ? restClientRequestContext.entity.getMediaType() : null;
return restClientRequestContext.entity.getMediaType() == RestClientRequestContext.IGNORED_MEDIA_TYPE ? null
: restClientRequestContext.entity.getMediaType();
}

@Override
Expand Down Expand Up @@ -515,12 +519,8 @@ private boolean isContentType(Object key) {
}

private String mediaType() {
Entity<?> entity = restClientRequestContext.entity;
return entity == null
? null
: entity.getMediaType() == null
? null
: entity.getMediaType().toString();
MediaType mediaType = getMediaType();
return mediaType == null ? null : mediaType.toString();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ public class RestClientRequestContext extends AbstractResteasyReactiveContext<Re
public static final String DEFAULT_CONTENT_TYPE_PROP = "io.quarkus.rest.client.defaultContentType";
private static final String TMP_FILE_PATH_KEY = "tmp_file_path";

static final MediaType IGNORED_MEDIA_TYPE = new MediaType("ignored", "ignored");

private final HttpClient httpClient;
// Changeable by the request filter
String httpMethod;
Expand Down Expand Up @@ -273,7 +275,14 @@ public Buffer writeEntity(Entity<?> entity, MultivaluedMap<String, String> heade
}

public void setEntity(Object entity, Annotation[] annotations, MediaType mediaType) {
this.entity = Entity.entity(entity, mediaType, annotations);
if (entity == null) {
this.entity = null;
} else {
if (mediaType == null) {
mediaType = IGNORED_MEDIA_TYPE; // we need this in order to avoid getting IAE from Variant...
}
this.entity = Entity.entity(entity, mediaType, annotations);
}
}

public CompletableFuture<ResponseImpl> getResult() {
Expand Down

0 comments on commit 5ce027b

Please sign in to comment.