Compare commits

..
17 Commits
Author SHA1 Message Date
buildmaster 245b106a76 Bumping versions 2022-09-11 23:33:49 +00:00
Olga Maciaszek-Sharma 666a59df6b Adjust to changes in commons. 2022-09-05 16:50:00 +02:00
Olga Maciaszek-Sharma 5a21e22002 Merge remote-tracking branch 'origin/3.1.x' 2022-09-05 16:43:41 +02:00
Olga Maciaszek-Sharma bdcbaa7f3b Allow overriding binary content types. Fixes gh-734. 2022-09-05 16:37:12 +02:00
buildmaster 375241803d Bumping versions to 3.1.5-SNAPSHOT after release 2022-09-02 23:46:06 +00:00
buildmaster 0213d4be21 Going back to snapshots 2022-09-02 23:46:05 +00:00
buildmaster 73cde28fcf Update SNAPSHOT to 3.1.4 2022-09-02 23:44:34 +00:00
小魏,小魏,我们要去哪里呀 5bddccf720 Customize load balanced requests according to the chosen ServiceInstance (#735) 2022-09-01 11:38:09 +02:00
Olga Maciaszek-Sharma 5f40f245af Merge remote-tracking branch 'origin/main' 2022-08-31 12:40:12 +02:00
buildmaster e4bdc13c51 Going back to snapshots 2022-07-29 19:39:18 +00:00
Olga Maciaszek-Sharma 26e157fd46 Merge remote-tracking branch 'origin/3.1.x' 2022-07-25 16:43:26 +02:00
Olga Maciaszek-Sharma efbf71294d Merge remote-tracking branch 'origin/3.0.x' into 3.1.x 2022-07-25 16:27:38 +02:00
fml2 b4c9567de5 Update spring-cloud-openfeign.adoc 2022-07-25 16:00:28 +02:00
fml2 9529e43c01 Update spring-cloud-openfeign.adoc 2022-07-25 15:52:05 +02:00
Kwangyong Kim a26095bb6c Fix a typo in sample code
I found a typo in the latest release.
It should be `@FeignClient(url = "http://localhost:8080")`
2022-07-25 15:22:52 +02:00
Nikita Konev 8fdb488697 fix cascading deserialization Spring Data's Page by setting @JsonIgnoreProperties(ignoreUnknown = true), revert ignoring getTotalPages(), getNumberOfElements(), isFirst(), isLast() (#653) 2022-07-25 15:12:22 +02:00
spencergibb 8989036e93 Removes libs-*-local repos 2022-07-18 12:59:55 -04:00
18 changed files with 277 additions and 52 deletions
+1 -1
View File
@@ -6,7 +6,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-openfeign</artifactId>
<version>4.0.0-M4</version>
<version>4.0.0-SNAPSHOT</version>
</parent>
<artifactId>spring-cloud-openfeign-docs</artifactId>
<packaging>jar</packaging>
@@ -204,7 +204,7 @@ spring:
Default configurations can be specified in the `@EnableFeignClients` attribute `defaultConfiguration` in a similar manner as described above. The difference is that this configuration will apply to _all_ feign clients.
If you prefer using configuration properties to configured all `@FeignClient`, you can create configuration properties with `default` feign name.
If you prefer using configuration properties to configure all `@FeignClient`, you can create configuration properties with `default` feign name.
You can use `spring.cloud.openfeign.client.config.feignName.defaultQueryParameters` and `spring.cloud.openfeign.client.config.feignName.defaultRequestHeaders` to specify query parameters and headers that will be sent with every request of the client named `feignName`.
@@ -385,7 +385,7 @@ For example, if you had this Feign client
[source,java,indent=0]
----
@FeignClienturl = "http://localhost:8080")
@FeignClient(url = "http://localhost:8080")
public interface DemoClient {
@GetMapping("demo")
@@ -815,6 +815,33 @@ Sometimes, when load balancing is enabled for Feign clients, you may want to use
spring.cloud.openfeign.oauth2.load-balanced=true
----
=== Transform the load-balanced HTTP request
You can use the selected `ServiceInstance` to transform the load-balanced HTTP Request.
For `Request`, you need to implement and define `LoadBalancerFeignRequestTransformer`, as follows:
[source,java,indent=0]
----
@Bean
public LoadBalancerFeignRequestTransformer transformer() {
return new LoadBalancerFeignRequestTransformer() {
@Override
public Request transformRequest(Request request, ServiceInstance instance) {
Map<String, Collection<String>> headers = new HashMap<>(request.headers());
headers.put("X-ServiceId", Collections.singletonList(instance.getServiceId()));
headers.put("X-InstanceId", Collections.singletonList(instance.getInstanceId()));
return Request.create(request.httpMethod(), request.url(), headers, request.body(), request.charset(),
request.requestTemplate());
}
};
}
----
If multiple transformers are defined, they are applied in the order in which beans are defined.
Alternatively, you can use `LoadBalancerFeignRequestTransformer.DEFAULT_ORDER` to specify the order.
== Configuration properties
To see the list of all Spring Cloud OpenFeign related configuration properties please check link:appendix.html[the Appendix page].
+3 -3
View File
@@ -4,14 +4,14 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-openfeign</artifactId>
<version>4.0.0-M4</version>
<version>4.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Spring Cloud OpenFeign</name>
<description>Spring Cloud OpenFeign</description>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-build</artifactId>
<version>4.0.0-M4</version>
<version>4.0.0-SNAPSHOT</version>
<relativePath/>
</parent>
<scm>
@@ -26,7 +26,7 @@
<properties>
<main.basedir>${basedir}</main.basedir>
<jackson.version>2.11.3</jackson.version>
<spring-cloud-commons.version>4.0.0-M4</spring-cloud-commons.version>
<spring-cloud-commons.version>4.0.0-SNAPSHOT</spring-cloud-commons.version>
<!-- Plugin versions -->
<maven-eclipse-plugin.version>2.10</maven-eclipse-plugin.version>
+1 -1
View File
@@ -6,7 +6,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-openfeign</artifactId>
<version>4.0.0-M4</version>
<version>4.0.0-SNAPSHOT</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-openfeign-core</artifactId>
@@ -16,6 +16,8 @@
package org.springframework.cloud.openfeign.loadbalancer;
import java.util.List;
import feign.Client;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
@@ -36,6 +38,7 @@ import org.springframework.context.annotation.Configuration;
* that uses {@link Client.Default} under the hood.
*
* @author Olga Maciaszek-Sharma
* @author changjin wei(魏昌进)
* @since 2.2.0
*/
@Configuration(proxyBeanMethods = false)
@@ -46,9 +49,10 @@ class DefaultFeignLoadBalancerConfiguration {
@ConditionalOnMissingBean
@Conditional(OnRetryNotEnabledCondition.class)
public Client feignClient(LoadBalancerClient loadBalancerClient,
LoadBalancerClientFactory loadBalancerClientFactory) {
LoadBalancerClientFactory loadBalancerClientFactory,
List<LoadBalancerFeignRequestTransformer> transformers) {
return new FeignBlockingLoadBalancerClient(new Client.Default(null, null), loadBalancerClient,
loadBalancerClientFactory);
loadBalancerClientFactory, transformers);
}
@Bean
@@ -58,9 +62,10 @@ class DefaultFeignLoadBalancerConfiguration {
@ConditionalOnProperty(value = "spring.cloud.loadbalancer.retry.enabled", havingValue = "true",
matchIfMissing = true)
public Client feignRetryClient(LoadBalancerClient loadBalancerClient,
LoadBalancedRetryFactory loadBalancedRetryFactory, LoadBalancerClientFactory loadBalancerClientFactory) {
LoadBalancedRetryFactory loadBalancedRetryFactory, LoadBalancerClientFactory loadBalancerClientFactory,
List<LoadBalancerFeignRequestTransformer> transformers) {
return new RetryableFeignBlockingLoadBalancerClient(new Client.Default(null, null), loadBalancerClient,
loadBalancedRetryFactory, loadBalancerClientFactory);
loadBalancedRetryFactory, loadBalancerClientFactory, transformers);
}
}
@@ -19,6 +19,8 @@ package org.springframework.cloud.openfeign.loadbalancer;
import java.io.IOException;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import feign.Client;
@@ -49,6 +51,7 @@ import static org.springframework.cloud.openfeign.loadbalancer.LoadBalancerUtils
* {@link ServiceInstance} to use while resolving the request host.
*
* @author Olga Maciaszek-Sharma
* @author changjin wei(魏昌进)
* @since 2.2.0
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -62,9 +65,11 @@ public class FeignBlockingLoadBalancerClient implements Client {
private final LoadBalancerClientFactory loadBalancerClientFactory;
private final List<LoadBalancerFeignRequestTransformer> transformers;
/**
* @deprecated in favour of
* {@link FeignBlockingLoadBalancerClient#FeignBlockingLoadBalancerClient(Client, LoadBalancerClient, LoadBalancerClientFactory)}
* {@link FeignBlockingLoadBalancerClient#FeignBlockingLoadBalancerClient(Client, LoadBalancerClient, LoadBalancerClientFactory, List)}
*/
@Deprecated
public FeignBlockingLoadBalancerClient(Client delegate, LoadBalancerClient loadBalancerClient,
@@ -72,13 +77,29 @@ public class FeignBlockingLoadBalancerClient implements Client {
this.delegate = delegate;
this.loadBalancerClient = loadBalancerClient;
this.loadBalancerClientFactory = loadBalancerClientFactory;
this.transformers = Collections.emptyList();
}
/**
* @deprecated in favour of
* {@link FeignBlockingLoadBalancerClient#FeignBlockingLoadBalancerClient(Client, LoadBalancerClient, LoadBalancerClientFactory, List)}
*/
@Deprecated
public FeignBlockingLoadBalancerClient(Client delegate, LoadBalancerClient loadBalancerClient,
LoadBalancerClientFactory loadBalancerClientFactory) {
this.delegate = delegate;
this.loadBalancerClient = loadBalancerClient;
this.loadBalancerClientFactory = loadBalancerClientFactory;
this.transformers = Collections.emptyList();
}
public FeignBlockingLoadBalancerClient(Client delegate, LoadBalancerClient loadBalancerClient,
LoadBalancerClientFactory loadBalancerClientFactory,
List<LoadBalancerFeignRequestTransformer> transformers) {
this.delegate = delegate;
this.loadBalancerClient = loadBalancerClient;
this.loadBalancerClientFactory = loadBalancerClientFactory;
this.transformers = transformers;
}
@Override
@@ -109,7 +130,7 @@ public class FeignBlockingLoadBalancerClient implements Client {
.body(message, StandardCharsets.UTF_8).build();
}
String reconstructedUrl = loadBalancerClient.reconstructURI(instance, originalUri).toString();
Request newRequest = buildRequest(request, reconstructedUrl);
Request newRequest = buildRequest(request, reconstructedUrl, instance);
return executeWithLoadBalancerLifecycleProcessing(delegate, options, newRequest, lbRequest, lbResponse,
supportedLifecycleProcessors);
}
@@ -119,6 +140,16 @@ public class FeignBlockingLoadBalancerClient implements Client {
request.charset(), request.requestTemplate());
}
protected Request buildRequest(Request request, String reconstructedUrl, ServiceInstance instance) {
Request newRequest = buildRequest(request, reconstructedUrl);
if (transformers != null) {
for (LoadBalancerFeignRequestTransformer transformer : transformers) {
newRequest = transformer.transformRequest(newRequest, instance);
}
}
return newRequest;
}
// Visible for Sleuth instrumentation
public Client getDelegate() {
return delegate;
@@ -16,6 +16,8 @@
package org.springframework.cloud.openfeign.loadbalancer;
import java.util.List;
import feign.Client;
import feign.hc5.ApacheHttp5Client;
import org.apache.hc.client5.http.classic.HttpClient;
@@ -40,6 +42,7 @@ import org.springframework.context.annotation.Import;
* that uses {@link ApacheHttp5Client} under the hood.
*
* @author Nguyen Ky Thanh
* @author changjin wei(魏昌进)
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(ApacheHttp5Client.class)
@@ -53,9 +56,11 @@ class HttpClient5FeignLoadBalancerConfiguration {
@ConditionalOnMissingBean
@Conditional(OnRetryNotEnabledCondition.class)
public Client feignClient(LoadBalancerClient loadBalancerClient, HttpClient httpClient5,
LoadBalancerClientFactory loadBalancerClientFactory) {
LoadBalancerClientFactory loadBalancerClientFactory,
List<LoadBalancerFeignRequestTransformer> transformers) {
Client delegate = new ApacheHttp5Client(httpClient5);
return new FeignBlockingLoadBalancerClient(delegate, loadBalancerClient, loadBalancerClientFactory);
return new FeignBlockingLoadBalancerClient(delegate, loadBalancerClient, loadBalancerClientFactory,
transformers);
}
@Bean
@@ -65,10 +70,11 @@ class HttpClient5FeignLoadBalancerConfiguration {
@ConditionalOnProperty(value = "spring.cloud.loadbalancer.retry.enabled", havingValue = "true",
matchIfMissing = true)
public Client feignRetryClient(LoadBalancerClient loadBalancerClient, HttpClient httpClient5,
LoadBalancedRetryFactory loadBalancedRetryFactory, LoadBalancerClientFactory loadBalancerClientFactory) {
LoadBalancedRetryFactory loadBalancedRetryFactory, LoadBalancerClientFactory loadBalancerClientFactory,
List<LoadBalancerFeignRequestTransformer> transformers) {
Client delegate = new ApacheHttp5Client(httpClient5);
return new RetryableFeignBlockingLoadBalancerClient(delegate, loadBalancerClient, loadBalancedRetryFactory,
loadBalancerClientFactory);
loadBalancerClientFactory, transformers);
}
}
@@ -16,6 +16,8 @@
package org.springframework.cloud.openfeign.loadbalancer;
import java.util.List;
import feign.Client;
import feign.httpclient.ApacheHttpClient;
import org.apache.http.client.HttpClient;
@@ -42,6 +44,7 @@ import org.springframework.context.annotation.Import;
*
* @author Olga Maciaszek-Sharma
* @author Nguyen Ky Thanh
* @author changjin wei(魏昌进)
* @since 2.2.0
*/
@Configuration(proxyBeanMethods = false)
@@ -57,9 +60,11 @@ class HttpClientFeignLoadBalancerConfiguration {
@ConditionalOnMissingBean
@Conditional(OnRetryNotEnabledCondition.class)
public Client feignClient(LoadBalancerClient loadBalancerClient, HttpClient httpClient,
LoadBalancerClientFactory loadBalancerClientFactory) {
LoadBalancerClientFactory loadBalancerClientFactory,
List<LoadBalancerFeignRequestTransformer> transformers) {
ApacheHttpClient delegate = new ApacheHttpClient(httpClient);
return new FeignBlockingLoadBalancerClient(delegate, loadBalancerClient, loadBalancerClientFactory);
return new FeignBlockingLoadBalancerClient(delegate, loadBalancerClient, loadBalancerClientFactory,
transformers);
}
@Bean
@@ -69,10 +74,11 @@ class HttpClientFeignLoadBalancerConfiguration {
@ConditionalOnProperty(value = "spring.cloud.loadbalancer.retry.enabled", havingValue = "true",
matchIfMissing = true)
public Client feignRetryClient(LoadBalancerClient loadBalancerClient, HttpClient httpClient,
LoadBalancedRetryFactory loadBalancedRetryFactory, LoadBalancerClientFactory loadBalancerClientFactory) {
LoadBalancedRetryFactory loadBalancedRetryFactory, LoadBalancerClientFactory loadBalancerClientFactory,
List<LoadBalancerFeignRequestTransformer> transformers) {
ApacheHttpClient delegate = new ApacheHttpClient(httpClient);
return new RetryableFeignBlockingLoadBalancerClient(delegate, loadBalancerClient, loadBalancedRetryFactory,
loadBalancerClientFactory);
loadBalancerClientFactory, transformers);
}
}
@@ -0,0 +1,47 @@
/*
* Copyright 2013-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.openfeign.loadbalancer;
import feign.Request;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.core.annotation.Order;
/**
* Allows applications to transform the load-balanced {@link Request} given the chosen
* {@link org.springframework.cloud.client.ServiceInstance}.
*
* @author changjin wei(魏昌进)
*/
@Order(LoadBalancerFeignRequestTransformer.DEFAULT_ORDER)
public interface LoadBalancerFeignRequestTransformer {
/**
* Order for the {@link LoadBalancerFeignRequestTransformer}.
*/
int DEFAULT_ORDER = 0;
/**
* Allows transforming load-balanced requests based on the provided
* {@link ServiceInstance}.
* @param request Original request.
* @param instance ServiceInstance returned from LoadBalancer.
* @return New request or original request
*/
Request transformRequest(Request request, ServiceInstance instance);
}
@@ -33,6 +33,7 @@ import org.springframework.cloud.client.loadbalancer.RequestData;
import org.springframework.cloud.client.loadbalancer.ResponseData;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatusCode;
/**
* @author Olga Maciaszek-Sharma
@@ -72,7 +73,8 @@ final class LoadBalancerUtils {
static ResponseData buildResponseData(Response response) {
HttpHeaders responseHeaders = new HttpHeaders();
response.headers().forEach((key, value) -> responseHeaders.put(key, new ArrayList<>(value)));
return new ResponseData(response.status(), responseHeaders, null, buildRequestData(response.request()));
return new ResponseData(HttpStatusCode.valueOf(response.status()), responseHeaders, null,
buildRequestData(response.request()));
}
static RequestData buildRequestData(Request request) {
@@ -16,6 +16,8 @@
package org.springframework.cloud.openfeign.loadbalancer;
import java.util.List;
import feign.Client;
import feign.okhttp.OkHttpClient;
@@ -39,6 +41,7 @@ import org.springframework.context.annotation.Import;
* that uses {@link OkHttpClient} under the hood.
*
* @author Olga Maciaszek-Sharma
* @author changjin wei(魏昌进)
* @since 2.2.0
*/
@Configuration(proxyBeanMethods = false)
@@ -53,9 +56,11 @@ class OkHttpFeignLoadBalancerConfiguration {
@ConditionalOnMissingBean
@Conditional(OnRetryNotEnabledCondition.class)
public Client feignClient(okhttp3.OkHttpClient okHttpClient, LoadBalancerClient loadBalancerClient,
LoadBalancerClientFactory loadBalancerClientFactory) {
LoadBalancerClientFactory loadBalancerClientFactory,
List<LoadBalancerFeignRequestTransformer> transformers) {
OkHttpClient delegate = new OkHttpClient(okHttpClient);
return new FeignBlockingLoadBalancerClient(delegate, loadBalancerClient, loadBalancerClientFactory);
return new FeignBlockingLoadBalancerClient(delegate, loadBalancerClient, loadBalancerClientFactory,
transformers);
}
@Bean
@@ -65,10 +70,11 @@ class OkHttpFeignLoadBalancerConfiguration {
@ConditionalOnProperty(value = "spring.cloud.loadbalancer.retry.enabled", havingValue = "true",
matchIfMissing = true)
public Client feignRetryClient(LoadBalancerClient loadBalancerClient, okhttp3.OkHttpClient okHttpClient,
LoadBalancedRetryFactory loadBalancedRetryFactory, LoadBalancerClientFactory loadBalancerClientFactory) {
LoadBalancedRetryFactory loadBalancedRetryFactory, LoadBalancerClientFactory loadBalancerClientFactory,
List<LoadBalancerFeignRequestTransformer> transformers) {
OkHttpClient delegate = new OkHttpClient(okHttpClient);
return new RetryableFeignBlockingLoadBalancerClient(delegate, loadBalancerClient, loadBalancedRetryFactory,
loadBalancerClientFactory);
loadBalancerClientFactory, transformers);
}
}
@@ -20,6 +20,7 @@ import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -65,6 +66,7 @@ import static org.springframework.cloud.openfeign.loadbalancer.LoadBalancerUtils
* load-balanced with Spring Cloud LoadBalancer.
*
* @author Olga Maciaszek-Sharma
* @author changjin wei(魏昌进)
* @since 2.2.6
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
@@ -80,9 +82,11 @@ public class RetryableFeignBlockingLoadBalancerClient implements Client {
private final LoadBalancerClientFactory loadBalancerClientFactory;
private final List<LoadBalancerFeignRequestTransformer> transformers;
/**
* @deprecated in favour of
* {@link RetryableFeignBlockingLoadBalancerClient#RetryableFeignBlockingLoadBalancerClient(Client, LoadBalancerClient, LoadBalancedRetryFactory, LoadBalancerClientFactory)}
* {@link RetryableFeignBlockingLoadBalancerClient#RetryableFeignBlockingLoadBalancerClient(Client, LoadBalancerClient, LoadBalancedRetryFactory, LoadBalancerClientFactory, List)}
*/
@Deprecated
public RetryableFeignBlockingLoadBalancerClient(Client delegate, LoadBalancerClient loadBalancerClient,
@@ -92,14 +96,31 @@ public class RetryableFeignBlockingLoadBalancerClient implements Client {
this.loadBalancerClient = loadBalancerClient;
this.loadBalancedRetryFactory = loadBalancedRetryFactory;
this.loadBalancerClientFactory = loadBalancerClientFactory;
this.transformers = Collections.emptyList();
}
/**
* @deprecated in favour of
* {@link RetryableFeignBlockingLoadBalancerClient#RetryableFeignBlockingLoadBalancerClient(Client, LoadBalancerClient, LoadBalancedRetryFactory, LoadBalancerClientFactory, List)}
*/
@Deprecated
public RetryableFeignBlockingLoadBalancerClient(Client delegate, LoadBalancerClient loadBalancerClient,
LoadBalancedRetryFactory loadBalancedRetryFactory, LoadBalancerClientFactory loadBalancerClientFactory) {
this.delegate = delegate;
this.loadBalancerClient = loadBalancerClient;
this.loadBalancedRetryFactory = loadBalancedRetryFactory;
this.loadBalancerClientFactory = loadBalancerClientFactory;
this.transformers = Collections.emptyList();
}
public RetryableFeignBlockingLoadBalancerClient(Client delegate, LoadBalancerClient loadBalancerClient,
LoadBalancedRetryFactory loadBalancedRetryFactory, LoadBalancerClientFactory loadBalancerClientFactory,
List<LoadBalancerFeignRequestTransformer> transformers) {
this.delegate = delegate;
this.loadBalancerClient = loadBalancerClient;
this.loadBalancedRetryFactory = loadBalancedRetryFactory;
this.loadBalancerClientFactory = loadBalancerClientFactory;
this.transformers = transformers;
}
@Override
@@ -158,7 +179,7 @@ public class RetryableFeignBlockingLoadBalancerClient implements Client {
}
String reconstructedUrl = loadBalancerClient.reconstructURI(retrievedServiceInstance, originalUri)
.toString();
feignRequest = buildRequest(request, reconstructedUrl);
feignRequest = buildRequest(request, reconstructedUrl, retrievedServiceInstance);
}
}
org.springframework.cloud.client.loadbalancer.Response<ServiceInstance> lbResponse = new DefaultResponse(
@@ -191,6 +212,16 @@ public class RetryableFeignBlockingLoadBalancerClient implements Client {
request.charset(), request.requestTemplate());
}
protected Request buildRequest(Request request, String reconstructedUrl, ServiceInstance instance) {
Request newRequest = buildRequest(request, reconstructedUrl);
if (transformers != null) {
for (LoadBalancerFeignRequestTransformer transformer : transformers) {
newRequest = transformer.transformRequest(newRequest, instance);
}
}
return newRequest;
}
private RetryTemplate buildRetryTemplate(String serviceId, Request request, LoadBalancedRetryPolicy retryPolicy) {
RetryTemplate retryTemplate = new RetryTemplate();
BackOffPolicy backOffPolicy = this.loadBalancedRetryFactory.createBackOffPolicy(serviceId);
@@ -247,7 +247,7 @@ public class SpringEncoder implements Encoder {
return Objects.equals(APPLICATION_FORM_URLENCODED, requestContentType);
}
private boolean binaryContentType(FeignOutputMessage outputMessage) {
protected boolean binaryContentType(FeignOutputMessage outputMessage) {
MediaType contentType = outputMessage.getHeaders().getContentType();
return contentType == null || Stream
.of(MediaType.APPLICATION_CBOR, MediaType.APPLICATION_OCTET_STREAM, MediaType.APPLICATION_PDF,
@@ -74,21 +74,21 @@ public final class Request extends com.google.protobuf.GeneratedMessageV3 implem
while (!done) {
int tag = input.readTag();
switch (tag) {
case 0:
done = true;
break;
default:
if (!parseUnknownFieldProto3(input, unknownFields, extensionRegistry, tag)) {
case 0:
done = true;
}
break;
case 8:
this.id_ = input.readInt32();
break;
case 18:
String s = input.readStringRequireUtf8();
this.msg_ = s;
break;
break;
default:
if (!parseUnknownFieldProto3(input, unknownFields, extensionRegistry, tag)) {
done = true;
}
break;
case 8:
this.id_ = input.readInt32();
break;
case 18:
String s = input.readStringRequireUtf8();
this.msg_ = s;
break;
}
}
}
@@ -21,9 +21,11 @@ import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
@@ -66,6 +68,7 @@ import static org.mockito.Mockito.when;
* {@link FeignBlockingLoadBalancerClient} and its delegates.
*
* @author Olga Maciaszek-Sharma
* @author changjin wei(魏昌进)
* @see <a href=
* "https://github.com/spring-cloud/spring-cloud-commons/blob/main/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/blocking/client/BlockingLoadBalancerClientTests.java">BlockingLoadBalancerClientTests</a>
*/
@@ -80,8 +83,11 @@ class FeignBlockingLoadBalancerClientTests {
private final LoadBalancerProperties loadBalancerProperties = new LoadBalancerProperties();
private final List<LoadBalancerFeignRequestTransformer> transformers = Arrays.asList(new InstanceIdTransformer(),
new ServiceIdTransformer());
private final FeignBlockingLoadBalancerClient feignBlockingLoadBalancerClient = new FeignBlockingLoadBalancerClient(
delegate, loadBalancerClient, loadBalancerClientFactory);
delegate, loadBalancerClient, loadBalancerClientFactory, transformers);
@BeforeEach
void setUp() {
@@ -133,9 +139,11 @@ class FeignBlockingLoadBalancerClientTests {
Request actualRequest = captor.getValue();
assertThat(actualRequest.httpMethod()).isEqualTo(Request.HttpMethod.GET);
assertThat(actualRequest.url()).isEqualTo(url);
assertThat(actualRequest.headers()).hasSize(1);
assertThat(actualRequest.headers()).hasSize(3);
assertThat(actualRequest.headers()).containsEntry(HttpHeaders.CONTENT_TYPE,
Collections.singletonList(MediaType.APPLICATION_JSON_VALUE));
assertThat(actualRequest.headers()).containsEntry("X-ServiceId", Collections.singletonList("test"));
assertThat(actualRequest.headers()).containsEntry("X-InstanceId", Collections.singletonList("test-1"));
assertThat(new String(actualRequest.body())).isEqualTo("hello");
}
@@ -171,7 +179,7 @@ class FeignBlockingLoadBalancerClientTests {
.contains(callbackTestHint);
assertThat(anotherLifecycleLogRequests)
.extracting(completionContext -> completionContext.getClientResponse().getHttpStatus())
.contains(HttpStatus.OK.value());
.contains(HttpStatus.OK);
}
private String read(Response response) throws IOException {
@@ -253,4 +261,28 @@ class FeignBlockingLoadBalancerClientTests {
}
private static class InstanceIdTransformer implements LoadBalancerFeignRequestTransformer {
@Override
public Request transformRequest(Request request, ServiceInstance instance) {
Map<String, Collection<String>> headers = new HashMap<>(request.headers());
headers.put("X-InstanceId", Collections.singletonList(instance.getInstanceId()));
return Request.create(request.httpMethod(), request.url(), headers, request.body(), request.charset(),
request.requestTemplate());
}
}
private static class ServiceIdTransformer implements LoadBalancerFeignRequestTransformer {
@Override
public Request transformRequest(Request request, ServiceInstance instance) {
Map<String, Collection<String>> headers = new HashMap<>(request.headers());
headers.put("X-ServiceId", Collections.singletonList(instance.getServiceId()));
return Request.create(request.httpMethod(), request.url(), headers, request.body(), request.charset(),
request.requestTemplate());
}
}
}
@@ -22,9 +22,11 @@ import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
@@ -70,6 +72,7 @@ import static org.mockito.Mockito.when;
* {@link RetryableFeignBlockingLoadBalancerClient} and its delegates.
*
* @author Olga Maciaszek-Sharma
* @author changjin wei(魏昌进)
* @see <a href=
* "https://github.com/spring-cloud/spring-cloud-commons/blob/main/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/blocking/client/BlockingLoadBalancerClientTests.java">BlockingLoadBalancerClientTests</a>
*/
@@ -86,8 +89,11 @@ class RetryableFeignBlockingLoadBalancerClientTests {
private final LoadBalancerProperties properties = new LoadBalancerProperties();
private final List<LoadBalancerFeignRequestTransformer> transformers = Arrays.asList(new InstanceIdTransformer(),
new ServiceIdTransformer());
private final RetryableFeignBlockingLoadBalancerClient feignBlockingLoadBalancerClient = new RetryableFeignBlockingLoadBalancerClient(
delegate, loadBalancerClient, retryFactory, properties, loadBalancerClientFactory);
delegate, loadBalancerClient, retryFactory, loadBalancerClientFactory, transformers);
private final ServiceInstance serviceInstance = new DefaultServiceInstance("test-a", "test", "testhost", 80, false);
@@ -197,9 +203,11 @@ class RetryableFeignBlockingLoadBalancerClientTests {
Request actualRequest = captor.getValue();
assertThat(actualRequest.httpMethod()).isEqualTo(Request.HttpMethod.GET);
assertThat(actualRequest.url()).isEqualTo(url);
assertThat(actualRequest.headers()).hasSize(1);
assertThat(actualRequest.headers()).hasSize(3);
assertThat(actualRequest.headers()).containsEntry(HttpHeaders.CONTENT_TYPE,
Collections.singletonList(MediaType.APPLICATION_JSON_VALUE));
assertThat(actualRequest.headers()).containsEntry("X-ServiceId", Collections.singletonList("test"));
assertThat(actualRequest.headers()).containsEntry("X-InstanceId", Collections.singletonList("test-1"));
assertThat(new String(actualRequest.body())).isEqualTo("hello");
}
@@ -236,7 +244,7 @@ class RetryableFeignBlockingLoadBalancerClientTests {
.contains(callbackTestHint);
assertThat(anotherLifecycleLogRequests)
.extracting(completionContext -> completionContext.getClientResponse().getHttpStatus())
.contains(HttpStatus.OK.value());
.contains(HttpStatus.OK);
}
private Request testRequest() {
@@ -310,4 +318,28 @@ class RetryableFeignBlockingLoadBalancerClientTests {
}
private static class InstanceIdTransformer implements LoadBalancerFeignRequestTransformer {
@Override
public Request transformRequest(Request request, ServiceInstance instance) {
Map<String, Collection<String>> headers = new HashMap<>(request.headers());
headers.put("X-InstanceId", Collections.singletonList(instance.getInstanceId()));
return Request.create(request.httpMethod(), request.url(), headers, request.body(), request.charset(),
request.requestTemplate());
}
}
private static class ServiceIdTransformer implements LoadBalancerFeignRequestTransformer {
@Override
public Request transformRequest(Request request, ServiceInstance instance) {
Map<String, Collection<String>> headers = new HashMap<>(request.headers());
headers.put("X-ServiceId", Collections.singletonList(instance.getServiceId()));
return Request.create(request.httpMethod(), request.url(), headers, request.body(), request.charset(),
request.requestTemplate());
}
}
}
+2 -2
View File
@@ -6,11 +6,11 @@
<parent>
<artifactId>spring-cloud-dependencies-parent</artifactId>
<groupId>org.springframework.cloud</groupId>
<version>4.0.0-M4</version>
<version>4.0.0-SNAPSHOT</version>
<relativePath/>
</parent>
<artifactId>spring-cloud-openfeign-dependencies</artifactId>
<version>4.0.0-M4</version>
<version>4.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>spring-cloud-openfeign-dependencies</name>
<description>Spring Cloud OpenFeign Dependencies</description>
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-openfeign</artifactId>
<version>4.0.0-M4</version>
<version>4.0.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>spring-cloud-starter-openfeign</artifactId>