Skip to content

Commit 2e24b47

Browse files
authored
Merge branch 'main' into allow-v1-and-v2
2 parents ff38ee0 + 1baf186 commit 2e24b47

File tree

20 files changed

+380
-46
lines changed

20 files changed

+380
-46
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## Latest
2+
3+
### New Features
4+
- Added basic auth support for proxies. Now you can specify username/password when connecting via a proxy that requires it with HttpURLConnection and Apache HttpClient.
5+
16
## 0.7.1-patch1
27

38
### Bug Fixes

clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseConfig.java

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,8 @@ public static Map<ClickHouseOption, Serializable> toClientOptions(Map<?, ?> prop
245245
private final ClickHouseProxyType proxyType;
246246
private final String proxyHost;
247247
private final int proxyPort;
248+
private final String proxyUserName;
249+
private final char[] proxyPassword;
248250
// client specific options
249251
private final Map<ClickHouseOption, Serializable> options;
250252
private final ClickHouseCredentials credentials;
@@ -383,6 +385,8 @@ public ClickHouseConfig(Map<ClickHouseOption, Serializable> options, ClickHouseC
383385
this.proxyType = getOption(ClickHouseClientOption.PROXY_TYPE, ClickHouseProxyType.class);
384386
this.proxyHost = getStrOption(ClickHouseClientOption.PROXY_HOST);
385387
this.proxyPort = getIntOption(ClickHouseClientOption.PROXY_PORT);
388+
this.proxyUserName = getStrOption(ClickHouseClientOption.PROXY_USERNAME);
389+
this.proxyPassword = getStrOption(ClickHouseClientOption.PROXY_PASSWORD).toCharArray();
386390
}
387391

388392
@Override
@@ -674,14 +678,6 @@ public boolean isUseObjectsInArray() {
674678
return useObjectsInArray;
675679
}
676680

677-
/**
678-
* Checks whether no proxy is used or not.
679-
*
680-
* @return true if no proxy is used; false otherwise
681-
* @deprecated will be dropped in 0.5, please use {@link #getProxyType()}
682-
* instead
683-
*/
684-
685681
public ClickHouseProxyType getProxyType() {
686682
return proxyType;
687683
}
@@ -694,6 +690,14 @@ public int getProxyPort() {
694690
return proxyPort;
695691
}
696692

693+
public String getProxyUserName() {
694+
return proxyUserName;
695+
}
696+
697+
public char[] getProxyPassword() {
698+
return proxyPassword;
699+
}
700+
697701
public boolean isUseServerTimeZone() {
698702
return useServerTimeZone;
699703
}

clickhouse-client/src/main/java/com/clickhouse/client/config/ClickHouseClientOption.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,15 @@ public enum ClickHouseClientOption implements ClickHouseOption {
402402
/**
403403
* Set ClickHouse proxy port.
404404
*/
405-
PROXY_PORT("proxy_port", -1, "Set ClickHouse server proxy hostname."),
405+
PROXY_PORT("proxy_port", -1, "Set ClickHouse server proxy port."),
406+
/**
407+
* Set Clickhouse proxy username.
408+
*/
409+
PROXY_USERNAME("proxy_username", "", "Set ClickHouse server proxy username."),
410+
/**
411+
* Set ClickHouse proxy password.
412+
*/
413+
PROXY_PASSWORD("proxy_password", "", "Set ClickHouse server proxy password."),
406414
/**
407415
* Whether to use server time zone.
408416
*/

clickhouse-http-client/src/main/java/com/clickhouse/client/http/ApacheHttpConnectionImpl.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,12 @@
1919
import com.clickhouse.data.ClickHouseUtils;
2020
import com.clickhouse.logging.Logger;
2121
import com.clickhouse.logging.LoggerFactory;
22+
import org.apache.hc.client5.http.auth.AuthScope;
23+
import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
2224
import org.apache.hc.client5.http.classic.methods.HttpGet;
2325
import org.apache.hc.client5.http.classic.methods.HttpPost;
2426
import org.apache.hc.client5.http.config.ConnectionConfig;
27+
import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
2528
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
2629
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
2730
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
@@ -121,6 +124,14 @@ private CloseableHttpClient newConnection(ClickHouseConfig c) throws IOException
121124
}
122125
if (c.getProxyType() == ClickHouseProxyType.HTTP) {
123126
builder.setProxy(new HttpHost(c.getProxyHost(), c.getProxyPort()));
127+
128+
if (c.getProxyUserName() != null && c.getProxyUserName() != "") {
129+
AuthScope authScope = new AuthScope(c.getProxyHost(), c.getProxyPort());
130+
UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(c.getProxyUserName(), c.getProxyPassword());
131+
BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
132+
credsProvider.setCredentials(authScope, credentials);
133+
builder.setDefaultCredentialsProvider(credsProvider);
134+
}
124135
}
125136
return builder.build();
126137
}

clickhouse-http-client/src/main/java/com/clickhouse/client/http/ClickHouseHttpConnection.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,19 @@ protected static Proxy getProxy(ClickHouseConfig config) {
287287
return proxy;
288288
}
289289

290+
protected static String getProxyAuth(ClickHouseConfig config) {
291+
String authHeader = null;
292+
if (config.getProxyType() == ClickHouseProxyType.HTTP) {
293+
String userName = config.getProxyUserName();
294+
if (!ClickHouseChecker.isNullOrEmpty(userName)) {
295+
String auth = userName + ":" + new String(config.getProxyPassword());
296+
byte[] encodedAuth = Base64.getEncoder().encode(auth.getBytes(StandardCharsets.UTF_8));
297+
authHeader = "Basic " + new String(encodedAuth);
298+
}
299+
}
300+
return authHeader;
301+
}
302+
290303
protected static String parseErrorFromException(String errorCode, String serverName, IOException e, byte[] bytes) {
291304
log.debug("Failed to read error message[code=%s] from server [%s] due to: %s", errorCode, serverName,
292305
e.getMessage());

clickhouse-http-client/src/main/java/com/clickhouse/client/http/HttpUrlConnectionImpl.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,10 @@ private HttpURLConnection newConnection(String url, boolean post) throws IOExcep
111111
if (proxy != null) {
112112
log.debug("using proxy type [%s] address [%s]", proxy.type().name(), proxy.address().toString());
113113
newConn = (HttpURLConnection) new URL(url).openConnection(proxy);
114+
String authString = getProxyAuth(c);
115+
if (authString != null) {
116+
newConn.setRequestProperty("Proxy-Authorization", authString);
117+
}
114118
} else {
115119
newConn = (HttpURLConnection) new URL(url).openConnection();
116120
}

client-v2/src/main/java/com/clickhouse/client/api/Client.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1903,7 +1903,7 @@ public ClickHouseBinaryFormatReader newBinaryFormatReader(QueryResponse response
19031903
byteBufferPool);
19041904
break;
19051905
default:
1906-
throw new IllegalArgumentException("Unsupported format: " + response.getFormat());
1906+
throw new IllegalArgumentException("Binary readers doesn't support format: " + response.getFormat());
19071907
}
19081908
return reader;
19091909
}

client-v2/src/main/java/com/clickhouse/client/api/ClientSettings.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,16 @@ public static List<String> valuesFromCommaSeparated(String value) {
3939
public static final String SETTING_LOG_COMMENT = SERVER_SETTING_PREFIX + "log_comment";
4040

4141
public static final String HTTP_USE_BASIC_AUTH = "http_use_basic_auth";
42+
43+
// -- Experimental features --
44+
45+
/**
46+
* Server will expect a string in JSON format and parse it into a JSON object.
47+
*/
48+
public static final String INPUT_FORMAT_BINARY_READ_JSON_AS_STRING = "input_format_binary_read_json_as_string";
49+
50+
/**
51+
* Server will return a JSON object as a string.
52+
*/
53+
public static final String OUTPUT_FORMAT_BINARY_WRITE_JSON_AS_STRING = "output_format_binary_write_json_as_string";
4254
}

client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/AbstractBinaryFormatReader.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package com.clickhouse.client.api.data_formats.internal;
22

33
import com.clickhouse.client.api.ClientException;
4+
import com.clickhouse.client.api.ClientSettings;
45
import com.clickhouse.client.api.data_formats.ClickHouseBinaryFormatReader;
6+
import com.clickhouse.client.api.internal.MapUtils;
57
import com.clickhouse.client.api.metadata.TableSchema;
68
import com.clickhouse.client.api.query.NullValueException;
79
import com.clickhouse.client.api.query.POJOSetter;
@@ -32,8 +34,10 @@
3234
import java.time.temporal.ChronoUnit;
3335
import java.util.Collections;
3436
import java.util.HashMap;
37+
import java.util.HashSet;
3538
import java.util.List;
3639
import java.util.Map;
40+
import java.util.Set;
3741
import java.util.TimeZone;
3842
import java.util.UUID;
3943
import java.util.concurrent.ConcurrentHashMap;
@@ -71,7 +75,9 @@ protected AbstractBinaryFormatReader(InputStream inputStream, QuerySettings quer
7175
if (timeZone == null) {
7276
throw new ClientException("Time zone is not set. (useServerTimezone:" + useServerTimeZone + ")");
7377
}
74-
this.binaryStreamReader = new BinaryStreamReader(inputStream, timeZone, LOG, byteBufferAllocator);
78+
boolean jsonAsString = MapUtils.getFlag(this.settings,
79+
ClientSettings.SERVER_SETTING_PREFIX + ClientSettings.OUTPUT_FORMAT_BINARY_WRITE_JSON_AS_STRING, false);
80+
this.binaryStreamReader = new BinaryStreamReader(inputStream, timeZone, LOG, byteBufferAllocator, jsonAsString);
7581
if (schema != null) {
7682
setSchema(schema);
7783
}

client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/BinaryStreamReader.java

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -45,16 +45,7 @@ public class BinaryStreamReader {
4545

4646
private final ByteBufferAllocator bufferAllocator;
4747

48-
/**
49-
* Creates a BinaryStreamReader instance that will use {@link DefaultByteBufferAllocator} to allocate buffers.
50-
*
51-
* @param input - source of raw data in a suitable format
52-
* @param timeZone - timezone to use for date and datetime values
53-
* @param log - logger
54-
*/
55-
BinaryStreamReader(InputStream input, TimeZone timeZone, Logger log) {
56-
this(input, timeZone, log, new DefaultByteBufferAllocator());
57-
}
48+
private final boolean jsonAsString;
5849

5950
/**
6051
* Createa a BinaryStreamReader instance that will use the provided buffer allocator.
@@ -64,11 +55,12 @@ public class BinaryStreamReader {
6455
* @param log - logger
6556
* @param bufferAllocator - byte buffer allocator
6657
*/
67-
BinaryStreamReader(InputStream input, TimeZone timeZone, Logger log, ByteBufferAllocator bufferAllocator) {
58+
BinaryStreamReader(InputStream input, TimeZone timeZone, Logger log, ByteBufferAllocator bufferAllocator, boolean jsonAsString) {
6859
this.log = log == null ? NOPLogger.NOP_LOGGER : log;
6960
this.timeZone = timeZone;
7061
this.input = input;
7162
this.bufferAllocator = bufferAllocator;
63+
this.jsonAsString = jsonAsString;
7264
}
7365

7466
/**
@@ -203,8 +195,13 @@ public <T> T readValue(ClickHouseColumn column, Class<?> typeHint) throws IOExce
203195
case Ring:
204196
return (T) readGeoRing();
205197

206-
// case JSON: // obsolete https://clickhouse.com/docs/en/sql-reference/data-types/json#displaying-json-column
207-
// case Object:
198+
case JSON: // experimental https://clickhouse.com/docs/en/sql-reference/data-types/newjson
199+
if (jsonAsString) {
200+
return (T) readString(input);
201+
} else {
202+
throw new RuntimeException("Reading JSON from binary is not implemented yet");
203+
}
204+
// case Object: // deprecated https://clickhouse.com/docs/en/sql-reference/data-types/object-data-type
208205
case Array:
209206
return convertArray(readArray(column), typeHint);
210207
case Map:

0 commit comments

Comments
 (0)