diff --git a/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancerAutoConfiguration.java b/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancerAutoConfiguration.java new file mode 100644 index 00000000..157b9605 --- /dev/null +++ b/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancerAutoConfiguration.java @@ -0,0 +1,56 @@ +/* + * Copyright 2013-2015 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 + * + * http://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.ArrayList; +import java.util.List; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.ClientHttpRequestInterceptor; +import org.springframework.web.client.RestTemplate; + +/** + * Auto configuration for Ribbon (client side load balancing). + * + * @author Spencer Gibb + * @author Dave Syer + */ +@Configuration +@ConditionalOnClass(RestTemplate.class) +@ConditionalOnBean(LoadBalancerClient.class) +public class LoadBalancerAutoConfiguration { + + @Bean + @ConditionalOnMissingBean(RestTemplate.class) + public RestTemplate restTemplate(LoadBalancerInterceptor loadBalancerInterceptor) { + RestTemplate restTemplate = new RestTemplate(); + List list = new ArrayList<>(); + list.add(loadBalancerInterceptor); + restTemplate.setInterceptors(list); + return restTemplate; + } + + @Bean + public LoadBalancerInterceptor ribbonInterceptor(LoadBalancerClient loadBalancerClient) { + return new LoadBalancerInterceptor(loadBalancerClient); + } + +} diff --git a/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancerInterceptor.java b/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancerInterceptor.java new file mode 100644 index 00000000..5f1877b1 --- /dev/null +++ b/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancerInterceptor.java @@ -0,0 +1,78 @@ +/* + * Copyright 2013-2015 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 + * + * http://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.io.IOException; +import java.net.URI; + +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.http.HttpRequest; +import org.springframework.http.client.ClientHttpRequestExecution; +import org.springframework.http.client.ClientHttpRequestInterceptor; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.http.client.support.HttpRequestWrapper; + +/** + * @author Spencer Gibb + * @author Dave Syer + */ +public class LoadBalancerInterceptor implements ClientHttpRequestInterceptor { + + private LoadBalancerClient loadBalancer; + + public LoadBalancerInterceptor(LoadBalancerClient loadBalancer) { + this.loadBalancer = loadBalancer; + } + + @Override + public ClientHttpResponse intercept(final HttpRequest request, final byte[] body, + final ClientHttpRequestExecution execution) throws IOException { + final URI originalUri = request.getURI(); + String serviceName = originalUri.getHost(); + return this.loadBalancer.execute(serviceName, + new LoadBalancerRequest() { + + @Override + public ClientHttpResponse apply(final ServiceInstance instance) + throws Exception { + HttpRequest serviceRequest = new ServiceRequestWrapper(request, + instance); + return execution.execute(serviceRequest, body); + } + + }); + } + + private class ServiceRequestWrapper extends HttpRequestWrapper { + + private final ServiceInstance instance; + + public ServiceRequestWrapper(HttpRequest request, ServiceInstance instance) { + super(request); + this.instance = instance; + } + + @Override + public URI getURI() { + URI uri = LoadBalancerInterceptor.this.loadBalancer.reconstructURI( + this.instance, getRequest().getURI()); + return uri; + } + + } + +} diff --git a/src/main/resources/META-INF/spring.factories b/src/main/resources/META-INF/spring.factories index 9d369afe..0345563f 100644 --- a/src/main/resources/META-INF/spring.factories +++ b/src/main/resources/META-INF/spring.factories @@ -1,4 +1,5 @@ # AutoConfiguration org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.cloud.client.CommonsClientAutoConfiguration,\ -org.springframework.cloud.client.discovery.noop.NoopDiscoveryClientAutoConfiguration +org.springframework.cloud.client.discovery.noop.NoopDiscoveryClientAutoConfiguration,\ +org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration