Skip to content

Commit

Permalink
Merge branch 'quarkusio:main' into datasource-devservices-showLogs-sq…
Browse files Browse the repository at this point in the history
…uashed
  • Loading branch information
DeMol-EE authored Nov 12, 2024
2 parents 52ebb92 + c41dfd6 commit d1394b6
Show file tree
Hide file tree
Showing 17 changed files with 332 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,29 @@
public abstract class AbstractRestClientConfigBuilder implements ConfigBuilder {
private static final String REST_CLIENT_PREFIX = "quarkus.rest-client.";

private final boolean runtime;

public AbstractRestClientConfigBuilder() {
this.runtime = true;
RestClientsConfig.RestClientKeysProvider.KEYS.clear();
}

public AbstractRestClientConfigBuilder(boolean runtime) {
this.runtime = runtime;
}

@Override
public SmallRyeConfigBuilder configBuilder(final SmallRyeConfigBuilder builder) {
RestClientsConfig.RestClientKeysProvider.KEYS.clear();
List<RegisteredRestClient> restClients = getRestClients();

Map<String, String> quarkusFallbacks = new HashMap<>();
Map<String, String> microProfileFallbacks = new HashMap<>();
// relocates [All Combinations] -> quarkus.rest-client."FQN".*
Map<String, String> relocates = new HashMap<>();
for (RegisteredRestClient restClient : restClients) {
RestClientsConfig.RestClientKeysProvider.KEYS.add(restClient.getFullName());
if (runtime) {
RestClientsConfig.RestClientKeysProvider.KEYS.add(restClient.getFullName());
}

// FQN -> Simple Name
String quotedFullName = "\"" + restClient.getFullName() + "\"";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@
import io.quarkus.runtime.annotations.ConfigPhase;
import io.quarkus.runtime.annotations.ConfigRoot;
import io.smallrye.config.ConfigMapping;
import io.smallrye.config.ConfigValue;
import io.smallrye.config.SmallRyeConfig;
import io.smallrye.config.SmallRyeConfigBuilder;
import io.smallrye.config.SmallRyeConfigBuilderCustomizer;
import io.smallrye.config.WithDefault;
import io.smallrye.config.WithDefaults;
import io.smallrye.config.WithName;
import io.smallrye.config.WithParentName;

@ConfigMapping(prefix = "quarkus.rest-client")
Expand All @@ -30,6 +32,14 @@ public interface RestClientsBuildTimeConfig {
@WithDefaults
Map<String, RestClientBuildConfig> clients();

/**
* If true, the extension will automatically remove the trailing slash in the paths if any.
* This property is not applicable to the RESTEasy Client.
*/
@WithName("removes-trailing-slash")
@WithDefault("true")
boolean removesTrailingSlash();

interface RestClientBuildConfig {

/**
Expand Down Expand Up @@ -69,6 +79,14 @@ interface RestClientBuildConfig {
* </ul>
*/
Optional<String> localProxyProvider();

/**
* If true, the extension will automatically remove the trailing slash in the paths if any.
* This property is not applicable to the RESTEasy Client.
*/
@WithName("removes-trailing-slash")
@WithDefault("true")
boolean removesTrailingSlash();
}

/**
Expand All @@ -83,10 +101,15 @@ interface RestClientBuildConfig {
* @return a {@link RestClientsBuildTimeConfig} with the discovered registered REST Clients configuration only.
*/
default RestClientsBuildTimeConfig get(List<RegisteredRestClient> restClients) {
SmallRyeConfig config = new SmallRyeConfigBuilder()
return getConfig(restClients).getConfigMapping(RestClientsBuildTimeConfig.class);
}

default SmallRyeConfig getConfig(List<RegisteredRestClient> restClients) {
return new SmallRyeConfigBuilder()
.withSources(
new ConfigSource() {
final SmallRyeConfig config = ConfigProvider.getConfig().unwrap(SmallRyeConfig.class);
final ConfigSource defaultsSource = getDefaultsSource();

@Override
public Set<String> getPropertyNames() {
Expand All @@ -97,18 +120,30 @@ public Set<String> getPropertyNames() {

@Override
public String getValue(final String propertyName) {
return config.getRawValue(propertyName);
ConfigValue configValue = config.getConfigValue(propertyName);
if (configValue != null && !defaultsSource.getName().equals(configValue.getSourceName())) {
return configValue.getValue();
}
return null;
}

@Override
public String getName() {
return "SmallRye Config";
}

private ConfigSource getDefaultsSource() {
ConfigSource configSource = null;
for (ConfigSource source : config.getConfigSources()) {
configSource = source;
}
return configSource;
}
})
.withCustomizers(new SmallRyeConfigBuilderCustomizer() {
@Override
public void configBuilder(final SmallRyeConfigBuilder builder) {
new AbstractRestClientConfigBuilder() {
new AbstractRestClientConfigBuilder(false) {
@Override
public List<RegisteredRestClient> getRestClients() {
return restClients;
Expand All @@ -119,7 +154,5 @@ public List<RegisteredRestClient> getRestClients() {
.withMapping(RestClientsBuildTimeConfig.class)
.withMappingIgnore("quarkus.**")
.build();

return config.getConfigMapping(RestClientsBuildTimeConfig.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

Expand Down Expand Up @@ -232,6 +233,19 @@ public List<RegisteredRestClient> getRestClients() {
assertThat(restClientConfig.uri().get()).isEqualTo("http://localhost:8082");
}

@Test
void buildTimeConfig() {
SmallRyeConfig config = ConfigUtils.emptyConfigBuilder()
.withMapping(RestClientsBuildTimeConfig.class)
.build();
assertNotNull(config);

RestClientsBuildTimeConfig buildTimeConfig = config.getConfigMapping(RestClientsBuildTimeConfig.class)
.get(List.of(new RegisteredRestClient(ConfigKeyRestClient.class, "key")));

assertFalse(buildTimeConfig.clients().get(ConfigKeyRestClient.class.getName()).removesTrailingSlash());
}

private void verifyConfig(RestClientConfig config) {
assertTrue(config.url().isPresent());
assertThat(config.url().get()).isEqualTo("http://localhost:8080");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ quarkus.rest-client."io.quarkus.restclient.config.FullNameRestClient".connection
quarkus.rest-client."io.quarkus.restclient.config.FullNameRestClient".connection-pool-size=10
quarkus.rest-client."io.quarkus.restclient.config.FullNameRestClient".max-chunk-size=1024

quarkus.rest-client.key.removes-trailing-slash=false
quarkus.rest-client.key.url=http://localhost:8080
quarkus.rest-client.key.uri=http://localhost:8081
quarkus.rest-client.key.scope=Singleton
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,9 @@ void setupClientProxies(JaxrsClientReactiveRecorder recorder,
List<RestClientDefaultProducesBuildItem> defaultConsumes,
List<RestClientDefaultConsumesBuildItem> defaultProduces,
List<RestClientDisableSmartDefaultProduces> disableSmartDefaultProduces,
List<RestClientDisableRemovalTrailingSlashBuildItem> disableRemovalTrailingSlashProduces,
List<ParameterContainersBuildItem> parameterContainersBuildItems) {

String defaultConsumesType = defaultMediaType(defaultConsumes, MediaType.APPLICATION_OCTET_STREAM);
String defaultProducesType = defaultMediaType(defaultProduces, MediaType.TEXT_PLAIN);

Expand Down Expand Up @@ -403,8 +405,9 @@ public void accept(EndpointIndexer.ResourceMethodCallbackEntry entry) {
ClassInfo clazz = index.getClassByName(i.getKey());
//these interfaces can also be clients
//so we generate client proxies for them
MaybeRestClientInterface maybeClientProxy = clientEndpointIndexer.createClientProxy(clazz,
i.getValue());
String path = sanitizePath(i.getValue(),
isRemovalTrailingSlashEnabled(i.getKey(), disableRemovalTrailingSlashProduces));
MaybeRestClientInterface maybeClientProxy = clientEndpointIndexer.createClientProxy(clazz, path);
if (maybeClientProxy.exists()) {
RestClientInterface clientProxy = maybeClientProxy.getRestClientInterface();
try {
Expand Down Expand Up @@ -3076,6 +3079,30 @@ private void addCookieParam(BytecodeCreator invoBuilderEnricher, AssignableResul
invocationBuilder, notNullValue.load(paramName), cookieParamHandle));
}

private String sanitizePath(String path, boolean removesTrailingSlash) {
if (!path.startsWith("/")) {
path = "/" + path;
}

// For the client side, by default, we're only removing the trailing slash for the
// `@Path` annotations at class level which is configurable.
if (removesTrailingSlash && path.endsWith("/")) {
path = path.substring(0, path.length() - 1);
}
return path;
}

private boolean isRemovalTrailingSlashEnabled(DotName restClientName,
List<RestClientDisableRemovalTrailingSlashBuildItem> buildItems) {
for (RestClientDisableRemovalTrailingSlashBuildItem buildItem : buildItems) {
if (buildItem.getClients().contains(restClientName)) {
return false;
}
}

return true;
}

private enum ReturnCategory {
BLOCKING,
COMPLETION_STAGE,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package io.quarkus.jaxrs.client.reactive.deployment;

import java.util.List;

import org.jboss.jandex.DotName;

import io.quarkus.builder.item.MultiBuildItem;

/**
* This build item disables the removal of trailing slashes from the paths.
*/
public final class RestClientDisableRemovalTrailingSlashBuildItem extends MultiBuildItem {
private final List<DotName> clients;

public RestClientDisableRemovalTrailingSlashBuildItem(List<DotName> clients) {
this.clients = clients;
}

public List<DotName> getClients() {
return clients;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@
import io.quarkus.jaxrs.client.reactive.deployment.JaxrsClientReactiveEnricherBuildItem;
import io.quarkus.jaxrs.client.reactive.deployment.RestClientDefaultConsumesBuildItem;
import io.quarkus.jaxrs.client.reactive.deployment.RestClientDefaultProducesBuildItem;
import io.quarkus.jaxrs.client.reactive.deployment.RestClientDisableRemovalTrailingSlashBuildItem;
import io.quarkus.jaxrs.client.reactive.deployment.RestClientDisableSmartDefaultProduces;
import io.quarkus.rest.client.reactive.runtime.AnnotationRegisteredProviders;
import io.quarkus.rest.client.reactive.runtime.HeaderCapturingServerFilter;
Expand All @@ -108,6 +109,7 @@
import io.quarkus.rest.client.reactive.runtime.RestClientReactiveConfig;
import io.quarkus.rest.client.reactive.runtime.RestClientRecorder;
import io.quarkus.rest.client.reactive.spi.RestClientAnnotationsTransformerBuildItem;
import io.quarkus.restclient.config.RegisteredRestClient;
import io.quarkus.restclient.config.RestClientsBuildTimeConfig;
import io.quarkus.restclient.config.RestClientsConfig;
import io.quarkus.restclient.config.deployment.RestClientConfigUtils;
Expand Down Expand Up @@ -159,15 +161,32 @@ ServiceProviderBuildItem nativeSpiSupport() {
}

@BuildStep
void setUpDefaultMediaType(BuildProducer<RestClientDefaultConsumesBuildItem> consumes,
void setUpClientBuildTimeProperties(BuildProducer<RestClientDefaultConsumesBuildItem> consumes,
BuildProducer<RestClientDefaultProducesBuildItem> produces,
BuildProducer<RestClientDisableSmartDefaultProduces> disableSmartProduces,
RestClientReactiveConfig config) {
BuildProducer<RestClientDisableRemovalTrailingSlashBuildItem> disableRemovalTrailingSlash,
RestClientReactiveConfig config,
RestClientsBuildTimeConfig configsPerClient,
List<RegisteredRestClientBuildItem> registeredRestClientBuildItems) {
consumes.produce(new RestClientDefaultConsumesBuildItem(MediaType.APPLICATION_JSON, 10));
produces.produce(new RestClientDefaultProducesBuildItem(MediaType.APPLICATION_JSON, 10));
if (config.disableSmartProduces()) {
disableSmartProduces.produce(new RestClientDisableSmartDefaultProduces());
}

List<RegisteredRestClient> registeredRestClients = toRegisteredRestClients(registeredRestClientBuildItems);
RestClientsBuildTimeConfig buildTimeConfig = configsPerClient.get(registeredRestClients);

List<DotName> clientsToDisable = new ArrayList<>();
for (RegisteredRestClientBuildItem registeredRestClient : registeredRestClientBuildItems) {
if (removesTrailingSlashIsDisabled(buildTimeConfig, registeredRestClient)) {
clientsToDisable.add(registeredRestClient.getClassInfo().name());
}
}

if (!clientsToDisable.isEmpty()) {
disableRemovalTrailingSlash.produce(new RestClientDisableRemovalTrailingSlashBuildItem(clientsToDisable));
}
}

@BuildStep
Expand Down Expand Up @@ -412,7 +431,6 @@ void determineRegisteredRestClients(CombinedIndexBuildItem combinedIndexBuildIte
Set<DotName> seen = new HashSet<>();

List<AnnotationInstance> actualInstances = index.getAnnotations(REGISTER_REST_CLIENT);
List<RegisteredRestClientBuildItem> registeredRestClientBuildItems = new ArrayList<>();
for (AnnotationInstance instance : actualInstances) {
AnnotationTarget annotationTarget = instance.target();
ClassInfo classInfo = annotationTarget.asClass();
Expand Down Expand Up @@ -841,11 +859,17 @@ private boolean isRestMethod(MethodInfo method) {
return false;
}

private Optional<String> getConfigKey(AnnotationInstance registerRestClientAnnotation) {
AnnotationValue configKeyValue = registerRestClientAnnotation.value("configKey");
return configKeyValue != null
? Optional.of(configKeyValue.asString())
: Optional.empty();
private boolean removesTrailingSlashIsDisabled(RestClientsBuildTimeConfig config,
RegisteredRestClientBuildItem registeredRestClient) {
// is disabled for all the clients
if (!config.removesTrailingSlash()) {
return true;
}

// is disabled for this concrete client
return !config.clients()
.get(registeredRestClient.getClassInfo().name().toString())
.removesTrailingSlash();
}

private ScopeInfo computeDefaultScope(Capabilities capabilities, Config config,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
import java.util.stream.Collectors;

import org.apache.commons.lang3.exception.UncheckedException;
import org.eclipse.microprofile.config.ConfigProvider;
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.IndexView;
import org.jboss.logging.Logger;
Expand All @@ -32,6 +31,7 @@
import io.quarkus.rest.client.reactive.deployment.RegisteredRestClientBuildItem;
import io.quarkus.rest.client.reactive.spi.DevServicesRestClientProxyProvider;
import io.quarkus.rest.client.reactive.spi.RestClientHttpProxyBuildItem;
import io.quarkus.restclient.config.RegisteredRestClient;
import io.quarkus.restclient.config.RestClientsBuildTimeConfig;
import io.quarkus.restclient.config.RestClientsBuildTimeConfig.RestClientBuildConfig;
import io.smallrye.config.SmallRyeConfig;
Expand Down Expand Up @@ -60,14 +60,15 @@ public void determineRequiredProxies(
CombinedIndexBuildItem combinedIndexBuildItem,
List<RegisteredRestClientBuildItem> registeredRestClientBuildItems,
BuildProducer<RestClientHttpProxyBuildItem> producer) {
Map<String, RestClientBuildConfig> configs = clientsConfig.get(toRegisteredRestClients(registeredRestClientBuildItems))
.clients();

List<RegisteredRestClient> registeredRestClients = toRegisteredRestClients(registeredRestClientBuildItems);
Map<String, RestClientBuildConfig> configs = clientsConfig.get(registeredRestClients).clients();
if (configs.isEmpty()) {
return;
}

IndexView index = combinedIndexBuildItem.getIndex();
SmallRyeConfig config = ConfigProvider.getConfig().unwrap(SmallRyeConfig.class);
SmallRyeConfig config = clientsConfig.getConfig(registeredRestClients);
for (var configEntry : configs.entrySet()) {
if (!configEntry.getValue().enableLocalProxy()) {
log.trace("Ignoring config key: '" + configEntry.getKey() + "' because enableLocalProxy is false");
Expand Down
Loading

0 comments on commit d1394b6

Please sign in to comment.