Skip to content

Commit

Permalink
Merge branch '2.2.x'
Browse files Browse the repository at this point in the history
  • Loading branch information
spencergibb committed Jul 28, 2020
2 parents f6f2f47 + 8d5a3f8 commit 34d956a
Show file tree
Hide file tree
Showing 10 changed files with 200 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
Expand All @@ -30,14 +31,16 @@
import org.springframework.cloud.netflix.eureka.http.WebClientDiscoveryClientOptionalArgs;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;

/**
* @author Daniel Lavoie
*/
@Configuration(proxyBeanMethods = false)
public class DiscoveryClientOptionalArgsConfiguration {

protected final Log logger = LogFactory.getLog(getClass());
protected static final Log logger = LogFactory
.getLog(DiscoveryClientOptionalArgsConfiguration.class);

@Bean
@ConditionalOnClass(name = "org.springframework.web.client.RestTemplate")
Expand All @@ -51,21 +54,6 @@ public RestTemplateDiscoveryClientOptionalArgs restTemplateDiscoveryClientOption
return new RestTemplateDiscoveryClientOptionalArgs();
}

@Bean
@ConditionalOnMissingClass("com.sun.jersey.api.client.filter.ClientFilter")
@ConditionalOnClass(
name = "org.springframework.web.reactive.function.client.WebClient")
@ConditionalOnMissingBean(
value = { AbstractDiscoveryClientOptionalArgs.class,
RestTemplateDiscoveryClientOptionalArgs.class },
search = SearchStrategy.CURRENT)
@ConditionalOnProperty(prefix = "eureka.client", name = "webclient.enabled",
havingValue = "true")
public WebClientDiscoveryClientOptionalArgs webClientDiscoveryClientOptionalArgs() {
logger.info("Eureka HTTP Client uses WebClient.");
return new WebClientDiscoveryClientOptionalArgs();
}

@Bean
@ConditionalOnClass(name = "com.sun.jersey.api.client.filter.ClientFilter")
@ConditionalOnMissingBean(value = AbstractDiscoveryClientOptionalArgs.class,
Expand All @@ -75,6 +63,26 @@ public MutableDiscoveryClientOptionalArgs discoveryClientOptionalArgs() {
return new MutableDiscoveryClientOptionalArgs();
}

@ConditionalOnMissingClass("com.sun.jersey.api.client.filter.ClientFilter")
@ConditionalOnClass(
name = "org.springframework.web.reactive.function.client.WebClient")
@ConditionalOnProperty(prefix = "eureka.client", name = "webclient.enabled",
havingValue = "true")
protected static class WebClientConfiguration {

@Bean
@ConditionalOnMissingBean(
value = { AbstractDiscoveryClientOptionalArgs.class,
RestTemplateDiscoveryClientOptionalArgs.class },
search = SearchStrategy.CURRENT)
public WebClientDiscoveryClientOptionalArgs webClientDiscoveryClientOptionalArgs(
ObjectProvider<WebClient.Builder> builder) {
logger.info("Eureka HTTP Client uses WebClient.");
return new WebClientDiscoveryClientOptionalArgs(builder::getIfAvailable);
}

}

@Configuration
@ConditionalOnMissingClass({ "com.sun.jersey.api.client.filter.ClientFilter",
"org.springframework.web.reactive.function.client.WebClient" })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,14 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.SearchStrategy;
import org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration;
import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.config.client.ConfigServerInstanceProvider;
Expand All @@ -48,6 +52,7 @@
import org.springframework.core.env.Environment;
import org.springframework.http.HttpStatus;
import org.springframework.util.StringUtils;
import org.springframework.web.reactive.function.client.WebClient;

/**
* Bootstrap configuration for config client that wants to lookup the config server via
Expand All @@ -72,18 +77,6 @@ public EurekaClientConfigBean eurekaClientConfigBean() {
return new EurekaClientConfigBean();
}

@Bean
@ConditionalOnMissingBean(EurekaHttpClient.class)
@ConditionalOnClass(
name = "org.springframework.web.reactive.function.client.WebClient")
@ConditionalOnProperty(prefix = "eureka.client", name = "webclient.enabled",
havingValue = "true")
public WebClientEurekaHttpClient configDiscoveryWebClientEurekaHttpClient(
EurekaClientConfigBean config, Environment env) {
return (WebClientEurekaHttpClient) new WebClientTransportClientFactory()
.newClient(new DefaultEndpoint(getEurekaUrl(config, env)));
}

@Bean
@ConditionalOnMissingBean(EurekaHttpClient.class)
@ConditionalOnProperty(prefix = "eureka.client", name = "webclient.enabled",
Expand All @@ -94,7 +87,7 @@ public RestTemplateEurekaHttpClient configDiscoveryRestTemplateEurekaHttpClient(
.newClient(new DefaultEndpoint(getEurekaUrl(config, env)));
}

private String getEurekaUrl(EurekaClientConfigBean config, Environment env) {
private static String getEurekaUrl(EurekaClientConfigBean config, Environment env) {
List<String> urls = EndpointUtils.getDiscoveryServiceUrls(config,
EurekaClientConfigBean.DEFAULT_ZONE, new HostnameBasedUrlRandomizer(
env.getProperty("eureka.instance.hostname")));
Expand Down Expand Up @@ -170,4 +163,25 @@ public void randomize(List<String> urlList) {

}

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(
name = "org.springframework.web.reactive.function.client.WebClient")
@ConditionalOnProperty(prefix = "eureka.client", name = "webclient.enabled",
havingValue = "true")
@ImportAutoConfiguration({ CodecsAutoConfiguration.class,
WebClientAutoConfiguration.class })
protected static class WebClientConfiguration {

@Bean
@ConditionalOnMissingBean(EurekaHttpClient.class)
public WebClientEurekaHttpClient configDiscoveryWebClientEurekaHttpClient(
EurekaClientConfigBean config, ObjectProvider<WebClient.Builder> builder,
Environment env) {
return (WebClientEurekaHttpClient) new WebClientTransportClientFactory(
builder::getIfAvailable)
.newClient(new DefaultEndpoint(getEurekaUrl(config, env)));
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,26 @@

package org.springframework.cloud.netflix.eureka.http;

import java.util.function.Supplier;

import com.netflix.discovery.AbstractDiscoveryClientOptionalArgs;

import org.springframework.web.reactive.function.client.WebClient;

/**
* @author Daniel Lavoie
* @author Haytham Mohamed
*/
public class WebClientDiscoveryClientOptionalArgs
extends AbstractDiscoveryClientOptionalArgs<Void> {

@Deprecated
public WebClientDiscoveryClientOptionalArgs() {
setTransportClientFactories(new WebClientTransportClientFactories());
this(WebClient::builder);
}

public WebClientDiscoveryClientOptionalArgs(Supplier<WebClient.Builder> builder) {
setTransportClientFactories(new WebClientTransportClientFactories(builder));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,10 @@ public void shutdown() {
// Nothing to do
}

public WebClient getWebClient() {
return this.webClient;
}

private static Map<String, String> headersOf(ClientResponse response) {
ClientResponse.Headers httpHeaders = response.headers();
if (httpHeaders == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import java.util.Collection;
import java.util.Optional;
import java.util.function.Supplier;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
Expand All @@ -28,12 +29,20 @@
import com.netflix.discovery.shared.transport.jersey.EurekaJerseyClient;
import com.netflix.discovery.shared.transport.jersey.TransportClientFactories;

import org.springframework.web.reactive.function.client.WebClient;

/**
* @author Daniel Lavoie
* @author Haytham Mohamed
*/
public class WebClientTransportClientFactories implements TransportClientFactories<Void> {

private final Supplier<WebClient.Builder> builder;

public WebClientTransportClientFactories(Supplier<WebClient.Builder> builder) {
this.builder = builder;
}

@Override
public TransportClientFactory newTransportClientFactory(
Collection<Void> additionalFilters, EurekaJerseyClient providedJerseyClient) {
Expand All @@ -44,7 +53,7 @@ public TransportClientFactory newTransportClientFactory(
public TransportClientFactory newTransportClientFactory(
EurekaClientConfig clientConfig, Collection<Void> additionalFilters,
InstanceInfo myInstanceInfo) {
return new WebClientTransportClientFactory();
return new WebClientTransportClientFactory(builder);
}

@Override
Expand All @@ -53,7 +62,7 @@ public TransportClientFactory newTransportClientFactory(
final Collection<Void> additionalFilters, final InstanceInfo myInstanceInfo,
final Optional<SSLContext> sslContext,
final Optional<HostnameVerifier> hostnameVerifier) {
return new WebClientTransportClientFactory();
return new WebClientTransportClientFactory(builder);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import java.net.URI;
import java.net.URISyntaxException;
import java.util.function.Supplier;

import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.DeserializationFeature;
Expand All @@ -41,13 +42,13 @@

import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ClientCodecConfigurer;
import org.springframework.http.codec.json.Jackson2JsonDecoder;
import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import org.springframework.web.reactive.function.client.ExchangeFilterFunctions;
import org.springframework.web.reactive.function.client.ExchangeStrategies;
import org.springframework.web.reactive.function.client.WebClient;

/**
Expand All @@ -60,17 +61,29 @@
*/
public class WebClientTransportClientFactory implements TransportClientFactory {

private final Supplier<WebClient.Builder> builderSupplier;

@Deprecated
public WebClientTransportClientFactory() {
this(WebClient::builder);
}

public WebClientTransportClientFactory(Supplier<WebClient.Builder> builderSupplier) {
this.builderSupplier = builderSupplier;
}

@Override
public EurekaHttpClient newClient(EurekaEndpoint serviceUrl) {
WebClient.Builder builder = of(serviceUrl.getServiceUrl());
this.setExchangeStrategies(builder);
this.skipHttp400Error(builder);
public EurekaHttpClient newClient(EurekaEndpoint endpoint) {
// we want a copy to modify. Don't change the original
WebClient.Builder builder = this.builderSupplier.get().clone();
setUrl(builder, endpoint.getServiceUrl());
setCodecs(builder);
builder.filter(http4XxErrorExchangeFilterFunction());
return new WebClientEurekaHttpClient(builder.build());
}

private WebClient.Builder of(String serviceUrl) {
private WebClient.Builder setUrl(WebClient.Builder builder, String serviceUrl) {
String url = serviceUrl;
WebClient.Builder builder = WebClient.builder();
try {
URI serviceURI = new URI(serviceUrl);
if (serviceURI.getUserInfo() != null) {
Expand All @@ -88,23 +101,17 @@ private WebClient.Builder of(String serviceUrl) {
return builder.baseUrl(url);
}

private void setExchangeStrategies(WebClient.Builder builder) {
private void setCodecs(WebClient.Builder builder) {
ObjectMapper objectMapper = objectMapper();
ExchangeStrategies strategies = ExchangeStrategies.builder()
.codecs(clientDefaultCodecsConfigurer -> {
clientDefaultCodecsConfigurer.defaultCodecs()
.jackson2JsonEncoder(new Jackson2JsonEncoder(objectMapper,
MediaType.APPLICATION_JSON));
clientDefaultCodecsConfigurer.defaultCodecs()
.jackson2JsonDecoder(new Jackson2JsonDecoder(objectMapper,
MediaType.APPLICATION_JSON));

}).build();
builder.exchangeStrategies(strategies);
}
builder.codecs(configurer -> {
ClientCodecConfigurer.ClientDefaultCodecs defaults = configurer
.defaultCodecs();
defaults.jackson2JsonEncoder(
new Jackson2JsonEncoder(objectMapper, MediaType.APPLICATION_JSON));
defaults.jackson2JsonDecoder(
new Jackson2JsonDecoder(objectMapper, MediaType.APPLICATION_JSON));

private void skipHttp400Error(WebClient.Builder builder) {
builder.filter(http4XxErrorExchangeFilterFunction());
});
}

// Skip over 4xx http errors
Expand All @@ -114,9 +121,8 @@ private ExchangeFilterFunction http4XxErrorExchangeFilterFunction() {
if (clientResponse.statusCode().value() == 400) {
ClientResponse newResponse = ClientResponse.from(clientResponse)
.statusCode(HttpStatus.OK).build();
newResponse.body((clientHttpResponse, context) -> {
return clientHttpResponse.getBody();
});
newResponse.body(
(clientHttpResponse, context) -> clientHttpResponse.getBody());
return Mono.just(newResponse);
}
return Mono.just(clientResponse);
Expand Down
Loading

0 comments on commit 34d956a

Please sign in to comment.