Skip to content

Commit

Permalink
Merge pull request #45010 from brunobat/fix-template-tag
Browse files Browse the repository at this point in the history
Properly create REST Client template path when @url is used
geoand authored Dec 11, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
2 parents 19e7beb + 37c50ee commit 00e07bd
Showing 4 changed files with 141 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package io.quarkus.micrometer.deployment.binder;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;

import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.micrometer.core.instrument.Metrics;
import io.micrometer.core.instrument.Timer;
import io.micrometer.core.instrument.search.Search;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
import io.quarkus.rest.client.reactive.Url;
import io.quarkus.test.QuarkusUnitTest;

public class RestClientUriParameterTest {

final static SimpleMeterRegistry registry = new SimpleMeterRegistry();

@RegisterExtension
static final QuarkusUnitTest TEST = new QuarkusUnitTest()
.withApplicationRoot(
jar -> jar.addClasses(Resource.class, Client.class))
.overrideConfigKey("quarkus.redis.devservices.enabled", "false")
.overrideConfigKey("quarkus.rest-client.\"client\".url", "http://does-not-exist.io");

@RestClient
Client client;

@ConfigProperty(name = "quarkus.http.test-port")
Integer testPort;

@BeforeAll
static void setRegistry() {
Metrics.addRegistry(registry);
}

@AfterAll()
static void removeRegistry() {
Metrics.removeRegistry(registry);
}

@Test
public void testOverride() {
String result = client.getById("http://localhost:" + testPort, "bar");
assertEquals("bar", result);

Timer clientTimer = registry.find("http.client.requests").timer();
assertNotNull(clientTimer);
assertEquals("/example/{id}", clientTimer.getId().getTag("uri"));
}

private Search getMeter(String name) {
return registry.find(name);
}

@Path("/example")
@RegisterRestClient(baseUri = "http://dummy")
public interface Client {

@GET
@Path("/{id}")
String getById(@Url String baseUri, @PathParam("id") String id);
}

@Path("/example")
public static class Resource {

@RestClient
Client client;

@GET
@Path("/{id}")
@Produces(MediaType.TEXT_PLAIN)
public String example() {
return "bar";
}

@GET
@Path("/call")
@Produces(MediaType.TEXT_PLAIN)
public String call() {
return client.getById("http://localhost:8080", "1");
}
}
}
Original file line number Diff line number Diff line change
@@ -44,6 +44,14 @@ public class UriTagWithHttpRootTest {
@Inject
MeterRegistry registry;

@Test
public void testClient() throws InterruptedException {
when().get("/ping/one").then().statusCode(200);
Util.waitForMeters(registry.find("http.server.requests").timers(), 1);
Util.waitForMeters(registry.find("http.client.requests").timers(), 1);
Assertions.assertEquals(1, registry.find("http.client.requests").tag("uri", "/pong/{message}").timers().size());
}

@Test
public void testRequestUris() throws Exception {
RestAssured.basePath = "/";
Original file line number Diff line number Diff line change
@@ -955,8 +955,7 @@ A more full example of generated client (with sub-resource) can is at the bottom
classContext.constructor.getThis(),
baseTarget));
if (observabilityIntegrationNeeded) {
String templatePath = MULTIPLE_SLASH_PATTERN.matcher(restClientInterface.getPath() + method.getPath())
.replaceAll("/");
String templatePath = templatePath(restClientInterface, method);
classContext.constructor.invokeVirtualMethod(
MethodDescriptor.ofMethod(WebTargetImpl.class, "setPreClientSendHandler", void.class,
ClientRestHandler.class),
@@ -1012,11 +1011,25 @@ A more full example of generated client (with sub-resource) can is at the bottom
+ jandexMethod.name());
}

ResultHandle newInputTarget = methodParamNotNull.invokeVirtualMethod(
MethodDescriptor.ofMethod(WebTargetImpl.class, "withNewUri", WebTargetImpl.class,
java.net.URI.class),
methodParamNotNull.readInstanceField(inputTargetField, methodParamNotNull.getThis()),
newUri);
ResultHandle newInputTarget;
if (observabilityIntegrationNeeded) {
// we need to apply the ClientObservabilityHandler to the inputTarget field without altering it
newInputTarget = methodParamNotNull.invokeVirtualMethod(
MethodDescriptor.ofMethod(WebTargetImpl.class, "withNewUri", WebTargetImpl.class,
java.net.URI.class, ClientRestHandler.class),
methodParamNotNull.readInstanceField(inputTargetField, methodParamNotNull.getThis()),
newUri,
methodParamNotNull.newInstance(
MethodDescriptor.ofConstructor(ClientObservabilityHandler.class, String.class),
methodParamNotNull.load(templatePath(restClientInterface, method))));
} else {
// just read the inputTarget field and call withNewUri on it
newInputTarget = methodParamNotNull.invokeVirtualMethod(
MethodDescriptor.ofMethod(WebTargetImpl.class, "withNewUri", WebTargetImpl.class,
java.net.URI.class),
methodParamNotNull.readInstanceField(inputTargetField, methodParamNotNull.getThis()),
newUri);
}
ResultHandle newBaseTarget = methodParamNotNull.invokeVirtualMethod(
baseTargetProducer.getMethodDescriptor(),
methodParamNotNull.getThis(), newInputTarget);
@@ -1247,6 +1260,11 @@ A more full example of generated client (with sub-resource) can is at the bottom

}

private String templatePath(RestClientInterface restClientInterface, ResourceMethod method) {
return MULTIPLE_SLASH_PATTERN.matcher(restClientInterface.getPath() + method.getPath())
.replaceAll("/");
}

/**
* The @Encoded annotation is only supported in path/query/matrix/form params.
*/
Original file line number Diff line number Diff line change
@@ -259,6 +259,11 @@ public WebTargetImpl withNewUri(URI uri) {
return newInstance(client, UriBuilder.fromUri(uri), configuration);
}

@SuppressWarnings("unused") // this is used in the REST Client to support @BaseUrl and observability is enabled
public WebTargetImpl withNewUri(URI uri, ClientRestHandler preClientSendHandler) {
return newInstance(client, UriBuilder.fromUri(uri), configuration, preClientSendHandler);
}

@SuppressWarnings("unused")
public WebTargetImpl queryParams(MultivaluedMap<String, Object> parameters)
throws IllegalArgumentException, NullPointerException {
@@ -297,6 +302,12 @@ public WebTargetImpl queryParamNoTemplate(String name, Object... values) throws

protected WebTargetImpl newInstance(HttpClient client, UriBuilder uriBuilder,
ConfigurationImpl configuration) {
return newInstance(client, uriBuilder, configuration, preClientSendHandler);
}

protected WebTargetImpl newInstance(HttpClient client, UriBuilder uriBuilder,
ConfigurationImpl configuration,
ClientRestHandler preClientSendHandler) {
WebTargetImpl result = new WebTargetImpl(restClient, client, uriBuilder, configuration,
handlerChain.setPreClientSendHandler(preClientSendHandler),
requestContext);

0 comments on commit 00e07bd

Please sign in to comment.