Skip to content

Commit fedb151

Browse files
authored
Merge pull request #1070 from zhicwu/develop
Respect custom Authorization header in clickhouse-http-client
2 parents 4077e59 + 12b95ac commit fedb151

File tree

9 files changed

+181
-75
lines changed

9 files changed

+181
-75
lines changed

Diff for: clickhouse-client/src/test/java/com/clickhouse/client/BaseIntegrationTest.java

+4
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ protected ClickHouseNode getSecureServer(ClickHouseProtocol protocol) {
1919
return ClickHouseServerForTest.getClickHouseNode(protocol, true, ClickHouseNode.builder().build());
2020
}
2121

22+
protected ClickHouseNode getSecureServer(ClickHouseProtocol protocol, ClickHouseNode base) {
23+
return ClickHouseServerForTest.getClickHouseNode(protocol, true, base);
24+
}
25+
2226
protected ClickHouseNode getServer(ClickHouseProtocol protocol) {
2327
return ClickHouseServerForTest.getClickHouseNode(protocol, false, ClickHouseNode.builder().build());
2428
}

Diff for: clickhouse-client/src/test/java/com/clickhouse/client/ClientIntegrationTest.java

+20-6
Original file line numberDiff line numberDiff line change
@@ -101,12 +101,14 @@ protected ClickHouseClientBuilder initClient(ClickHouseClientBuilder builder) {
101101
return builder;
102102
}
103103

104-
protected ClickHouseClient getClient() {
105-
return initClient(ClickHouseClient.builder()).nodeSelector(ClickHouseNodeSelector.of(getProtocol())).build();
104+
protected ClickHouseClient getClient(ClickHouseConfig... configs) {
105+
return initClient(ClickHouseClient.builder()).config(new ClickHouseConfig(configs))
106+
.nodeSelector(ClickHouseNodeSelector.of(getProtocol())).build();
106107
}
107108

108-
protected ClickHouseClient getSecureClient() {
109+
protected ClickHouseClient getSecureClient(ClickHouseConfig... configs) {
109110
return initClient(ClickHouseClient.builder())
111+
.config(new ClickHouseConfig(configs))
110112
.nodeSelector(ClickHouseNodeSelector.of(getProtocol()))
111113
.option(ClickHouseClientOption.SSL, true)
112114
.option(ClickHouseClientOption.SSL_MODE, ClickHouseSslMode.STRICT)
@@ -117,14 +119,22 @@ protected ClickHouseClient getSecureClient() {
117119
.build();
118120
}
119121

120-
protected ClickHouseNode getServer() {
121-
return getServer(getProtocol());
122+
protected ClickHouseNode getSecureServer(ClickHouseNode base) {
123+
return getSecureServer(getProtocol(), base);
122124
}
123125

124126
protected ClickHouseNode getSecureServer() {
125127
return getSecureServer(getProtocol());
126128
}
127129

130+
protected ClickHouseNode getServer(ClickHouseNode base) {
131+
return getServer(getProtocol(), base);
132+
}
133+
134+
protected ClickHouseNode getServer() {
135+
return getServer(getProtocol());
136+
}
137+
128138
@DataProvider(name = "compressionMatrix")
129139
protected Object[][] getCompressionMatrix() {
130140
ClickHouseFormat[] formats = new ClickHouseFormat[] {
@@ -1402,7 +1412,11 @@ public void testTempTable() throws Exception {
14021412
request.query("drop temporary table if exists my_temp_table").execute().get();
14031413
request.query("create temporary table my_temp_table(a Int8)").execute().get();
14041414
request.query("insert into my_temp_table values(2)").execute().get();
1405-
request.write().table("my_temp_table").data(new ByteArrayInputStream(new byte[] { 3 })).execute().get();
1415+
try (ClickHouseResponse resp = request.write().table("my_temp_table")
1416+
.data(new ByteArrayInputStream(new byte[] { 3 })).executeAndWait()) {
1417+
// ignore
1418+
}
1419+
14061420
int count = 0;
14071421
try (ClickHouseResponse resp = request.format(ClickHouseFormat.RowBinaryWithNamesAndTypes)
14081422
.query("select * from my_temp_table order by a").execute().get()) {

Diff for: clickhouse-http-client/src/main/java/com/clickhouse/client/http/ClickHouseHttpConnection.java

+32-16
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import java.util.Collections;
1010
import java.util.LinkedHashMap;
1111
import java.util.List;
12+
import java.util.Locale;
1213
import java.util.Map;
1314
import java.util.Optional;
1415
import java.util.Map.Entry;
@@ -158,39 +159,52 @@ static String buildUrl(String baseUrl, ClickHouseRequest<?> request) {
158159

159160
protected static Map<String, String> createDefaultHeaders(ClickHouseConfig config, ClickHouseNode server) {
160161
Map<String, String> map = new LinkedHashMap<>();
162+
boolean hasAuthorizationHeader = false;
161163
// add customer headers
162-
map.putAll(ClickHouseOption.toKeyValuePairs(config.getStrOption(ClickHouseHttpOption.CUSTOM_HEADERS)));
163-
map.put("Accept", "*/*");
164+
for (Entry<String, String> header : ClickHouseOption
165+
.toKeyValuePairs(config.getStrOption(ClickHouseHttpOption.CUSTOM_HEADERS)).entrySet()) {
166+
String name = header.getKey().toLowerCase(Locale.ROOT);
167+
String value = header.getValue();
168+
if (value == null) {
169+
continue;
170+
}
171+
if ("authorization".equals(name)) {
172+
hasAuthorizationHeader = true;
173+
}
174+
map.put(name, value);
175+
}
176+
177+
map.put("accept", "*/*");
164178
if (!config.getBoolOption(ClickHouseHttpOption.KEEP_ALIVE)) {
165-
map.put("Connection", "Close");
179+
map.put("connection", "Close");
166180
}
167-
map.put("User-Agent", config.getClientName());
181+
map.put("user-agent", config.getClientName());
168182

169183
ClickHouseCredentials credentials = server.getCredentials(config);
170184
if (credentials.useAccessToken()) {
171185
// TODO check if auth-scheme is available and supported
172-
map.put("Authorization", credentials.getAccessToken());
173-
} else {
174-
map.put("X-ClickHouse-User", credentials.getUserName());
186+
map.put("authorization", credentials.getAccessToken());
187+
} else if (!hasAuthorizationHeader) {
188+
map.put("x-clickhouse-user", credentials.getUserName());
175189
if (config.isSsl() && !ClickHouseChecker.isNullOrEmpty(config.getSslCert())) {
176-
map.put("X-ClickHouse-SSL-Certificate-Auth", "on");
190+
map.put("x-clickhouse-ssl-certificate-auth", "on");
177191
} else if (!ClickHouseChecker.isNullOrEmpty(credentials.getPassword())) {
178-
map.put("X-ClickHouse-Key", credentials.getPassword());
192+
map.put("x-clickhouse-key", credentials.getPassword());
179193
}
180194
}
181195

182196
String database = server.getDatabase(config);
183197
if (!ClickHouseChecker.isNullOrEmpty(database)) {
184-
map.put("X-ClickHouse-Database", database);
198+
map.put("x-clickhouse-database", database);
185199
}
186200
// Also, you can use the ‘default_format’ URL parameter
187-
map.put("X-ClickHouse-Format", config.getFormat().name());
201+
map.put("x-clickhouse-format", config.getFormat().name());
188202
if (config.isResponseCompressed()) {
189-
map.put("Accept-Encoding", config.getResponseCompressAlgorithm().encoding());
203+
map.put("accept-encoding", config.getResponseCompressAlgorithm().encoding());
190204
}
191205
if (config.isRequestCompressed()
192206
&& config.getRequestCompressAlgorithm() != ClickHouseCompression.LZ4) {
193-
map.put("Content-Encoding", config.getRequestCompressAlgorithm().encoding());
207+
map.put("content-encoding", config.getRequestCompressAlgorithm().encoding());
194208
}
195209
return map;
196210
}
@@ -251,10 +265,12 @@ protected Map<String, String> mergeHeaders(Map<String, String> requestHeaders) {
251265
Map<String, String> merged = new LinkedHashMap<>();
252266
merged.putAll(defaultHeaders);
253267
for (Entry<String, String> header : requestHeaders.entrySet()) {
254-
if (header.getValue() == null) {
255-
merged.remove(header.getKey());
268+
String name = header.getKey().toLowerCase(Locale.ROOT);
269+
String value = header.getValue();
270+
if (value == null) {
271+
merged.remove(name);
256272
} else {
257-
merged.put(header.getKey(), header.getValue());
273+
merged.put(name, value);
258274
}
259275
}
260276
return merged;

Diff for: clickhouse-http-client/src/main/java/com/clickhouse/client/http/ClickHouseHttpConnectionFactory.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,12 @@
66
import com.clickhouse.client.ClickHouseNode;
77
import com.clickhouse.client.ClickHouseRequest;
88

9-
public abstract class ClickHouseHttpConnectionFactory {
9+
public final class ClickHouseHttpConnectionFactory {
1010
public static ClickHouseHttpConnection createConnection(ClickHouseNode server, ClickHouseRequest<?> request,
1111
ExecutorService executor) throws IOException {
1212
return new HttpUrlConnectionImpl(server, request, executor);
1313
}
14+
15+
private ClickHouseHttpConnectionFactory() {
16+
}
1417
}

Diff for: clickhouse-http-client/src/main/java/com/clickhouse/client/http/HttpUrlConnectionImpl.java

+12-11
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,11 @@
4545
public class HttpUrlConnectionImpl extends ClickHouseHttpConnection {
4646
private static final Logger log = LoggerFactory.getLogger(HttpUrlConnectionImpl.class);
4747

48-
private static final byte[] HEADER_CONTENT_DISPOSITION = "Content-Disposition: form-data; name=\""
48+
private static final byte[] HEADER_CONTENT_DISPOSITION = "content-disposition: form-data; name=\""
4949
.getBytes(StandardCharsets.US_ASCII);
50-
private static final byte[] HEADER_OCTET_STREAM = "Content-Type: application/octet-stream\r\n"
50+
private static final byte[] HEADER_OCTET_STREAM = "content-type: application/octet-stream\r\n"
5151
.getBytes(StandardCharsets.US_ASCII);
52-
private static final byte[] HEADER_BINARY_ENCODING = "Content-Transfer-Encoding: binary\r\n\r\n"
52+
private static final byte[] HEADER_BINARY_ENCODING = "content-transfer-encoding: binary\r\n\r\n"
5353
.getBytes(StandardCharsets.US_ASCII);
5454

5555
private static final byte[] DOUBLE_DASH = new byte[] { '-', '-' };
@@ -217,14 +217,14 @@ protected boolean isReusable() {
217217
protected ClickHouseHttpResponse post(String sql, ClickHouseInputStream data, List<ClickHouseExternalTable> tables,
218218
String url, Map<String, String> headers, ClickHouseConfig config, Runnable postCloseAction)
219219
throws IOException {
220-
Charset charset = StandardCharsets.US_ASCII;
220+
Charset ascii = StandardCharsets.US_ASCII;
221221
byte[] boundary = null;
222222
if (tables != null && !tables.isEmpty()) {
223223
String uuid = UUID.randomUUID().toString();
224-
conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=".concat(uuid));
225-
boundary = uuid.getBytes(charset);
224+
conn.setRequestProperty("content-type", "multipart/form-data; boundary=".concat(uuid));
225+
boundary = uuid.getBytes(ascii);
226226
} else {
227-
conn.setRequestProperty("Content-Type", "text/plain; charset=UTF-8");
227+
conn.setRequestProperty("content-type", "text/plain; charset=UTF-8");
228228
}
229229
setHeaders(conn, headers);
230230

@@ -241,7 +241,8 @@ protected ClickHouseHttpResponse post(String sql, ClickHouseInputStream data, Li
241241
: (hasInput
242242
? ClickHouseClient.getAsyncRequestOutputStream(config, conn.getOutputStream(), null) // latch::countDown)
243243
: ClickHouseClient.getRequestOutputStream(c, conn.getOutputStream(), null))) {
244-
byte[] sqlBytes = hasFile ? new byte[0] : sql.getBytes(StandardCharsets.UTF_8);
244+
Charset utf8 = StandardCharsets.UTF_8;
245+
byte[] sqlBytes = hasFile ? new byte[0] : sql.getBytes(utf8);
245246
if (boundary != null) {
246247
out.writeBytes(LINE_PREFIX);
247248
out.writeBytes(boundary);
@@ -250,7 +251,7 @@ protected ClickHouseHttpResponse post(String sql, ClickHouseInputStream data, Li
250251
out.writeBytes(SUFFIX_QUERY);
251252
out.writeBytes(sqlBytes);
252253
for (ClickHouseExternalTable t : tables) {
253-
byte[] tableName = t.getName().getBytes(StandardCharsets.UTF_8);
254+
byte[] tableName = t.getName().getBytes(utf8);
254255
for (int i = 0; i < 3; i++) {
255256
out.writeBytes(LINE_PREFIX);
256257
out.writeBytes(boundary);
@@ -259,10 +260,10 @@ protected ClickHouseHttpResponse post(String sql, ClickHouseInputStream data, Li
259260
out.writeBytes(tableName);
260261
if (i == 0) {
261262
out.writeBytes(SUFFIX_FORMAT);
262-
out.writeBytes(t.getFormat().name().getBytes(charset));
263+
out.writeBytes(t.getFormat().name().getBytes(ascii));
263264
} else if (i == 1) {
264265
out.writeBytes(SUFFIX_STRUCTURE);
265-
out.writeBytes(t.getStructure().getBytes(StandardCharsets.UTF_8));
266+
out.writeBytes(t.getStructure().getBytes(utf8));
266267
} else {
267268
out.writeBytes(SUFFIX_FILENAME);
268269
out.writeBytes(tableName);

Diff for: clickhouse-http-client/src/main/java/com/clickhouse/client/http/config/ClickHouseHttpOption.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ public enum ClickHouseHttpOption implements ClickHouseOption {
1919
*/
2020
CUSTOM_HEADERS("custom_http_headers", "", "Custom HTTP headers."),
2121
/**
22-
* Custom HTTP query parameters.
22+
* Custom HTTP query parameters. Consider
23+
* {@link com.clickhouse.client.config.ClickHouseClientOption#CUSTOM_SETTINGS}
24+
* if you don't want your implementation ties to http protocol.
2325
*/
2426
CUSTOM_PARAMS("custom_http_params", "", "Custom HTTP query parameters."),
2527
/**

Diff for: clickhouse-http-client/src/main/java11/com/clickhouse/client/http/ClickHouseHttpConnectionFactory.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import com.clickhouse.client.http.config.ClickHouseHttpOption;
99
import com.clickhouse.client.http.config.HttpConnectionProvider;
1010

11-
public abstract class ClickHouseHttpConnectionFactory {
11+
public final class ClickHouseHttpConnectionFactory {
1212
public static ClickHouseHttpConnection createConnection(ClickHouseNode server, ClickHouseRequest<?> request,
1313
ExecutorService executor) throws IOException {
1414
HttpConnectionProvider provider = request.getConfig().getOption(ClickHouseHttpOption.CONNECTION_PROVIDER,
@@ -24,4 +24,7 @@ public static ClickHouseHttpConnection createConnection(ClickHouseNode server, C
2424
return new HttpUrlConnectionImpl(server, request, executor);
2525
}
2626
}
27+
28+
private ClickHouseHttpConnectionFactory() {
29+
}
2730
}

0 commit comments

Comments
 (0)