5151import org .apache .hc .core5 .concurrent .DefaultThreadFactory ;
5252import org .apache .hc .core5 .http .ClassicHttpResponse ;
5353import org .apache .hc .core5 .http .ConnectionRequestTimeoutException ;
54+ import org .apache .hc .core5 .http .HttpHeaders ;
5455import org .apache .hc .core5 .http .HttpStatus ;
5556import org .apache .hc .core5 .http .NoHttpResponseException ;
5657import org .slf4j .Logger ;
7475import java .util .HashSet ;
7576import java .util .LinkedHashMap ;
7677import java .util .List ;
78+ import java .util .Locale ;
7779import java .util .Map ;
7880import java .util .Set ;
7981import java .util .StringJoiner ;
@@ -811,7 +813,7 @@ public Builder allowBinaryReaderToReuseBuffers(boolean reuse) {
811813 * @return same instance of the builder
812814 */
813815 public Builder httpHeader (String key , String value ) {
814- this .configuration .put (ClientSettings .HTTP_HEADER_PREFIX + key , value );
816+ this .configuration .put (ClientSettings .HTTP_HEADER_PREFIX + key . toUpperCase ( Locale . US ) , value );
815817 return this ;
816818 }
817819
@@ -822,7 +824,7 @@ public Builder httpHeader(String key, String value) {
822824 * @return same instance of the builder
823825 */
824826 public Builder httpHeader (String key , Collection <String > values ) {
825- this .configuration .put (ClientSettings .HTTP_HEADER_PREFIX + key , ClientSettings .commaSeparated (values ));
827+ this .configuration .put (ClientSettings .HTTP_HEADER_PREFIX + key . toUpperCase ( Locale . US ) , ClientSettings .commaSeparated (values ));
826828 return this ;
827829 }
828830
@@ -880,12 +882,30 @@ public Builder columnToMethodMatchingStrategy(ColumnToMethodMatchingStrategy str
880882 * Whether to use HTTP basic authentication. Default value is true.
881883 * Password that contain UTF8 characters may not be passed through http headers and BASIC authentication
882884 * is the only option here.
885+ * @param useBasicAuth - indicates if basic authentication should be used
886+ * @return same instance of the builder
883887 */
884888 public Builder useHTTPBasicAuth (boolean useBasicAuth ) {
885889 this .configuration .put (ClientSettings .HTTP_USE_BASIC_AUTH , String .valueOf (useBasicAuth ));
886890 return this ;
887891 }
888892
893+ /**
894+ * Sets additional information about calling application. This string will be passed to server as a client name.
895+ * In case of HTTP protocol it will be passed as a {@code User-Agent} header.
896+ * Warn: If custom value of User-Agent header is set it will override this value for HTTP transport
897+ * </br>
898+ * Client name is used by server to identify client application when investigating {@code system.query_log}. In case of HTTP
899+ * transport this value will be in the {@code system.query_log.http_user_agent} column. Currently only HTTP transport is used.
900+ *
901+ * @param clientName - client application display name.
902+ * @return same instance of the builder
903+ */
904+ public Builder setClientName (String clientName ) {
905+ this .configuration .put (ClientSettings .CLIENT_NAME , clientName );
906+ return this ;
907+ }
908+
889909 public Client build () {
890910 setDefaults ();
891911
@@ -1023,7 +1043,41 @@ private void setDefaults() {
10231043 if (!configuration .containsKey (ClientSettings .HTTP_USE_BASIC_AUTH )) {
10241044 useHTTPBasicAuth (true );
10251045 }
1046+
1047+ String userAgent = configuration .getOrDefault (ClientSettings .HTTP_HEADER_PREFIX + HttpHeaders .USER_AGENT .toUpperCase (Locale .US ), "" );
1048+ String clientName = configuration .getOrDefault (ClientSettings .CLIENT_NAME , "" );
1049+ httpHeader (HttpHeaders .USER_AGENT , buildUserAgent (userAgent .isEmpty () ? clientName : userAgent ));
1050+ }
1051+
1052+ private static String buildUserAgent (String customUserAgent ) {
1053+
1054+ StringBuilder userAgent = new StringBuilder ();
1055+ if (customUserAgent != null && !customUserAgent .isEmpty ()) {
1056+ userAgent .append (customUserAgent ).append (" " );
1057+ }
1058+
1059+ userAgent .append (CLIENT_USER_AGENT );
1060+
1061+ String clientVersion = Client .class .getPackage ().getImplementationVersion ();
1062+ if (clientVersion == null ) {
1063+ clientVersion = LATEST_ARTIFACT_VERSION ;
1064+ }
1065+ userAgent .append (clientVersion );
1066+
1067+ userAgent .append (" (" );
1068+ userAgent .append (System .getProperty ("os.name" ));
1069+ userAgent .append ("; " );
1070+ userAgent .append ("jvm:" ).append (System .getProperty ("java.version" ));
1071+ userAgent .append ("; " );
1072+
1073+ userAgent .setLength (userAgent .length () - 2 );
1074+ userAgent .append (')' );
1075+
1076+ return userAgent .toString ();
10261077 }
1078+
1079+ public static final String LATEST_ARTIFACT_VERSION = "0.7.1-patch1" ;
1080+ public static final String CLIENT_USER_AGENT = "ch-j-v2/" ;
10271081 }
10281082
10291083 private ClickHouseNode getServerNode () {
0 commit comments