4 changed files with 180 additions and 0 deletions
@ -0,0 +1,63 @@
@@ -0,0 +1,63 @@
|
||||
/* |
||||
* 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 java.net.URI; |
||||
import java.util.Collection; |
||||
import java.util.Collections; |
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
import feign.Request; |
||||
|
||||
import org.springframework.cloud.client.ServiceInstance; |
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerProperties; |
||||
import org.springframework.cloud.client.loadbalancer.reactive.ReactiveLoadBalancer; |
||||
|
||||
/** |
||||
* To add X-Forwarded-Host and X-Forwarded-Proto Headers. |
||||
* |
||||
* @author changjin wei(魏昌进) |
||||
*/ |
||||
public class XForwardedHeadersTransformer implements LoadBalancerFeignRequestTransformer { |
||||
|
||||
private final ReactiveLoadBalancer.Factory<ServiceInstance> factory; |
||||
|
||||
public XForwardedHeadersTransformer(ReactiveLoadBalancer.Factory<ServiceInstance> factory) { |
||||
this.factory = factory; |
||||
} |
||||
|
||||
@Override |
||||
public Request transformRequest(Request request, ServiceInstance instance) { |
||||
if (instance == null) { |
||||
return request; |
||||
} |
||||
LoadBalancerProperties.XForwarded xForwarded = factory.getProperties(instance.getServiceId()).getXForwarded(); |
||||
if (xForwarded.isEnabled()) { |
||||
Map<String, Collection<String>> headers = new HashMap<>(request.headers()); |
||||
URI uri = URI.create(request.url()); |
||||
String xForwardedHost = uri.getHost(); |
||||
String xForwardedProto = uri.getScheme(); |
||||
headers.put("X-Forwarded-Host", Collections.singleton(xForwardedHost)); |
||||
headers.put("X-Forwarded-Proto", Collections.singleton(xForwardedProto)); |
||||
request = Request.create(request.httpMethod(), request.url(), headers, request.body(), request.charset(), |
||||
request.requestTemplate()); |
||||
} |
||||
return request; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,98 @@
@@ -0,0 +1,98 @@
|
||||
/* |
||||
* 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 java.nio.charset.StandardCharsets; |
||||
import java.util.Collection; |
||||
import java.util.Collections; |
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
import feign.Request; |
||||
import org.junit.jupiter.api.Test; |
||||
|
||||
import org.springframework.cloud.client.DefaultServiceInstance; |
||||
import org.springframework.cloud.client.ServiceInstance; |
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerProperties; |
||||
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory; |
||||
import org.springframework.http.HttpHeaders; |
||||
import org.springframework.http.MediaType; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
import static org.mockito.Mockito.mock; |
||||
import static org.mockito.Mockito.when; |
||||
|
||||
/** |
||||
* Tests for |
||||
* {@link XForwardedHeadersTransformer}. |
||||
* |
||||
* @author changjin wei(魏昌进) |
||||
*/ |
||||
class XForwardedHeadersTransformerTests { |
||||
|
||||
private final LoadBalancerClientFactory loadBalancerClientFactory = mock(LoadBalancerClientFactory.class); |
||||
|
||||
private final LoadBalancerProperties loadBalancerProperties = new LoadBalancerProperties(); |
||||
|
||||
private final ServiceInstance serviceInstance = new DefaultServiceInstance("test1", "test", "test.org", 8080, |
||||
false); |
||||
|
||||
private final Request request = testRequest(); |
||||
|
||||
private Request testRequest() { |
||||
return testRequest("spring.io"); |
||||
} |
||||
|
||||
private Request testRequest(String host) { |
||||
return Request.create(Request.HttpMethod.GET, "https://" + host + "/path", testHeaders(), "hello".getBytes(), |
||||
StandardCharsets.UTF_8, null); |
||||
} |
||||
|
||||
private Map<String, Collection<String>> testHeaders() { |
||||
Map<String, Collection<String>> feignHeaders = new HashMap<>(); |
||||
feignHeaders.put(HttpHeaders.CONTENT_TYPE, Collections.singletonList(MediaType.APPLICATION_JSON_VALUE)); |
||||
return feignHeaders; |
||||
|
||||
} |
||||
|
||||
@Test |
||||
void shouldAppendXForwardedHeadersIfEnabled() { |
||||
loadBalancerProperties.getXForwarded().setEnabled(true); |
||||
when(loadBalancerClientFactory.getProperties("test")).thenReturn(loadBalancerProperties); |
||||
XForwardedHeadersTransformer transformer = new XForwardedHeadersTransformer(loadBalancerClientFactory); |
||||
|
||||
Request newRequest = transformer.transformRequest(request, serviceInstance); |
||||
|
||||
assertThat(newRequest.headers()).containsKey("X-Forwarded-Host"); |
||||
assertThat(newRequest.headers()).containsEntry("X-Forwarded-Host", Collections.singleton("spring.io")); |
||||
assertThat(newRequest.headers()).containsKey("X-Forwarded-Proto"); |
||||
assertThat(newRequest.headers()).containsEntry("X-Forwarded-Proto", Collections.singleton("https")); |
||||
|
||||
} |
||||
|
||||
@Test |
||||
void shouldNotAppendXForwardedHeadersIfDefault() { |
||||
when(loadBalancerClientFactory.getProperties("test")).thenReturn(loadBalancerProperties); |
||||
XForwardedHeadersTransformer transformer = new XForwardedHeadersTransformer(loadBalancerClientFactory); |
||||
|
||||
Request newRequest = transformer.transformRequest(request, serviceInstance); |
||||
|
||||
assertThat(newRequest.headers()).doesNotContainKey("X-Forwarded-Host"); |
||||
assertThat(newRequest.headers()).doesNotContainKey("X-Forwarded-Proto"); |
||||
} |
||||
|
||||
} |
Loading…
Reference in new issue