Browse Source
Co-authored-by: Ryan Baxter <524254+ryanjbaxter@users.noreply.github.com>pull/792/head
10 changed files with 12 additions and 248 deletions
@ -1,77 +0,0 @@
@@ -1,77 +0,0 @@
|
||||
/* |
||||
* 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.clientconfig; |
||||
|
||||
import java.time.Duration; |
||||
import java.util.concurrent.TimeUnit; |
||||
|
||||
import jakarta.annotation.PreDestroy; |
||||
import okhttp3.ConnectionPool; |
||||
import okhttp3.OkHttpClient; |
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; |
||||
import org.springframework.cloud.commons.httpclient.OkHttpClientConnectionPoolFactory; |
||||
import org.springframework.cloud.commons.httpclient.OkHttpClientFactory; |
||||
import org.springframework.cloud.openfeign.support.FeignHttpClientProperties; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
|
||||
/** |
||||
* Defualt configuration for {@link OkHttpClient}. |
||||
* |
||||
* @author Ryan Baxter |
||||
* @author Marcin Grzejszczak |
||||
* @author Spencer Gibb |
||||
* @author Olga Maciaszek-Sharma |
||||
*/ |
||||
@Configuration(proxyBeanMethods = false) |
||||
@ConditionalOnMissingBean(okhttp3.OkHttpClient.class) |
||||
public class OkHttpFeignConfiguration { |
||||
|
||||
private okhttp3.OkHttpClient okHttpClient; |
||||
|
||||
@Bean |
||||
@ConditionalOnMissingBean(ConnectionPool.class) |
||||
public ConnectionPool httpClientConnectionPool(FeignHttpClientProperties httpClientProperties, |
||||
OkHttpClientConnectionPoolFactory connectionPoolFactory) { |
||||
int maxTotalConnections = httpClientProperties.getMaxConnections(); |
||||
long timeToLive = httpClientProperties.getTimeToLive(); |
||||
TimeUnit ttlUnit = httpClientProperties.getTimeToLiveUnit(); |
||||
return connectionPoolFactory.create(maxTotalConnections, timeToLive, ttlUnit); |
||||
} |
||||
|
||||
@Bean |
||||
public okhttp3.OkHttpClient client(OkHttpClientFactory httpClientFactory, ConnectionPool connectionPool, |
||||
FeignHttpClientProperties httpClientProperties) { |
||||
boolean followRedirects = httpClientProperties.isFollowRedirects(); |
||||
int connectTimeout = httpClientProperties.getConnectionTimeout(); |
||||
Duration reaTimeout = httpClientProperties.getOkHttp().getReadTimeout(); |
||||
this.okHttpClient = httpClientFactory.createBuilder(httpClientProperties.isDisableSslValidation()) |
||||
.connectTimeout(connectTimeout, TimeUnit.MILLISECONDS).followRedirects(followRedirects) |
||||
.readTimeout(reaTimeout).connectionPool(connectionPool).build(); |
||||
return this.okHttpClient; |
||||
} |
||||
|
||||
@PreDestroy |
||||
public void destroy() { |
||||
if (this.okHttpClient != null) { |
||||
this.okHttpClient.dispatcher().executorService().shutdown(); |
||||
this.okHttpClient.connectionPool().evictAll(); |
||||
} |
||||
} |
||||
|
||||
} |
@ -1,103 +0,0 @@
@@ -1,103 +0,0 @@
|
||||
/* |
||||
* 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; |
||||
|
||||
import java.lang.reflect.Field; |
||||
|
||||
import javax.net.ssl.SSLContextSpi; |
||||
import javax.net.ssl.SSLSocketFactory; |
||||
import javax.net.ssl.X509TrustManager; |
||||
|
||||
import org.apache.http.config.Lookup; |
||||
import org.apache.http.conn.HttpClientConnectionManager; |
||||
import org.apache.http.conn.socket.ConnectionSocketFactory; |
||||
import org.apache.http.impl.conn.DefaultHttpClientConnectionOperator; |
||||
import org.junit.jupiter.api.AfterEach; |
||||
import org.junit.jupiter.api.BeforeEach; |
||||
import org.junit.jupiter.api.Disabled; |
||||
import org.junit.jupiter.api.Test; |
||||
|
||||
import org.springframework.boot.WebApplicationType; |
||||
import org.springframework.boot.builder.SpringApplicationBuilder; |
||||
import org.springframework.cloud.commons.httpclient.HttpClientConfiguration; |
||||
import org.springframework.context.ConfigurableApplicationContext; |
||||
import org.springframework.util.ReflectionUtils; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
|
||||
/** |
||||
* @author Ryan Baxter |
||||
*/ |
||||
// TODO: Bring back when there's corresponding HttpClient 5 support in Commons
|
||||
@Disabled |
||||
class FeignHttpClientConfigurationTests { |
||||
|
||||
private ConfigurableApplicationContext context; |
||||
|
||||
@BeforeEach |
||||
void setUp() { |
||||
this.context = new SpringApplicationBuilder() |
||||
.properties("debug=true", "spring.cloud.openfeign.httpclient.disableSslValidation=true") |
||||
.web(WebApplicationType.NONE).sources(HttpClientConfiguration.class, FeignAutoConfiguration.class) |
||||
.run(); |
||||
} |
||||
|
||||
@AfterEach |
||||
void tearDown() { |
||||
if (this.context != null) { |
||||
this.context.close(); |
||||
} |
||||
} |
||||
|
||||
@Test |
||||
void disableSslTest() { |
||||
try { |
||||
HttpClientConnectionManager connectionManager = this.context.getBean(HttpClientConnectionManager.class); |
||||
Lookup<ConnectionSocketFactory> socketFactoryRegistry = getConnectionSocketFactoryLookup(connectionManager); |
||||
assertThat(socketFactoryRegistry.lookup("https")).isNotNull(); |
||||
assertThat(this.getX509TrustManager(socketFactoryRegistry).getAcceptedIssuers()).isNull(); |
||||
} |
||||
catch (RuntimeException e) { |
||||
// FIXME: java 16 need junit 5 compatible modified classpath extension
|
||||
if (e.getMessage() == null || !e.getMessage().startsWith("Unable to make field private final")) { |
||||
ReflectionUtils.rethrowRuntimeException(e); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@SuppressWarnings("unchecked") |
||||
private Lookup<ConnectionSocketFactory> getConnectionSocketFactoryLookup( |
||||
HttpClientConnectionManager connectionManager) { |
||||
DefaultHttpClientConnectionOperator connectionOperator = (DefaultHttpClientConnectionOperator) this |
||||
.getField(connectionManager, "connectionOperator"); |
||||
return (Lookup) this.getField(connectionOperator, "socketFactoryRegistry"); |
||||
} |
||||
|
||||
private X509TrustManager getX509TrustManager(Lookup<ConnectionSocketFactory> socketFactoryRegistry) { |
||||
ConnectionSocketFactory connectionSocketFactory = socketFactoryRegistry.lookup("https"); |
||||
SSLSocketFactory sslSocketFactory = (SSLSocketFactory) this.getField(connectionSocketFactory, "socketfactory"); |
||||
SSLContextSpi sslContext = (SSLContextSpi) this.getField(sslSocketFactory, "context"); |
||||
return (X509TrustManager) this.getField(sslContext, "trustManager"); |
||||
} |
||||
|
||||
protected <T> Object getField(Object target, String name) { |
||||
Field field = ReflectionUtils.findField(target.getClass(), name); |
||||
ReflectionUtils.makeAccessible(field); |
||||
return ReflectionUtils.getField(field, target); |
||||
} |
||||
|
||||
} |
Loading…
Reference in new issue