diff --git a/clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseConfig.java b/clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseConfig.java index 8a9eecb28..8e48dc236 100644 --- a/clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseConfig.java +++ b/clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseConfig.java @@ -26,7 +26,7 @@ */ public class ClickHouseConfig implements Serializable { static final class ClientOptions { - private static final ClientOptions instance = new ClientOptions(); + private static final ClientOptions INSTANCE = new ClientOptions(); private final Map customOptions; @@ -138,7 +138,7 @@ protected static final Object mergeMetricRegistry(List list) { public static Map toClientOptions(Map props) { Map options = new HashMap<>(); if (props != null && !props.isEmpty()) { - Map customOptions = ClientOptions.instance.customOptions; + Map customOptions = ClientOptions.INSTANCE.customOptions; for (Entry e : props.entrySet()) { if (e.getKey() == null || e.getValue() == null) { continue; @@ -202,6 +202,7 @@ public static Map toClientOptions(Map prop private final String sslKey; private final boolean useBlockingQueue; private final boolean useObjectsInArray; + private final boolean useNoProxy; private final boolean useServerTimeZone; private final boolean useServerTimeZoneForDates; private final TimeZone timeZoneForDate; @@ -297,6 +298,7 @@ public ClickHouseConfig(Map options, ClickHouseC this.sslKey = (String) getOption(ClickHouseClientOption.SSL_KEY); this.useBlockingQueue = (boolean) getOption(ClickHouseClientOption.USE_BLOCKING_QUEUE); this.useObjectsInArray = (boolean) getOption(ClickHouseClientOption.USE_OBJECTS_IN_ARRAYS); + this.useNoProxy = (boolean) getOption(ClickHouseClientOption.USE_NO_PROXY); this.useServerTimeZone = (boolean) getOption(ClickHouseClientOption.USE_SERVER_TIME_ZONE); this.useServerTimeZoneForDates = (boolean) getOption(ClickHouseClientOption.USE_SERVER_TIME_ZONE_FOR_DATES); @@ -649,6 +651,10 @@ public boolean isUseObjectsInArray() { return useObjectsInArray; } + public boolean isUseNoProxy() { + return useNoProxy; + } + public boolean isUseServerTimeZone() { return useServerTimeZone; } diff --git a/clickhouse-client/src/main/java/com/clickhouse/client/config/ClickHouseClientOption.java b/clickhouse-client/src/main/java/com/clickhouse/client/config/ClickHouseClientOption.java index 75f9fe3af..e9d06cbc6 100644 --- a/clickhouse-client/src/main/java/com/clickhouse/client/config/ClickHouseClientOption.java +++ b/clickhouse-client/src/main/java/com/clickhouse/client/config/ClickHouseClientOption.java @@ -287,6 +287,12 @@ public enum ClickHouseClientOption implements ClickHouseOption { */ USE_OBJECTS_IN_ARRAYS("use_objects_in_arrays", false, "Whether Object[] should be used instead of primitive arrays."), + /** + * Whether to access ClickHouse server directly without using system wide proxy + * including the one defined in JVM system properties. + */ + USE_NO_PROXY("use_no_proxy", false, + "Whether to access ClickHouse server directly without using system wide proxy including the one defined in JVM system properties."), /** * Whether to use server time zone. */ diff --git a/clickhouse-grpc-client/src/main/java/com/clickhouse/client/grpc/ClickHouseGrpcChannelFactory.java b/clickhouse-grpc-client/src/main/java/com/clickhouse/client/grpc/ClickHouseGrpcChannelFactory.java index 3c816a908..4ca730288 100644 --- a/clickhouse-grpc-client/src/main/java/com/clickhouse/client/grpc/ClickHouseGrpcChannelFactory.java +++ b/clickhouse-grpc-client/src/main/java/com/clickhouse/client/grpc/ClickHouseGrpcChannelFactory.java @@ -1,7 +1,9 @@ package com.clickhouse.client.grpc; import java.io.FileNotFoundException; +import java.io.IOException; import java.io.InputStreamReader; +import java.net.SocketAddress; import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.HashMap; @@ -11,6 +13,8 @@ import com.google.gson.stream.JsonReader; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import io.grpc.ProxiedSocketAddress; +import io.grpc.ProxyDetector; import io.grpc.Status; import com.clickhouse.client.ClickHouseChecker; import com.clickhouse.client.ClickHouseConfig; @@ -22,6 +26,18 @@ import com.clickhouse.client.logging.LoggerFactory; public abstract class ClickHouseGrpcChannelFactory { + static class NoProxyDetector implements ProxyDetector { + static final NoProxyDetector INSTANCE = new NoProxyDetector(); + + private NoProxyDetector() { + } + + @Override + public ProxiedSocketAddress proxyFor(SocketAddress arg0) throws IOException { + return null; + } + } + private static final Logger log = LoggerFactory.getLogger(ClickHouseGrpcChannelFactory.class); private static final String PROP_NAME = "name"; @@ -164,6 +180,9 @@ protected void setupMisc() { builder.enableFullStreamDecompression(); } + if (config.isUseNoProxy()) { + builder.proxyDetector(NoProxyDetector.INSTANCE); + } // TODO add interceptor to customize retry builder.maxInboundMessageSize((int) config.getOption(ClickHouseGrpcOption.MAX_INBOUND_MESSAGE_SIZE)) .maxInboundMetadataSize((int) config.getOption(ClickHouseGrpcOption.MAX_INBOUND_METADATA_SIZE)); diff --git a/clickhouse-http-client/src/main/java/com/clickhouse/client/http/HttpUrlConnectionImpl.java b/clickhouse-http-client/src/main/java/com/clickhouse/client/http/HttpUrlConnectionImpl.java index 4346e3726..86fe4b1b7 100644 --- a/clickhouse-http-client/src/main/java/com/clickhouse/client/http/HttpUrlConnectionImpl.java +++ b/clickhouse-http-client/src/main/java/com/clickhouse/client/http/HttpUrlConnectionImpl.java @@ -27,6 +27,7 @@ import java.io.UncheckedIOException; import java.net.ConnectException; import java.net.HttpURLConnection; +import java.net.Proxy; import java.net.URL; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; @@ -107,7 +108,9 @@ private ClickHouseHttpResponse buildResponse() throws IOException { } private HttpURLConnection newConnection(String url, boolean post) throws IOException { - HttpURLConnection newConn = (HttpURLConnection) new URL(url).openConnection(); + HttpURLConnection newConn = config.isUseNoProxy() + ? (HttpURLConnection) new URL(url).openConnection(Proxy.NO_PROXY) + : (HttpURLConnection) new URL(url).openConnection(); if ((newConn instanceof HttpsURLConnection) && config.isSsl()) { HttpsURLConnection secureConn = (HttpsURLConnection) newConn; @@ -143,12 +146,10 @@ private String getResponseHeader(String header, String defaultValue) { private void setHeaders(HttpURLConnection conn, Map headers) { headers = mergeHeaders(headers); - if (headers == null || headers.isEmpty()) { - return; - } - - for (Entry header : headers.entrySet()) { - conn.setRequestProperty(header.getKey(), header.getValue()); + if (headers != null && !headers.isEmpty()) { + for (Entry header : headers.entrySet()) { + conn.setRequestProperty(header.getKey(), header.getValue()); + } } } diff --git a/clickhouse-http-client/src/main/java11/com/clickhouse/client/http/HttpClientConnectionImpl.java b/clickhouse-http-client/src/main/java11/com/clickhouse/client/http/HttpClientConnectionImpl.java index cb2a027b6..499c7bfa4 100644 --- a/clickhouse-http-client/src/main/java11/com/clickhouse/client/http/HttpClientConnectionImpl.java +++ b/clickhouse-http-client/src/main/java11/com/clickhouse/client/http/HttpClientConnectionImpl.java @@ -29,6 +29,9 @@ import java.io.UncheckedIOException; import java.net.ConnectException; import java.net.HttpURLConnection; +import java.net.Proxy; +import java.net.ProxySelector; +import java.net.SocketAddress; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpConnectTimeoutException; @@ -52,6 +55,25 @@ import javax.net.ssl.SSLContext; public class HttpClientConnectionImpl extends ClickHouseHttpConnection { + static class NoProxySelector extends ProxySelector { + static final NoProxySelector INSTANCE = new NoProxySelector(); + + private static final List NO_PROXY_LIST = List.of(Proxy.NO_PROXY); + + private NoProxySelector() { + } + + @Override + public void connectFailed(URI uri, SocketAddress sa, IOException e) { + // ignore + } + + @Override + public List select(URI uri) { + return NO_PROXY_LIST; + } + } + private static final Logger log = LoggerFactory.getLogger(HttpClientConnectionImpl.class); private final HttpClient httpClient; @@ -147,6 +169,9 @@ protected HttpClientConnectionImpl(ClickHouseNode server, ClickHouseRequest r if (executor != null) { builder.executor(executor); } + if (config.isUseNoProxy()) { + builder.proxy(NoProxySelector.INSTANCE); + } if (config.isSsl()) { builder.sslContext(ClickHouseSslContextProvider.getProvider().getSslContext(SSLContext.class, config) .orElse(null));