From c7eca5ea0cbd1133b1e25e2ea604266a4a88beb2 Mon Sep 17 00:00:00 2001 From: cen1 Date: Sun, 29 Nov 2020 22:13:21 +0100 Subject: [PATCH] make http client implementation configurable, configurable jetty connector --- README.md | 24 +++++ .../client/mp/spec/RestClientBuilderImpl.java | 88 +++++++++++++++++-- 2 files changed, 103 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index aaeba84..b69bccc 100644 --- a/README.md +++ b/README.md @@ -179,6 +179,30 @@ kumuluzee: When using both configuration keys and fully qualified class names for the configuration the fully qualified class name configuration takes precedence. +### Configuration of underlying http client + +Corresponding jetty javadoc for jetty can be found [here](https://www.eclipse.org/jetty/javadoc/9.4.35.v20201120/org/eclipse/jetty/client/HttpClient.html). + +Configuration for `http-url` native java connector is not yet possible due to limitations in Jersey. + +```yaml +kumuluzee: + rest-client: + http-client-connector: jetty # or http-url, java native http client + enable-ssl-hostname-verification: true + disable-jetty-www-auth: true + jetty: + address-resolution-timeout: 100 #in ms + connect-timeout: 100 # in ms + default-request-content-type: application/json + follow-redirects: true + idle-timeout: 30000 # in ms + max-redirects: 3 + request-buffer-size: 4000 # in bytes, internal buffers only, not max size + read-buffer-size: 4000 # in bytes, internal buffers only, not max size + tcp-no-delay: false +``` + ### Making asynchronous requests In order to make requests asynchronously the method in the API interface should return parameterized type diff --git a/src/main/java/com/kumuluz/ee/rest/client/mp/spec/RestClientBuilderImpl.java b/src/main/java/com/kumuluz/ee/rest/client/mp/spec/RestClientBuilderImpl.java index bc25545..81968cc 100644 --- a/src/main/java/com/kumuluz/ee/rest/client/mp/spec/RestClientBuilderImpl.java +++ b/src/main/java/com/kumuluz/ee/rest/client/mp/spec/RestClientBuilderImpl.java @@ -32,6 +32,8 @@ import org.eclipse.microprofile.rest.client.ext.ResponseExceptionMapper; import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; import org.eclipse.microprofile.rest.client.spi.RestClientListener; +import org.glassfish.jersey.client.ClientConfig; +import org.glassfish.jersey.client.HttpUrlConnectorProvider; import org.glassfish.jersey.jetty.connector.JettyClientProperties; import org.glassfish.jersey.jetty.connector.JettyConnectorProvider; import org.glassfish.jersey.media.multipart.MultiPartFeature; @@ -67,6 +69,11 @@ public class RestClientBuilderImpl implements RestClientBuilder { private static final Logger LOG = Logger.getLogger(RestClientBuilderImpl.class.getSimpleName()); + private static final String CONFIG_PREFIX = "kumuluzee.rest-client"; + private static final String CONFIG_PREFIX_JETTY = "kumuluzee.rest-client.jetty"; + private static final String CONFIG_CONNECTOR_JETTY = "jetty"; + private static final String CONFIG_CONNECTOR_HTTP_URL = "http-url"; + private ClientBuilder clientBuilder; private URI baseURI; private ExecutorService executorService; @@ -301,23 +308,86 @@ private T create(Class apiClass) { register(DefaultExceptionMapper.class); } - if (ConfigurationUtil.getInstance().getBoolean("kumuluzee.rest-client.enable-ssl-hostname-verification") + ConfigurationUtil confUtil = ConfigurationUtil.getInstance(); + + String httpClient = confUtil.get(CONFIG_PREFIX+".http-client-connector").orElse(CONFIG_CONNECTOR_JETTY); + + if (CONFIG_CONNECTOR_HTTP_URL.equals(httpClient)) { + ClientConfig clientConfig = new ClientConfig(); + clientConfig.connectorProvider(new HttpUrlConnectorProvider()); + clientBuilder.withConfig(clientConfig); + } + else { + if (confUtil.getBoolean(CONFIG_PREFIX+".enable-ssl-hostname-verification") .orElse(hostnameVerifier == null)) { - clientBuilder.property(JettyClientProperties.ENABLE_SSL_HOSTNAME_VERIFICATION, true); + clientBuilder.property(JettyClientProperties.ENABLE_SSL_HOSTNAME_VERIFICATION, true); + } } Client client = clientBuilder.build(); - if (this.hostnameVerifier != null) { - // Jetty connector does not yet support setting the hostname verifier, fix it manually - JettyConnectorProvider.getHttpClient(client).getSslContextFactory().setEndpointIdentificationAlgorithm(null); - JettyConnectorProvider.getHttpClient(client).getSslContextFactory().setHostnameVerifier(hostnameVerifier); - } + if (CONFIG_CONNECTOR_JETTY.equals(httpClient)) { + //Configure all (or most) Jetty props from config + List configNames = confUtil.getMapKeys(CONFIG_PREFIX_JETTY) + .orElse(new LinkedList<>()); + for (String configLine : configNames) { + String configKey = CONFIG_PREFIX_JETTY + "." + configLine; + switch (configLine) { + case "address-resolution-timeout": + JettyConnectorProvider.getHttpClient(client) + .setAddressResolutionTimeout(confUtil.getLong(configKey).get()); + break; + case "connect-timeout": + JettyConnectorProvider.getHttpClient(client) + .setConnectTimeout(confUtil.getLong(configKey).get()); + break; + case "default-request-content-type": + JettyConnectorProvider.getHttpClient(client) + .setDefaultRequestContentType(confUtil.get(configKey).get()); + break; + case "follow-redirects": + JettyConnectorProvider.getHttpClient(client) + .setFollowRedirects(confUtil.getBoolean(configKey).get()); + break; + case "idle-timeout": + JettyConnectorProvider.getHttpClient(client) + .setIdleTimeout(confUtil.getLong(configKey).get()); + break; + case "max-redirects": + JettyConnectorProvider.getHttpClient(client) + .setMaxRedirects(confUtil.getInteger(configKey).get()); + break; + case "request-buffer-size": + JettyConnectorProvider.getHttpClient(client) + .setRequestBufferSize(confUtil.getInteger(configKey).get()); + break; + case "read-buffer-size": + JettyConnectorProvider.getHttpClient(client) + .setResponseBufferSize(confUtil.getInteger(configKey).get()); + break; + case "tcp-no-delay": + JettyConnectorProvider.getHttpClient(client) + .setTCPNoDelay(confUtil.getBoolean(configKey).get()); + break; + default: + break; + } + } + + if (this.hostnameVerifier != null) { + // Jetty connector does not yet support setting the hostname verifier, fix it manually + JettyConnectorProvider.getHttpClient(client).getSslContextFactory().setEndpointIdentificationAlgorithm(null); + JettyConnectorProvider.getHttpClient(client).getSslContextFactory().setHostnameVerifier(hostnameVerifier); + } - if (ConfigurationUtil.getInstance().getBoolean("kumuluzee.rest-client.disable-jetty-www-auth") + if (confUtil.getBoolean(CONFIG_PREFIX + ".disable-jetty-www-auth") .orElse(false)) { - JettyConnectorProvider.getHttpClient(client).getProtocolHandlers() + JettyConnectorProvider.getHttpClient(client).getProtocolHandlers() .remove(WWWAuthenticationProtocolHandler.NAME); + } + } + else if (CONFIG_CONNECTOR_HTTP_URL.equals(httpClient)) { + //TODO: not yet configurable in jersey, check with upstream } RestClientInvoker rcInvoker = new RestClientInvoker(