mirror of
https://github.com/apache/httpcomponents-client.git
synced 2025-02-18 16:07:11 +00:00
HTTPCLIENT-1778: [OSGi] simplify handling of ManagedService based configurations
- simplify TrustedHostsConfiguration handling git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@1763263 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
e9f8c5b315
commit
71d0567376
@ -31,13 +31,11 @@
|
|||||||
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
|
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
|
||||||
import org.apache.hc.client5.http.impl.sync.HttpClientBuilder;
|
import org.apache.hc.client5.http.impl.sync.HttpClientBuilder;
|
||||||
import org.apache.hc.client5.http.osgi.services.ProxyConfiguration;
|
import org.apache.hc.client5.http.osgi.services.ProxyConfiguration;
|
||||||
|
import org.apache.hc.client5.http.osgi.services.TrustedHostsConfiguration;
|
||||||
import org.apache.hc.client5.http.socket.ConnectionSocketFactory;
|
import org.apache.hc.client5.http.socket.ConnectionSocketFactory;
|
||||||
import org.apache.hc.client5.http.socket.PlainConnectionSocketFactory;
|
import org.apache.hc.client5.http.socket.PlainConnectionSocketFactory;
|
||||||
import org.apache.hc.core5.http.config.Registry;
|
import org.apache.hc.core5.http.config.Registry;
|
||||||
import org.apache.hc.core5.http.config.RegistryBuilder;
|
import org.apache.hc.core5.http.config.RegistryBuilder;
|
||||||
import org.osgi.framework.BundleContext;
|
|
||||||
import org.osgi.framework.ServiceRegistration;
|
|
||||||
import org.osgi.service.cm.ManagedService;
|
|
||||||
|
|
||||||
import static org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory.getSocketFactory;
|
import static org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory.getSocketFactory;
|
||||||
|
|
||||||
@ -50,12 +48,11 @@ final class HttpClientBuilderConfigurator {
|
|||||||
private final Registry<ConnectionSocketFactory> socketFactoryRegistry;
|
private final Registry<ConnectionSocketFactory> socketFactoryRegistry;
|
||||||
|
|
||||||
HttpClientBuilderConfigurator(
|
HttpClientBuilderConfigurator(
|
||||||
final BundleContext bundleContext,
|
|
||||||
final List<ProxyConfiguration> proxyConfigurations,
|
final List<ProxyConfiguration> proxyConfigurations,
|
||||||
final ServiceRegistration<ManagedService> trustedHostsConfiguration) {
|
final TrustedHostsConfiguration trustedHostsConfiguration) {
|
||||||
credentialsProvider = new OSGiCredentialsProvider(proxyConfigurations);
|
credentialsProvider = new OSGiCredentialsProvider(proxyConfigurations);
|
||||||
routePlanner = new OSGiHttpRoutePlanner(proxyConfigurations);
|
routePlanner = new OSGiHttpRoutePlanner(proxyConfigurations);
|
||||||
socketFactoryRegistry = createSocketFactoryRegistry(bundleContext, trustedHostsConfiguration);
|
socketFactoryRegistry = createSocketFactoryRegistry(trustedHostsConfiguration);
|
||||||
}
|
}
|
||||||
|
|
||||||
<T extends HttpClientBuilder> T configure(final T clientBuilder) {
|
<T extends HttpClientBuilder> T configure(final T clientBuilder) {
|
||||||
@ -67,17 +64,15 @@ <T extends HttpClientBuilder> T configure(final T clientBuilder) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Registry<ConnectionSocketFactory> createSocketFactoryRegistry(
|
private Registry<ConnectionSocketFactory> createSocketFactoryRegistry(
|
||||||
final BundleContext bundleContext,
|
final TrustedHostsConfiguration trustedHostsConfiguration) {
|
||||||
final ServiceRegistration<ManagedService> trustedHostsConfiguration) {
|
|
||||||
return RegistryBuilder.<ConnectionSocketFactory>create()
|
return RegistryBuilder.<ConnectionSocketFactory>create()
|
||||||
.register("http", PlainConnectionSocketFactory.INSTANCE)
|
.register("http", PlainConnectionSocketFactory.INSTANCE)
|
||||||
.register("https", createSocketFactory(bundleContext, trustedHostsConfiguration))
|
.register("https", createSocketFactory(trustedHostsConfiguration))
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private ConnectionSocketFactory createSocketFactory(
|
private ConnectionSocketFactory createSocketFactory(
|
||||||
final BundleContext bundleContext,
|
final TrustedHostsConfiguration trustedHostsConfiguration) {
|
||||||
final ServiceRegistration<ManagedService> trustedHostsConfiguration) {
|
return new RelaxedLayeredConnectionSocketFactory(trustedHostsConfiguration, getSocketFactory());
|
||||||
return new RelaxedLayeredConnectionSocketFactory(bundleContext, trustedHostsConfiguration, getSocketFactory());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -108,12 +108,11 @@ public void start(final BundleContext context) throws Exception {
|
|||||||
props.put(Constants.SERVICE_PID, TRUSTED_HOSTS_PID);
|
props.put(Constants.SERVICE_PID, TRUSTED_HOSTS_PID);
|
||||||
props.put(Constants.SERVICE_VENDOR, context.getBundle().getHeaders().get(Constants.BUNDLE_VENDOR));
|
props.put(Constants.SERVICE_VENDOR, context.getBundle().getHeaders().get(Constants.BUNDLE_VENDOR));
|
||||||
props.put(Constants.SERVICE_DESCRIPTION, TRUSTED_HOSTS_SERVICE_NAME);
|
props.put(Constants.SERVICE_DESCRIPTION, TRUSTED_HOSTS_SERVICE_NAME);
|
||||||
trustedHostConfiguration = context.registerService(ManagedService.class,
|
final OSGiTrustedHostsConfiguration trustedHosts = new OSGiTrustedHostsConfiguration();
|
||||||
new OSGiTrustedHostsConfiguration(),
|
trustedHostConfiguration = context.registerService(ManagedService.class, trustedHosts, props);
|
||||||
props);
|
|
||||||
|
|
||||||
final HttpClientBuilderConfigurator configurator =
|
final HttpClientBuilderConfigurator configurator =
|
||||||
new HttpClientBuilderConfigurator(context, proxyConfigurations, trustedHostConfiguration);
|
new HttpClientBuilderConfigurator(proxyConfigurations, trustedHosts);
|
||||||
|
|
||||||
props.clear();
|
props.clear();
|
||||||
props.put(Constants.SERVICE_PID, BUILDER_FACTORY_SERVICE_PID);
|
props.put(Constants.SERVICE_PID, BUILDER_FACTORY_SERVICE_PID);
|
||||||
|
@ -36,23 +36,16 @@
|
|||||||
import org.apache.hc.client5.http.socket.LayeredConnectionSocketFactory;
|
import org.apache.hc.client5.http.socket.LayeredConnectionSocketFactory;
|
||||||
import org.apache.hc.core5.http.HttpHost;
|
import org.apache.hc.core5.http.HttpHost;
|
||||||
import org.apache.hc.core5.http.protocol.HttpContext;
|
import org.apache.hc.core5.http.protocol.HttpContext;
|
||||||
import org.osgi.framework.BundleContext;
|
|
||||||
import org.osgi.framework.ServiceRegistration;
|
|
||||||
import org.osgi.service.cm.ManagedService;
|
|
||||||
|
|
||||||
final class RelaxedLayeredConnectionSocketFactory implements LayeredConnectionSocketFactory {
|
final class RelaxedLayeredConnectionSocketFactory implements LayeredConnectionSocketFactory {
|
||||||
|
|
||||||
|
private TrustedHostsConfiguration trustedHostsConfiguration;
|
||||||
|
|
||||||
private final LayeredConnectionSocketFactory defaultSocketFactory;
|
private final LayeredConnectionSocketFactory defaultSocketFactory;
|
||||||
|
|
||||||
private final BundleContext bundleContext;
|
public RelaxedLayeredConnectionSocketFactory(final TrustedHostsConfiguration trustedHostsConfiguration,
|
||||||
|
|
||||||
private final ServiceRegistration<ManagedService> trustedHostConfiguration;
|
|
||||||
|
|
||||||
public RelaxedLayeredConnectionSocketFactory(final BundleContext bundleContext,
|
|
||||||
final ServiceRegistration<ManagedService> trustedHostConfiguration,
|
|
||||||
final LayeredConnectionSocketFactory defaultSocketFactory) {
|
final LayeredConnectionSocketFactory defaultSocketFactory) {
|
||||||
this.bundleContext = bundleContext;
|
this.trustedHostsConfiguration = trustedHostsConfiguration;
|
||||||
this.trustedHostConfiguration = trustedHostConfiguration;
|
|
||||||
this.defaultSocketFactory = defaultSocketFactory;
|
this.defaultSocketFactory = defaultSocketFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,26 +54,21 @@ public Socket createLayeredSocket(final Socket socket,
|
|||||||
final String target,
|
final String target,
|
||||||
final int port,
|
final int port,
|
||||||
final HttpContext context) throws IOException {
|
final HttpContext context) throws IOException {
|
||||||
final ManagedService trustedHostsConfigurationObject = bundleContext.getService(trustedHostConfiguration.getReference());
|
if (trustedHostsConfiguration.isEnabled()) {
|
||||||
if (trustedHostsConfigurationObject != null) {
|
// if trust all there is no check to perform
|
||||||
final TrustedHostsConfiguration configuration = (TrustedHostsConfiguration) trustedHostsConfigurationObject;
|
if (trustedHostsConfiguration.trustAll()) {
|
||||||
|
return socket;
|
||||||
|
}
|
||||||
|
|
||||||
if (configuration.isEnabled()) {
|
// blindly verify the host if in the trust list
|
||||||
// if trust all there is no check to perform
|
for (String trustedHost : trustedHostsConfiguration.getTrustedHosts()) {
|
||||||
if (configuration.trustAll()) {
|
if (createMatcher(trustedHost).matches(target)) {
|
||||||
return socket;
|
return socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
// blindly verify the host if in the trust list
|
|
||||||
for (String trustedHost : configuration.getTrustedHosts()) {
|
|
||||||
if (createMatcher(trustedHost).matches(target)) {
|
|
||||||
return socket;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// follow back to the default behavior
|
// fall back to the default behavior
|
||||||
return defaultSocketFactory.createLayeredSocket(socket, target, port, context);
|
return defaultSocketFactory.createLayeredSocket(socket, target, port, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,10 +26,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.hc.client5.http.osgi.impl;
|
package org.apache.hc.client5.http.osgi.impl;
|
||||||
|
|
||||||
import static org.junit.Assert.assertNotSame;
|
|
||||||
import static org.junit.Assert.assertSame;
|
import static org.junit.Assert.assertSame;
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
import static org.mockito.Mockito.when;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
@ -42,79 +39,56 @@
|
|||||||
import org.apache.hc.core5.http.protocol.BasicHttpContext;
|
import org.apache.hc.core5.http.protocol.BasicHttpContext;
|
||||||
import org.apache.hc.core5.http.protocol.HttpContext;
|
import org.apache.hc.core5.http.protocol.HttpContext;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.osgi.framework.BundleContext;
|
import org.mockito.Mock;
|
||||||
import org.osgi.framework.ServiceReference;
|
|
||||||
import org.osgi.framework.ServiceRegistration;
|
|
||||||
import org.osgi.service.cm.ConfigurationException;
|
import org.osgi.service.cm.ConfigurationException;
|
||||||
import org.osgi.service.cm.ManagedService;
|
|
||||||
|
|
||||||
public class TestRelaxedLayeredConnectionSocketFactory {
|
public class TestRelaxedLayeredConnectionSocketFactory {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
Socket insecureSocket;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
Socket secureSocket;
|
||||||
|
|
||||||
|
private final HttpContext context = new BasicHttpContext();
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTrustedAllConnections() throws Exception {
|
public void testTrustedAllConnections() throws Exception {
|
||||||
final HttpContext context = new BasicHttpContext();
|
final LayeredConnectionSocketFactory socketFactory = getLayeredConnectionSocketFactory(true, true);
|
||||||
|
|
||||||
final Dictionary<String, Object> config = new Hashtable<>();
|
|
||||||
config.put("trustedhosts.enabled", Boolean.TRUE);
|
|
||||||
config.put("trustedhosts.trustAll", Boolean.TRUE);
|
|
||||||
config.put("trustedhosts.hosts", new String[]{});
|
|
||||||
final LayeredConnectionSocketFactory socketFactory = getLayeredConnectionSocketFactory(config);
|
|
||||||
final Socket socket = socketFactory.createSocket(context);
|
final Socket socket = socketFactory.createSocket(context);
|
||||||
final Socket secureSocket = socketFactory.createLayeredSocket(socket, "localhost", 9999, context);
|
final Socket secureSocket = socketFactory.createLayeredSocket(socket, "localhost", 9999, context);
|
||||||
assertSame(socket, secureSocket);
|
assertSame(this.secureSocket, secureSocket);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTrustedConnections() throws Exception {
|
public void testTrustedConnections() throws Exception {
|
||||||
final HttpContext context = new BasicHttpContext();
|
final LayeredConnectionSocketFactory socketFactory = getLayeredConnectionSocketFactory(true, false, "localhost");
|
||||||
final Dictionary<String, Object> config = new Hashtable<>();
|
|
||||||
config.put("trustedhosts.enabled", Boolean.TRUE);
|
|
||||||
config.put("trustedhosts.trustAll", Boolean.FALSE);
|
|
||||||
config.put("trustedhosts.hosts", new String[]{ "localhost" });
|
|
||||||
final LayeredConnectionSocketFactory socketFactory = getLayeredConnectionSocketFactory(config);
|
|
||||||
|
|
||||||
final Socket socket = socketFactory.createSocket(context);
|
final Socket socket = socketFactory.createSocket(context);
|
||||||
final Socket localSecureSocket = socketFactory.createLayeredSocket(socket, "localhost", 9999, context);
|
final Socket localSecureSocket = socketFactory.createLayeredSocket(socket, "localhost", 9999, context);
|
||||||
assertSame(socket, localSecureSocket);
|
assertSame(this.insecureSocket, localSecureSocket);
|
||||||
|
|
||||||
final Socket apacheSecureSocket = socketFactory.createLayeredSocket(socket, "www.apache.org", 9999, context);
|
final Socket apacheSecureSocket = socketFactory.createLayeredSocket(socket, "www.apache.org", 9999, context);
|
||||||
assertNotSame(socket, apacheSecureSocket);
|
assertSame(this.secureSocket, apacheSecureSocket);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNotEabledConfiguration() throws Exception {
|
public void testNotEabledConfiguration() throws Exception {
|
||||||
final HttpContext context = new BasicHttpContext();
|
final LayeredConnectionSocketFactory socketFactory = getLayeredConnectionSocketFactory(false, true);
|
||||||
|
|
||||||
final Dictionary<String, Object> config = new Hashtable<>();
|
|
||||||
config.put("trustedhosts.enabled", Boolean.TRUE);
|
|
||||||
config.put("trustedhosts.trustAll", Boolean.FALSE);
|
|
||||||
config.put("trustedhosts.hosts", new String[]{});
|
|
||||||
final LayeredConnectionSocketFactory socketFactory = getLayeredConnectionSocketFactory(config);
|
|
||||||
final Socket socket = socketFactory.createSocket(context);
|
final Socket socket = socketFactory.createSocket(context);
|
||||||
final Socket secureSocket = socketFactory.createLayeredSocket(socket, "localhost", 9999, context);
|
final Socket secureSocket = socketFactory.createLayeredSocket(socket, "localhost", 9999, context);
|
||||||
assertNotSame(socket, secureSocket);
|
assertSame(this.secureSocket, secureSocket);
|
||||||
}
|
}
|
||||||
|
|
||||||
private LayeredConnectionSocketFactory getLayeredConnectionSocketFactory(final Dictionary<String, ?> config) {
|
private LayeredConnectionSocketFactory getLayeredConnectionSocketFactory(
|
||||||
final ServiceReference<ManagedService> reference = mock(ServiceReference.class);
|
final boolean enabled, final boolean trustAll, final String... trustedHosts) throws ConfigurationException {
|
||||||
final ServiceRegistration<ManagedService> registration = mock(ServiceRegistration.class);
|
|
||||||
when(registration.getReference()).thenReturn(reference);
|
|
||||||
final BundleContext bundleContext = mock(BundleContext.class);
|
|
||||||
final OSGiTrustedHostsConfiguration configuration = new OSGiTrustedHostsConfiguration();
|
final OSGiTrustedHostsConfiguration configuration = new OSGiTrustedHostsConfiguration();
|
||||||
try {
|
configuration.updated(createConfig(enabled, trustAll, trustedHosts));
|
||||||
configuration.updated(config);
|
|
||||||
} catch (ConfigurationException e) {
|
|
||||||
// it doesn't happen in tests
|
|
||||||
}
|
|
||||||
when(bundleContext.getService(reference)).thenReturn(configuration);
|
|
||||||
|
|
||||||
final Socket socket = mock(Socket.class);
|
|
||||||
final Socket secureSocket = mock(Socket.class);
|
|
||||||
final LayeredConnectionSocketFactory defaultSocketFactory = new LayeredConnectionSocketFactory() {
|
final LayeredConnectionSocketFactory defaultSocketFactory = new LayeredConnectionSocketFactory() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Socket createSocket(final HttpContext context) throws IOException {
|
public Socket createSocket(final HttpContext context) throws IOException {
|
||||||
return socket;
|
return insecureSocket;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -125,7 +99,7 @@ public Socket connectSocket(final int connectTimeout,
|
|||||||
final InetSocketAddress localAddress,
|
final InetSocketAddress localAddress,
|
||||||
final HttpContext context ) throws IOException {
|
final HttpContext context ) throws IOException {
|
||||||
// not needed in this version
|
// not needed in this version
|
||||||
return socket;
|
return insecureSocket;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -138,7 +112,15 @@ public Socket createLayeredSocket(final Socket socket,
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return new RelaxedLayeredConnectionSocketFactory(bundleContext, registration, defaultSocketFactory);
|
return new RelaxedLayeredConnectionSocketFactory(configuration, defaultSocketFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Dictionary<String, Object> createConfig(final boolean enabled, final boolean trustAll, final String... trustedHosts) {
|
||||||
|
final Dictionary<String, Object> config = new Hashtable<>();
|
||||||
|
config.put("trustedhosts.enabled", enabled);
|
||||||
|
config.put("trustedhosts.trustAll", trustAll);
|
||||||
|
config.put("trustedhosts.hosts", trustedHosts);
|
||||||
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user