diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/BlockingLoadBalancerRequest.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/BlockingLoadBalancerRequest.java new file mode 100644 index 00000000..d51e247f --- /dev/null +++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/BlockingLoadBalancerRequest.java @@ -0,0 +1,79 @@ +/* + * Copyright 2012-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.client.loadbalancer; + +import java.util.List; + +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.http.HttpRequest; +import org.springframework.http.client.ClientHttpRequestExecution; +import org.springframework.http.client.ClientHttpResponse; + +/** + * Default {@link LoadBalancerRequest} implementation. + * + * @author Olga Maciaszek-Sharma + * @since 3.1.2 + */ +class BlockingLoadBalancerRequest implements HttpRequestLoadBalancerRequest { + + private final LoadBalancerClient loadBalancer; + + private final List transformers; + + private final ClientHttpRequestData clientHttpRequestData; + + BlockingLoadBalancerRequest(LoadBalancerClient loadBalancer, List transformers, + ClientHttpRequestData clientHttpRequestData) { + this.loadBalancer = loadBalancer; + this.transformers = transformers; + this.clientHttpRequestData = clientHttpRequestData; + } + + @Override + public ClientHttpResponse apply(ServiceInstance instance) throws Exception { + HttpRequest serviceRequest = new ServiceRequestWrapper(clientHttpRequestData.request, instance, loadBalancer); + if (this.transformers != null) { + for (LoadBalancerRequestTransformer transformer : this.transformers) { + serviceRequest = transformer.transformRequest(serviceRequest, instance); + } + } + return clientHttpRequestData.execution.execute(serviceRequest, clientHttpRequestData.body); + } + + @Override + public HttpRequest getHttpRequest() { + return clientHttpRequestData.request; + } + + static class ClientHttpRequestData { + + private final HttpRequest request; + + private final byte[] body; + + private final ClientHttpRequestExecution execution; + + ClientHttpRequestData(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) { + this.request = request; + this.body = body; + this.execution = execution; + } + + } + +} diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/HttpRequestLoadBalancerRequest.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/HttpRequestLoadBalancerRequest.java new file mode 100644 index 00000000..9c4ae023 --- /dev/null +++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/HttpRequestLoadBalancerRequest.java @@ -0,0 +1,31 @@ +/* + * Copyright 2012-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.client.loadbalancer; + +import org.springframework.http.HttpRequest; + +/** + * Represents a {@link LoadBalancerRequest} created on top of an {@link HttpRequest}. + * + * @author Olga Maciaszek-Sharma + * @since 3.1.2 + */ +public interface HttpRequestLoadBalancerRequest extends LoadBalancerRequest { + + HttpRequest getHttpRequest(); + +} diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancerRequestFactory.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancerRequestFactory.java index 2e45bd63..b8a06fbb 100644 --- a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancerRequestFactory.java +++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancerRequestFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-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. @@ -16,6 +16,7 @@ package org.springframework.cloud.client.loadbalancer; +import java.util.ArrayList; import java.util.List; import org.springframework.http.HttpRequest; @@ -28,13 +29,14 @@ import org.springframework.http.client.ClientHttpResponse; * to the intercepted {@link HttpRequest}. * * @author William Tran + * @author Olga Maciaszek-Sharma * */ public class LoadBalancerRequestFactory { - private LoadBalancerClient loadBalancer; + private final LoadBalancerClient loadBalancer; - private List transformers; + private final List transformers; public LoadBalancerRequestFactory(LoadBalancerClient loadBalancer, List transformers) { @@ -44,19 +46,13 @@ public class LoadBalancerRequestFactory { public LoadBalancerRequestFactory(LoadBalancerClient loadBalancer) { this.loadBalancer = loadBalancer; + transformers = new ArrayList<>(); } public LoadBalancerRequest createRequest(final HttpRequest request, final byte[] body, final ClientHttpRequestExecution execution) { - return instance -> { - HttpRequest serviceRequest = new ServiceRequestWrapper(request, instance, this.loadBalancer); - if (this.transformers != null) { - for (LoadBalancerRequestTransformer transformer : this.transformers) { - serviceRequest = transformer.transformRequest(serviceRequest, instance); - } - } - return execution.execute(serviceRequest, body); - }; + return new BlockingLoadBalancerRequest(loadBalancer, transformers, + new BlockingLoadBalancerRequest.ClientHttpRequestData(request, body, execution)); } } diff --git a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/blocking/client/BlockingLoadBalancerClient.java b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/blocking/client/BlockingLoadBalancerClient.java index 47c1bacc..dc7567a7 100644 --- a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/blocking/client/BlockingLoadBalancerClient.java +++ b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/blocking/client/BlockingLoadBalancerClient.java @@ -28,6 +28,7 @@ import org.springframework.cloud.client.loadbalancer.DefaultRequest; import org.springframework.cloud.client.loadbalancer.DefaultRequestContext; import org.springframework.cloud.client.loadbalancer.DefaultResponse; import org.springframework.cloud.client.loadbalancer.EmptyResponse; +import org.springframework.cloud.client.loadbalancer.HttpRequestLoadBalancerRequest; import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; import org.springframework.cloud.client.loadbalancer.LoadBalancerLifecycle; import org.springframework.cloud.client.loadbalancer.LoadBalancerLifecycleValidator; @@ -36,10 +37,14 @@ import org.springframework.cloud.client.loadbalancer.LoadBalancerRequest; import org.springframework.cloud.client.loadbalancer.LoadBalancerRequestAdapter; import org.springframework.cloud.client.loadbalancer.LoadBalancerUriTools; import org.springframework.cloud.client.loadbalancer.Request; +import org.springframework.cloud.client.loadbalancer.RequestData; +import org.springframework.cloud.client.loadbalancer.RequestDataContext; import org.springframework.cloud.client.loadbalancer.Response; import org.springframework.cloud.client.loadbalancer.ResponseData; +import org.springframework.cloud.client.loadbalancer.TimedRequestContext; import org.springframework.cloud.client.loadbalancer.reactive.ReactiveLoadBalancer; import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory; +import org.springframework.http.HttpRequest; import org.springframework.http.client.ClientHttpResponse; import org.springframework.util.ReflectionUtils; @@ -73,8 +78,8 @@ public class BlockingLoadBalancerClient implements LoadBalancerClient { @Override public T execute(String serviceId, LoadBalancerRequest request) throws IOException { String hint = getHint(serviceId); - LoadBalancerRequestAdapter lbRequest = new LoadBalancerRequestAdapter<>(request, - new DefaultRequestContext(request, hint)); + LoadBalancerRequestAdapter lbRequest = new LoadBalancerRequestAdapter<>(request, + buildRequestContext(request, hint)); Set supportedLifecycleProcessors = getSupportedLifecycleProcessors(serviceId); supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onStart(lbRequest)); ServiceInstance serviceInstance = choose(serviceId, lbRequest); @@ -86,6 +91,17 @@ public class BlockingLoadBalancerClient implements LoadBalancerClient { return execute(serviceId, serviceInstance, lbRequest); } + private TimedRequestContext buildRequestContext(LoadBalancerRequest delegate, String hint) { + if (delegate instanceof HttpRequestLoadBalancerRequest) { + HttpRequest request = ((HttpRequestLoadBalancerRequest) delegate).getHttpRequest(); + if (request != null) { + RequestData requestData = new RequestData(request); + return new RequestDataContext(requestData, hint); + } + } + return new DefaultRequestContext(delegate, hint); + } + @Override public T execute(String serviceId, ServiceInstance serviceInstance, LoadBalancerRequest request) throws IOException {