From 5b80029c301572871d3cc593d538c8a33cf5a51d Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Tue, 11 Mar 2025 18:57:36 +0700 Subject: [PATCH 01/52] feat: support proxy and ssl --- CHANGELOG.md | 4 + examples/docker-compose.yml | 12 +++ examples/envoy.yaml | 62 +++++++++++ .../java/com/influxdb/v3/ProxyExample.java | 59 ++++++++++ .../v3/client/config/ClientConfig.java | 95 +++++++++++++++- .../v3/client/internal/FlightSqlClient.java | 102 ++++++++++++++++-- .../v3/client/internal/RestClient.java | 9 +- .../v3/client/InfluxDBClientTest.java | 78 +++++++++++++- 8 files changed, 405 insertions(+), 16 deletions(-) create mode 100644 examples/docker-compose.yml create mode 100644 examples/envoy.yaml create mode 100644 examples/src/main/java/com/influxdb/v3/ProxyExample.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 48211487..48ed94b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## 1.1.0 [unreleased] +### Features + +1. [#229](https://github.com/InfluxCommunity/influxdb3-java/pull/229): Support proxy and ssl + ## 1.0.0 [2024-12-11] ### Features diff --git a/examples/docker-compose.yml b/examples/docker-compose.yml new file mode 100644 index 00000000..1ffa7ae0 --- /dev/null +++ b/examples/docker-compose.yml @@ -0,0 +1,12 @@ +version: "3" + +services: + envoy: + image: envoyproxy/envoy:v1.26-latest + volumes: + - ./envoy.yaml:/etc/envoy/envoy.yaml + ports: + - "10000:10000" + environment: + - ENVOY_UID=0 + diff --git a/examples/envoy.yaml b/examples/envoy.yaml new file mode 100644 index 00000000..4f627cfa --- /dev/null +++ b/examples/envoy.yaml @@ -0,0 +1,62 @@ +static_resources: + listeners: + - name: listener_0 + address: + socket_address: { address: 0.0.0.0, port_value: 10000 } + filter_chains: + - filter_chain_match: + filters: + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + stat_prefix: ingress_http + access_log: + - name: envoy.access_loggers.stdout + typed_config: + "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog + http2_protocol_options: + allow_connect: true + upgrade_configs: + - upgrade_type: CONNECT + http_filters: + - name: envoy.filters.http.router + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + + route_config: + name: local_route + virtual_hosts: + - name: local_service + domains: [ "*" ] + routes: + - match: + connect_matcher: { } + route: + cluster: influxdb_cluster + upgrade_configs: + upgrade_type: CONNECT + connect_config: { } + - match: + prefix: "/" + route: + cluster: influxdb_cluster + prefix_rewrite: "/" + auto_host_rewrite: true + timeout: 10s + cors: + allow_origin_string_match: + - prefix: "*" + allow_methods: GET, PUT, DELETE, POST, OPTIONS + clusters: + - name: influxdb_cluster + connect_timeout: 10s + type: STRICT_DNS + load_assignment: + cluster_name: influxdb_cluster + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: "us-east-1-1.aws.cloud2.influxdata.com" + port_value: 443 \ No newline at end of file diff --git a/examples/src/main/java/com/influxdb/v3/ProxyExample.java b/examples/src/main/java/com/influxdb/v3/ProxyExample.java new file mode 100644 index 00000000..c906229b --- /dev/null +++ b/examples/src/main/java/com/influxdb/v3/ProxyExample.java @@ -0,0 +1,59 @@ +package com.influxdb.v3; + +import java.net.InetSocketAddress; +import java.net.ProxySelector; +import java.net.URI; +import java.util.stream.Stream; + +import io.grpc.HttpConnectProxiedSocketAddress; +import io.grpc.ProxyDetector; + +import com.influxdb.v3.client.InfluxDBClient; +import com.influxdb.v3.client.Point; +import com.influxdb.v3.client.PointValues; +import com.influxdb.v3.client.config.ClientConfig; + +public final class ProxyExample { + + private ProxyExample() { } + + public static void main(final String[] args) throws Exception { + // Run docker-compose.yml file to start Envoy proxy + + URI queryProxyUri = new URI("proxyUrl"); + URI uri = new URI(System.getenv("url")); + + ProxyDetector proxyDetector = (targetServerAddress) -> { + InetSocketAddress targetAddress = (InetSocketAddress) targetServerAddress; + if (uri.getHost().equals(targetAddress.getHostString())) { + return HttpConnectProxiedSocketAddress.newBuilder() + .setProxyAddress(new InetSocketAddress(queryProxyUri.getHost(), queryProxyUri.getPort())) + .setTargetAddress(targetAddress) + .build(); + } + return null; + }; + ProxySelector proxy = ProxySelector.of(new InetSocketAddress(queryProxyUri.getHost(), queryProxyUri.getPort())); + ClientConfig clientConfig = new ClientConfig.Builder() + .host(uri.toString()) + .token(System.getenv("token").toCharArray()) + .database(System.getenv("database")) + .proxy(proxy) + .queryApiProxy(proxyDetector) + .build(); + + InfluxDBClient influxDBClient = InfluxDBClient.getInstance(clientConfig); + influxDBClient.writePoint( + Point.measurement("test1") + .setField("field", "field1") + ); + + try (Stream stream = influxDBClient.queryPoints("SELECT * FROM test1")) { + stream.findFirst() + .ifPresent(pointValues -> { + // do something + }); + } + } +} + diff --git a/src/main/java/com/influxdb/v3/client/config/ClientConfig.java b/src/main/java/com/influxdb/v3/client/config/ClientConfig.java index 55508a01..91af357b 100644 --- a/src/main/java/com/influxdb/v3/client/config/ClientConfig.java +++ b/src/main/java/com/influxdb/v3/client/config/ClientConfig.java @@ -35,6 +35,10 @@ import java.util.function.BiFunction; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import javax.net.ssl.SSLContext; + +import io.grpc.ProxyDetector; +import io.netty.handler.ssl.SslContext; import com.influxdb.v3.client.write.WritePrecision; @@ -58,6 +62,7 @@ * disable server certificate validation for HTTPS connections * *
  • proxy - HTTP proxy selector
  • + *
  • queryApiProxy - HTTP query detector
  • *
  • authenticator - HTTP proxy authenticator
  • *
  • headers - headers to be added to requests
  • * @@ -97,8 +102,11 @@ public final class ClientConfig { private final Boolean allowHttpRedirects; private final Boolean disableServerCertificateValidation; private final ProxySelector proxy; + private final ProxyDetector queryApiProxy; private final Authenticator authenticator; private final Map headers; + private final SslContext grpcSslContext; + private final SSLContext sslContext; /** * Gets URL of the InfluxDB server. @@ -219,6 +227,16 @@ public ProxySelector getProxy() { return proxy; } + /** + * Gets the proxy for query api. + * + * @return the proxy, may be null + */ + @Nullable + public ProxyDetector getQueryApiProxy() { + return queryApiProxy; + } + /** * Gets the (proxy) authenticator. * @@ -239,6 +257,26 @@ public Map getHeaders() { return headers; } + /** + * Gets SslContext object from grpc. + * + * @return the SslContext object + */ + @Nullable + public SslContext getGrpcSslContext() { + return grpcSslContext; + } + + /** + * Gets SSLContext object. + * + * @return the SSLContext object + */ + @Nullable + public SSLContext getSslContext() { + return sslContext; + } + /** * Validates the configuration properties. */ @@ -269,8 +307,11 @@ public boolean equals(final Object o) { && Objects.equals(allowHttpRedirects, that.allowHttpRedirects) && Objects.equals(disableServerCertificateValidation, that.disableServerCertificateValidation) && Objects.equals(proxy, that.proxy) + && Objects.equals(queryApiProxy, that.queryApiProxy) && Objects.equals(authenticator, that.authenticator) - && Objects.equals(headers, that.headers); + && Objects.equals(headers, that.headers) + && Objects.equals(grpcSslContext, that.grpcSslContext) + && Objects.equals(sslContext, that.sslContext); } @Override @@ -278,8 +319,8 @@ public int hashCode() { return Objects.hash(host, Arrays.hashCode(token), authScheme, organization, database, writePrecision, gzipThreshold, timeout, allowHttpRedirects, disableServerCertificateValidation, - proxy, authenticator, headers, - defaultTags); + proxy, queryApiProxy, authenticator, headers, + defaultTags, grpcSslContext, sslContext); } @Override @@ -294,9 +335,12 @@ public String toString() { .add("allowHttpRedirects=" + allowHttpRedirects) .add("disableServerCertificateValidation=" + disableServerCertificateValidation) .add("proxy=" + proxy) + .add("queryApiProxy=" + queryApiProxy) .add("authenticator=" + authenticator) .add("headers=" + headers) .add("defaultTags=" + defaultTags) + .add("grpcSslContext=" + grpcSslContext) + .add("sslContext=" + sslContext) .toString(); } @@ -318,8 +362,11 @@ public static final class Builder { private Boolean allowHttpRedirects; private Boolean disableServerCertificateValidation; private ProxySelector proxy; + private ProxyDetector queryApiProxy; private Authenticator authenticator; private Map headers; + private SslContext grpcSslContext; + private SSLContext sslContext; /** * Sets the URL of the InfluxDB server. @@ -480,6 +527,19 @@ public Builder proxy(@Nullable final ProxySelector proxy) { return this; } + /** + * Sets the proxy detector for query api. Default is 'null'. + * + * @param proxy Proxy detector. + * @return this + */ + @Nonnull + public Builder queryApiProxy(@Nullable final ProxyDetector proxy) { + + this.queryApiProxy = proxy; + return this; + } + /** * Sets the proxy authenticator. Default is 'null'. * @@ -523,6 +583,32 @@ public Builder headers(@Nullable final Map headers) { return this; } + /** + * Sets SslContext for grpc client. Default is 'null'. + * + * @param grpcSslContext The SSLContext + * @return this + */ + @Nonnull + public Builder grpcSslContext(@Nullable final SslContext grpcSslContext) { + + this.grpcSslContext = grpcSslContext; + return this; + } + + /** + * Sets SSLContext for rest client. Default is 'null'. + * + * @param sslContext The SSLContext + * @return this + */ + @Nonnull + public Builder sslContext(@Nullable final SSLContext sslContext) { + + this.sslContext = sslContext; + return this; + } + /** * Build an instance of {@code ClientConfig}. * @@ -658,7 +744,10 @@ private ClientConfig(@Nonnull final Builder builder) { disableServerCertificateValidation = builder.disableServerCertificateValidation != null ? builder.disableServerCertificateValidation : false; proxy = builder.proxy; + queryApiProxy = builder.queryApiProxy; authenticator = builder.authenticator; headers = builder.headers; + grpcSslContext = builder.grpcSslContext; + sslContext = builder.sslContext; } } diff --git a/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java b/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java index 5280550c..74a17bed 100644 --- a/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java +++ b/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java @@ -21,6 +21,7 @@ */ package com.influxdb.v3.client.internal; +import java.lang.reflect.InvocationTargetException; import java.net.URI; import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; @@ -36,14 +37,24 @@ import java.util.stream.StreamSupport; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import javax.net.ssl.SSLException; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import io.grpc.Metadata; +import io.grpc.netty.GrpcSslContexts; +import io.grpc.netty.NettyChannelBuilder; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.ServerChannel; +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.SslContextBuilder; +import io.netty.handler.ssl.util.InsecureTrustManagerFactory; import org.apache.arrow.flight.FlightClient; +import org.apache.arrow.flight.FlightGrpcUtils; import org.apache.arrow.flight.FlightStream; import org.apache.arrow.flight.HeaderCallOption; import org.apache.arrow.flight.Location; +import org.apache.arrow.flight.LocationSchemes; import org.apache.arrow.flight.Ticket; import org.apache.arrow.flight.grpc.MetadataAdapter; import org.apache.arrow.memory.RootAllocator; @@ -83,8 +94,6 @@ final class FlightSqlClient implements AutoCloseable { defaultHeaders.putAll(config.getHeaders()); } - Package mainPackage = RestClient.class.getPackage(); - this.client = (client != null) ? client : createFlightClient(config); } @@ -130,11 +139,54 @@ public void close() throws Exception { private FlightClient createFlightClient(@Nonnull final ClientConfig config) { Location location = createLocation(config); - return FlightClient.builder() - .location(location) - .allocator(new RootAllocator(Long.MAX_VALUE)) - .verifyServer(!config.getDisableServerCertificateValidation()) - .build(); + final NettyChannelBuilder nettyChannelBuilder = NettyChannelBuilder.forTarget(location.getUri().getHost()); + var validSchemas = List.of( + LocationSchemes.GRPC, + LocationSchemes.GRPC_INSECURE, + LocationSchemes.GRPC_TLS, + LocationSchemes.GRPC_DOMAIN_SOCKET + ); + if (!validSchemas.contains(location.getUri().getScheme())) { + throw new IllegalArgumentException( + "Scheme is not supported: " + location.getUri().getScheme()); + } + + if (location.getUri().getScheme().equals(LocationSchemes.GRPC_DOMAIN_SOCKET)) { + setChannelTypeAndEventLoop(nettyChannelBuilder); + } + + if (LocationSchemes.GRPC_TLS.equals(location.getUri().getScheme())) { + nettyChannelBuilder.useTransportSecurity(); + + SslContextBuilder sslContextBuilder; + SslContext sslContext; + if (config.getGrpcSslContext() != null) { + sslContext = config.getGrpcSslContext(); + nettyChannelBuilder.sslContext(sslContext); + } else { + sslContextBuilder = GrpcSslContexts.forClient(); + if (config.getDisableServerCertificateValidation()) { + sslContextBuilder.trustManager(InsecureTrustManagerFactory.INSTANCE); + } + try { + nettyChannelBuilder.sslContext(sslContextBuilder.build()); + } catch (SSLException e) { + throw new RuntimeException(e); + } + } + } else { + nettyChannelBuilder.usePlaintext(); + } + + if (config.getQueryApiProxy() != null) { + nettyChannelBuilder.proxyDetector(config.getQueryApiProxy()); + } + + nettyChannelBuilder.maxTraceEvents(0) + .maxInboundMessageSize(Integer.MAX_VALUE) + .maxInboundMetadataSize(Integer.MAX_VALUE); + + return FlightGrpcUtils.createFlightClient(new RootAllocator(Long.MAX_VALUE), nettyChannelBuilder.build()); } @Nonnull @@ -166,6 +218,42 @@ private HeaderCallOption metadataHeader(@Nonnull final Map reque return new HeaderCallOption(metadata); } + private void setChannelTypeAndEventLoop(@Nonnull final NettyChannelBuilder nettyChannelBuilder) { + // The implementation is platform-specific, so we have to find the classes at runtime + try { + try { + // Linux + nettyChannelBuilder.channelType( + Class.forName("io.netty.channel.epoll.EpollDomainSocketChannel") + .asSubclass(ServerChannel.class)); + final EventLoopGroup elg = + Class.forName("io.netty.channel.epoll.EpollEventLoopGroup") + .asSubclass(EventLoopGroup.class) + .getDeclaredConstructor() + .newInstance(); + nettyChannelBuilder.eventLoopGroup(elg); + } catch (ClassNotFoundException e) { + // BSD + nettyChannelBuilder.channelType( + Class.forName("io.netty.channel.kqueue.KQueueDomainSocketChannel") + .asSubclass(ServerChannel.class)); + final EventLoopGroup elg = + Class.forName("io.netty.channel.kqueue.KQueueEventLoopGroup") + .asSubclass(EventLoopGroup.class) + .getDeclaredConstructor() + .newInstance(); + nettyChannelBuilder.eventLoopGroup(elg); + } + } catch (ClassNotFoundException + | InstantiationException + | IllegalAccessException + | NoSuchMethodException + | InvocationTargetException e) { + throw new UnsupportedOperationException( + "Could not find suitable Netty native transport implementation for domain socket address."); + } + } + private static final class FlightSqlIterator implements Iterator, AutoCloseable { private final List autoCloseable = new ArrayList<>(); diff --git a/src/main/java/com/influxdb/v3/client/internal/RestClient.java b/src/main/java/com/influxdb/v3/client/internal/RestClient.java index 89607807..87053306 100644 --- a/src/main/java/com/influxdb/v3/client/internal/RestClient.java +++ b/src/main/java/com/influxdb/v3/client/internal/RestClient.java @@ -107,10 +107,15 @@ public void checkServerTrusted( if (baseUrl.startsWith("https")) { try { - if (config.getDisableServerCertificateValidation()) { - SSLContext sslContext = SSLContext.getInstance("TLS"); + SSLContext sslContext; + sslContext = SSLContext.getInstance("TLS"); + SSLContext customeSslContext = config.getSslContext(); + if (customeSslContext == null && config.getDisableServerCertificateValidation()) { sslContext.init(null, TRUST_ALL_CERTS, new SecureRandom()); builder.sslContext(sslContext); + } else { + sslContext.init(null, null, new SecureRandom()); + builder.sslContext(customeSslContext != null ? customeSslContext : sslContext); } } catch (Exception e) { throw new RuntimeException(e); diff --git a/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java b/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java index f1e868a2..ce5d0486 100644 --- a/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java +++ b/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java @@ -22,21 +22,91 @@ package com.influxdb.v3.client; import java.math.BigInteger; +import java.net.InetSocketAddress; +import java.net.ProxySelector; +import java.net.URI; +import java.security.NoSuchAlgorithmException; import java.time.Instant; import java.util.Map; import java.util.Properties; import java.util.UUID; import java.util.stream.Stream; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLException; +import io.grpc.HttpConnectProxiedSocketAddress; +import io.grpc.ProxyDetector; +import io.netty.handler.ssl.SslContext; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; +import com.influxdb.v3.client.config.ClientConfig; import com.influxdb.v3.client.write.WriteOptions; import com.influxdb.v3.client.write.WritePrecision; public class InfluxDBClientTest { + @Test + void testCustomSslContext() throws NoSuchAlgorithmException, SSLException { + // Test for java.net SslContext + ClientConfig.Builder builder = new ClientConfig.Builder(); + ClientConfig clientConfig = builder.sslContext(null).build(); + Assertions.assertThat(clientConfig.getSslContext()).isNull(); + + clientConfig = builder.sslContext(SSLContext.getDefault()).build(); + Assertions.assertThat(clientConfig.getSslContext()).isNotNull(); + + // Test for grpc SslContext + ClientConfig.Builder builder1 = new ClientConfig.Builder(); + ClientConfig clientConfig1 = builder1.grpcSslContext(null).build(); + Assertions.assertThat(clientConfig1.getGrpcSslContext()).isNull(); + + clientConfig1 = builder1.grpcSslContext(SslContext.newClientContext()).build(); + Assertions.assertThat(clientConfig1.getGrpcSslContext()).isNotNull(); + } + + @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_URL", matches = ".*") + @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_TOKEN", matches = ".*") + @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_DATABASE", matches = ".*") + @Test + void testQueryProxy() throws Exception { + URI queryProxyUri = new URI("http://127.0.0.1:10000"); + URI uri = new URI(System.getenv("TESTING_INFLUXDB_URL")); + + ProxyDetector proxyDetector = (targetServerAddress) -> { + InetSocketAddress targetAddress = (InetSocketAddress) targetServerAddress; + if (uri.getHost().equals(targetAddress.getHostString())) { + return HttpConnectProxiedSocketAddress.newBuilder() + .setProxyAddress(new InetSocketAddress(queryProxyUri.getHost(), queryProxyUri.getPort())) + .setTargetAddress(targetAddress) + .build(); + } + return null; + }; + ProxySelector proxy = ProxySelector.of(new InetSocketAddress(queryProxyUri.getHost(), queryProxyUri.getPort())); + ClientConfig clientConfig = new ClientConfig.Builder() + .host(uri.toString()) + .token(System.getenv("TESTING_INFLUXDB_TOKEN").toCharArray()) + .database(System.getenv("TESTING_INFLUXDB_DATABASE")) + .proxy(proxy) + .queryApiProxy(proxyDetector) + .build(); + + InfluxDBClient influxDBClient = InfluxDBClient.getInstance(clientConfig); + influxDBClient.writePoint( + Point.measurement("test1") + .setField("field", "field1") + ); + + try (Stream stream = influxDBClient.queryPoints("SELECT * FROM test1")) { + stream.findFirst() + .ifPresent(pointValues -> { + Assertions.assertThat(pointValues.getField("field")).isEqualTo("field1"); + }); + } + } + @Test void requiredHost() { @@ -102,10 +172,10 @@ void withDefaultTags() throws Exception { Map defaultTags = Map.of("unit", "U2", "model", "M1"); try (InfluxDBClient client = InfluxDBClient.getInstance( - "http://localhost:8086", - "MY-TOKEN".toCharArray(), - "MY-DATABASE", - defaultTags)) { + "http://localhost:8086", + "MY-TOKEN".toCharArray(), + "MY-DATABASE", + defaultTags)) { Assertions.assertThat(client).isNotNull(); } } From 7a4612512874d581ff73b2c03cdac06ac26635a4 Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Tue, 11 Mar 2025 19:06:52 +0700 Subject: [PATCH 02/52] chore: update license --- examples/docker-compose.yml | 22 +++++++++++++++++++ examples/envoy.yaml | 22 +++++++++++++++++++ .../java/com/influxdb/v3/ProxyExample.java | 21 ++++++++++++++++++ 3 files changed, 65 insertions(+) diff --git a/examples/docker-compose.yml b/examples/docker-compose.yml index 1ffa7ae0..b820d1bb 100644 --- a/examples/docker-compose.yml +++ b/examples/docker-compose.yml @@ -1,3 +1,25 @@ +# +# The MIT License +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# + version: "3" services: diff --git a/examples/envoy.yaml b/examples/envoy.yaml index 4f627cfa..ab539c73 100644 --- a/examples/envoy.yaml +++ b/examples/envoy.yaml @@ -1,3 +1,25 @@ +# +# The MIT License +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# + static_resources: listeners: - name: listener_0 diff --git a/examples/src/main/java/com/influxdb/v3/ProxyExample.java b/examples/src/main/java/com/influxdb/v3/ProxyExample.java index c906229b..d2ef59e9 100644 --- a/examples/src/main/java/com/influxdb/v3/ProxyExample.java +++ b/examples/src/main/java/com/influxdb/v3/ProxyExample.java @@ -1,3 +1,24 @@ +/* + * The MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package com.influxdb.v3; import java.net.InetSocketAddress; From 6a11583dedb1b7d36e5c9d09b3ebbc30c2c34530 Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Wed, 12 Mar 2025 17:50:20 +0700 Subject: [PATCH 03/52] refactor: remove test case --- .../v3/client/InfluxDBClientTest.java | 41 ------------------- 1 file changed, 41 deletions(-) diff --git a/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java b/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java index ce5d0486..b855e360 100644 --- a/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java +++ b/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java @@ -66,47 +66,6 @@ void testCustomSslContext() throws NoSuchAlgorithmException, SSLException { Assertions.assertThat(clientConfig1.getGrpcSslContext()).isNotNull(); } - @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_URL", matches = ".*") - @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_TOKEN", matches = ".*") - @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_DATABASE", matches = ".*") - @Test - void testQueryProxy() throws Exception { - URI queryProxyUri = new URI("http://127.0.0.1:10000"); - URI uri = new URI(System.getenv("TESTING_INFLUXDB_URL")); - - ProxyDetector proxyDetector = (targetServerAddress) -> { - InetSocketAddress targetAddress = (InetSocketAddress) targetServerAddress; - if (uri.getHost().equals(targetAddress.getHostString())) { - return HttpConnectProxiedSocketAddress.newBuilder() - .setProxyAddress(new InetSocketAddress(queryProxyUri.getHost(), queryProxyUri.getPort())) - .setTargetAddress(targetAddress) - .build(); - } - return null; - }; - ProxySelector proxy = ProxySelector.of(new InetSocketAddress(queryProxyUri.getHost(), queryProxyUri.getPort())); - ClientConfig clientConfig = new ClientConfig.Builder() - .host(uri.toString()) - .token(System.getenv("TESTING_INFLUXDB_TOKEN").toCharArray()) - .database(System.getenv("TESTING_INFLUXDB_DATABASE")) - .proxy(proxy) - .queryApiProxy(proxyDetector) - .build(); - - InfluxDBClient influxDBClient = InfluxDBClient.getInstance(clientConfig); - influxDBClient.writePoint( - Point.measurement("test1") - .setField("field", "field1") - ); - - try (Stream stream = influxDBClient.queryPoints("SELECT * FROM test1")) { - stream.findFirst() - .ifPresent(pointValues -> { - Assertions.assertThat(pointValues.getField("field")).isEqualTo("field1"); - }); - } - } - @Test void requiredHost() { From ec530c425432862c728eac75685f0dd29213932f Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Wed, 12 Mar 2025 17:53:38 +0700 Subject: [PATCH 04/52] fix: linter --- src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java b/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java index b855e360..1b7dddc7 100644 --- a/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java +++ b/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java @@ -22,9 +22,6 @@ package com.influxdb.v3.client; import java.math.BigInteger; -import java.net.InetSocketAddress; -import java.net.ProxySelector; -import java.net.URI; import java.security.NoSuchAlgorithmException; import java.time.Instant; import java.util.Map; @@ -34,8 +31,6 @@ import javax.net.ssl.SSLContext; import javax.net.ssl.SSLException; -import io.grpc.HttpConnectProxiedSocketAddress; -import io.grpc.ProxyDetector; import io.netty.handler.ssl.SslContext; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; From 46979b5ab2c1899e429b910d361cc1b7fc6ff854 Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Fri, 14 Mar 2025 19:30:40 +0700 Subject: [PATCH 05/52] refactor: proxy and ssl --- .../v3/client/config/ClientConfig.java | 131 +++++------------- .../v3/client/internal/FlightSqlClient.java | 55 +++++--- .../v3/client/internal/RestClient.java | 59 ++++++-- .../v3/client/InfluxDBClientTest.java | 54 +++++--- .../v3/client/internal/RestClientTest.java | 4 +- 5 files changed, 164 insertions(+), 139 deletions(-) diff --git a/src/main/java/com/influxdb/v3/client/config/ClientConfig.java b/src/main/java/com/influxdb/v3/client/config/ClientConfig.java index 91af357b..39ed7418 100644 --- a/src/main/java/com/influxdb/v3/client/config/ClientConfig.java +++ b/src/main/java/com/influxdb/v3/client/config/ClientConfig.java @@ -23,7 +23,6 @@ import java.net.Authenticator; import java.net.MalformedURLException; -import java.net.ProxySelector; import java.net.URL; import java.time.Duration; import java.util.Arrays; @@ -35,10 +34,6 @@ import java.util.function.BiFunction; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import javax.net.ssl.SSLContext; - -import io.grpc.ProxyDetector; -import io.netty.handler.ssl.SslContext; import com.influxdb.v3.client.write.WritePrecision; @@ -61,16 +56,17 @@ *
  • disableServerCertificateValidation - * disable server certificate validation for HTTPS connections *
  • - *
  • proxy - HTTP proxy selector
  • + *
  • proxyUrl - Proxy url for query api and write api
  • *
  • queryApiProxy - HTTP query detector
  • *
  • authenticator - HTTP proxy authenticator
  • *
  • headers - headers to be added to requests
  • + *
  • certificateFilePath - Path to the stored certificates file
  • * *

    * If you want to create a client with custom configuration, you can use following code: *

      * ClientConfig config = new ClientConfig.Builder()
    - *     .host("https://us-east-1-1.aws.cloud2.influxdata.com")
    + *     .host("https://us-east-1-1.aws.cloud2.influxdata.com")
      *     .token("my-token".toCharArray())
      *     .database("my-database")
      *     .writePrecision(WritePrecision.S)
    @@ -89,7 +85,8 @@
      * Immutable class.
      */
     public final class ClientConfig {
    -
    +    //todo check if main use proxySelector for backward compality
    +    //todo check comments
         private final String host;
         private final char[] token;
         private final String authScheme;
    @@ -101,12 +98,10 @@ public final class ClientConfig {
         private final Duration timeout;
         private final Boolean allowHttpRedirects;
         private final Boolean disableServerCertificateValidation;
    -    private final ProxySelector proxy;
    -    private final ProxyDetector queryApiProxy;
    +    private final String proxyUrl;
         private final Authenticator authenticator;
         private final Map headers;
    -    private final SslContext grpcSslContext;
    -    private final SSLContext sslContext;
    +    private final String certificateFilePath;
     
         /**
          * Gets URL of the InfluxDB server.
    @@ -218,23 +213,23 @@ public Boolean getDisableServerCertificateValidation() {
         }
     
         /**
    -     * Gets the proxy.
    +     * Gets the proxy url.
          *
    -     * @return the proxy, may be null
    +     * @return the proxy url, may be null
          */
         @Nullable
    -    public ProxySelector getProxy() {
    -        return proxy;
    +    public String getProxyUrl() {
    +        return proxyUrl;
         }
     
         /**
    -     * Gets the proxy for query api.
    +     * Gets certificates file path
          *
    -     * @return the proxy, may be null
    +     * @return the certificates file path, may be null
          */
         @Nullable
    -    public ProxyDetector getQueryApiProxy() {
    -        return queryApiProxy;
    +    public String certificateFilePath() {
    +        return certificateFilePath;
         }
     
         /**
    @@ -257,26 +252,6 @@ public Map getHeaders() {
             return headers;
         }
     
    -    /**
    -     * Gets SslContext object from grpc.
    -     *
    -     * @return the SslContext object
    -     */
    -    @Nullable
    -    public SslContext getGrpcSslContext() {
    -        return grpcSslContext;
    -    }
    -
    -    /**
    -     * Gets SSLContext object.
    -     *
    -     * @return the SSLContext object
    -     */
    -    @Nullable
    -    public SSLContext getSslContext() {
    -        return sslContext;
    -    }
    -
         /**
          * Validates the configuration properties.
          */
    @@ -306,21 +281,19 @@ public boolean equals(final Object o) {
                     && Objects.equals(timeout, that.timeout)
                     && Objects.equals(allowHttpRedirects, that.allowHttpRedirects)
                     && Objects.equals(disableServerCertificateValidation, that.disableServerCertificateValidation)
    -                && Objects.equals(proxy, that.proxy)
    -                && Objects.equals(queryApiProxy, that.queryApiProxy)
    +                && Objects.equals(proxyUrl, that.proxyUrl)
                     && Objects.equals(authenticator, that.authenticator)
                     && Objects.equals(headers, that.headers)
    -                && Objects.equals(grpcSslContext, that.grpcSslContext)
    -                && Objects.equals(sslContext, that.sslContext);
    +                && Objects.equals(certificateFilePath, that.certificateFilePath);
         }
     
         @Override
         public int hashCode() {
             return Objects.hash(host, Arrays.hashCode(token), authScheme, organization,
    -          database, writePrecision, gzipThreshold,
    -          timeout, allowHttpRedirects, disableServerCertificateValidation,
    -          proxy, queryApiProxy, authenticator, headers,
    -          defaultTags, grpcSslContext, sslContext);
    +                database, writePrecision, gzipThreshold,
    +                timeout, allowHttpRedirects, disableServerCertificateValidation,
    +                proxyUrl, authenticator, headers,
    +                defaultTags, certificateFilePath);
         }
     
         @Override
    @@ -334,13 +307,11 @@ public String toString() {
                     .add("timeout=" + timeout)
                     .add("allowHttpRedirects=" + allowHttpRedirects)
                     .add("disableServerCertificateValidation=" + disableServerCertificateValidation)
    -                .add("proxy=" + proxy)
    -                .add("queryApiProxy=" + queryApiProxy)
    +                .add("proxy=" + proxyUrl)
                     .add("authenticator=" + authenticator)
                     .add("headers=" + headers)
                     .add("defaultTags=" + defaultTags)
    -                .add("grpcSslContext=" + grpcSslContext)
    -                .add("sslContext=" + sslContext)
    +                .add("certificateFilePath=" + certificateFilePath)
                     .toString();
         }
     
    @@ -361,12 +332,10 @@ public static final class Builder {
             private Duration timeout;
             private Boolean allowHttpRedirects;
             private Boolean disableServerCertificateValidation;
    -        private ProxySelector proxy;
    -        private ProxyDetector queryApiProxy;
    +        private String proxyUrl;
             private Authenticator authenticator;
             private Map headers;
    -        private SslContext grpcSslContext;
    -        private SSLContext sslContext;
    +        private String certificateFilePath;
     
             /**
              * Sets the URL of the InfluxDB server.
    @@ -515,28 +484,15 @@ public Builder disableServerCertificateValidation(@Nullable final Boolean disabl
             }
     
             /**
    -         * Sets the proxy selector. Default is 'null'.
    -         *
    -         * @param proxy Proxy selector.
    -         * @return this
    -         */
    -        @Nonnull
    -        public Builder proxy(@Nullable final ProxySelector proxy) {
    -
    -            this.proxy = proxy;
    -            return this;
    -        }
    -
    -        /**
    -         * Sets the proxy detector for query api. Default is 'null'.
    +         * Sets the proxy url. Default is 'null'.
              *
    -         * @param proxy Proxy detector.
    +         * @param proxyUrl Proxy url.
              * @return this
              */
             @Nonnull
    -        public Builder queryApiProxy(@Nullable final ProxyDetector proxy) {
    +        public Builder proxyUrl(@Nullable final String proxyUrl) {
     
    -            this.queryApiProxy = proxy;
    +            this.proxyUrl = proxyUrl;
                 return this;
             }
     
    @@ -558,7 +514,7 @@ public Builder authenticator(@Nullable final Authenticator authenticator) {
              * such as tracing headers. To add custom headers use following code:
              * 
              * ClientConfig config = new ClientConfig.Builder()
    -         *     .host("https://us-east-1-1.aws.cloud2.influxdata.com")
    +         *     .host("https://us-east-1-1.aws.cloud2.influxdata.com")
              *     .token("my-token".toCharArray())
              *     .database("my-database")
              *     .headers(Map.of("X-Tracing-Id", "123"))
    @@ -584,28 +540,15 @@ public Builder headers(@Nullable final Map headers) {
             }
     
             /**
    -         * Sets SslContext for grpc client. Default is 'null'.
    -         *
    -         * @param grpcSslContext The SSLContext
    -         * @return this
    -         */
    -        @Nonnull
    -        public Builder grpcSslContext(@Nullable final SslContext grpcSslContext) {
    -
    -            this.grpcSslContext = grpcSslContext;
    -            return this;
    -        }
    -
    -        /**
    -         * Sets SSLContext for rest client. Default is 'null'.
    +         * Sets certificate file path. Default is 'null'.
              *
    -         * @param sslContext The SSLContext
    +         * @param certificateFilePath The certificate file path
              * @return this
              */
             @Nonnull
    -        public Builder sslContext(@Nullable final SSLContext sslContext) {
    +        public Builder certificateFilePath(@Nullable final String certificateFilePath) {
     
    -            this.sslContext = sslContext;
    +            this.certificateFilePath = certificateFilePath;
                 return this;
             }
     
    @@ -743,11 +686,9 @@ private ClientConfig(@Nonnull final Builder builder) {
             allowHttpRedirects = builder.allowHttpRedirects != null ? builder.allowHttpRedirects : false;
             disableServerCertificateValidation = builder.disableServerCertificateValidation != null
                     ? builder.disableServerCertificateValidation : false;
    -        proxy = builder.proxy;
    -        queryApiProxy = builder.queryApiProxy;
    +        proxyUrl = builder.proxyUrl;
             authenticator = builder.authenticator;
             headers = builder.headers;
    -        grpcSslContext = builder.grpcSslContext;
    -        sslContext = builder.sslContext;
    +        certificateFilePath = builder.certificateFilePath;
         }
     }
    diff --git a/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java b/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java
    index 74a17bed..93c7821c 100644
    --- a/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java
    +++ b/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java
    @@ -21,7 +21,10 @@
      */
     package com.influxdb.v3.client.internal;
     
    +import java.io.FileInputStream;
    +import java.io.IOException;
     import java.lang.reflect.InvocationTargetException;
    +import java.net.InetSocketAddress;
     import java.net.URI;
     import java.net.URISyntaxException;
     import java.nio.charset.StandardCharsets;
    @@ -41,12 +44,13 @@
     
     import com.fasterxml.jackson.core.JsonProcessingException;
     import com.fasterxml.jackson.databind.ObjectMapper;
    +import io.grpc.HttpConnectProxiedSocketAddress;
     import io.grpc.Metadata;
    +import io.grpc.ProxyDetector;
     import io.grpc.netty.GrpcSslContexts;
     import io.grpc.netty.NettyChannelBuilder;
     import io.netty.channel.EventLoopGroup;
     import io.netty.channel.ServerChannel;
    -import io.netty.handler.ssl.SslContext;
     import io.netty.handler.ssl.SslContextBuilder;
     import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
     import org.apache.arrow.flight.FlightClient;
    @@ -159,27 +163,32 @@ private FlightClient createFlightClient(@Nonnull final ClientConfig config) {
                 nettyChannelBuilder.useTransportSecurity();
     
                 SslContextBuilder sslContextBuilder;
    -            SslContext sslContext;
    -            if (config.getGrpcSslContext() != null) {
    -                sslContext = config.getGrpcSslContext();
    -                nettyChannelBuilder.sslContext(sslContext);
    -            } else {
    -                sslContextBuilder = GrpcSslContexts.forClient();
    -                if (config.getDisableServerCertificateValidation()) {
    -                    sslContextBuilder.trustManager(InsecureTrustManagerFactory.INSTANCE);
    -                }
    -                try {
    -                    nettyChannelBuilder.sslContext(sslContextBuilder.build());
    -                } catch (SSLException e) {
    -                    throw new RuntimeException(e);
    +            sslContextBuilder = GrpcSslContexts.forClient();
    +            if (!config.getDisableServerCertificateValidation()) {
    +                if (config.certificateFilePath() != null) {
    +                    try (FileInputStream fileInputStream = new FileInputStream(config.certificateFilePath())) {
    +                        sslContextBuilder.trustManager(fileInputStream);
    +                    } catch (IOException e) {
    +                        throw new RuntimeException(e);
    +                    }
                     }
    +            } else {
    +                sslContextBuilder.trustManager(InsecureTrustManagerFactory.INSTANCE);
                 }
    +
    +            try {
    +                nettyChannelBuilder.sslContext(sslContextBuilder.build());
    +            } catch (SSLException e) {
    +                throw new RuntimeException(e);
    +            }
    +
             } else {
                 nettyChannelBuilder.usePlaintext();
             }
     
    -        if (config.getQueryApiProxy() != null) {
    -            nettyChannelBuilder.proxyDetector(config.getQueryApiProxy());
    +        if (config.getProxyUrl() != null) {
    +            ProxyDetector proxyDetector = createProxyDetector(config.getProxyUrl());
    +            nettyChannelBuilder.proxyDetector(proxyDetector);
             }
     
             nettyChannelBuilder.maxTraceEvents(0)
    @@ -254,6 +263,20 @@ private void setChannelTypeAndEventLoop(@Nonnull final NettyChannelBuilder netty
             }
         }
     
    +    private ProxyDetector createProxyDetector(@Nonnull String url) {
    +        URI proxyUri = URI.create(url);
    +        return (targetServerAddress) -> {
    +            InetSocketAddress targetAddress = (InetSocketAddress) targetServerAddress;
    +            if (proxyUri.getHost().equals(targetAddress.getHostString())) {
    +                return HttpConnectProxiedSocketAddress.newBuilder()
    +                        .setProxyAddress(new InetSocketAddress(proxyUri.getHost(), proxyUri.getPort()))
    +                        .setTargetAddress(targetAddress)
    +                        .build();
    +            }
    +            return null;
    +        };
    +    }
    +
         private static final class FlightSqlIterator implements Iterator, AutoCloseable {
     
             private final List autoCloseable = new ArrayList<>();
    diff --git a/src/main/java/com/influxdb/v3/client/internal/RestClient.java b/src/main/java/com/influxdb/v3/client/internal/RestClient.java
    index 87053306..8bfdaf7d 100644
    --- a/src/main/java/com/influxdb/v3/client/internal/RestClient.java
    +++ b/src/main/java/com/influxdb/v3/client/internal/RestClient.java
    @@ -21,11 +21,19 @@
      */
     package com.influxdb.v3.client.internal;
     
    +import java.io.FileInputStream;
    +import java.net.InetSocketAddress;
    +import java.net.ProxySelector;
    +import java.net.URI;
     import java.net.URISyntaxException;
     import java.net.http.HttpClient;
     import java.net.http.HttpRequest;
     import java.net.http.HttpResponse;
    +import java.security.KeyStore;
     import java.security.SecureRandom;
    +import java.security.cert.Certificate;
    +import java.security.cert.CertificateFactory;
    +import java.util.ArrayList;
     import java.util.List;
     import java.util.Map;
     import java.util.stream.Stream;
    @@ -33,6 +41,7 @@
     import javax.annotation.Nullable;
     import javax.net.ssl.SSLContext;
     import javax.net.ssl.TrustManager;
    +import javax.net.ssl.TrustManagerFactory;
     import javax.net.ssl.X509TrustManager;
     
     import com.fasterxml.jackson.core.JsonProcessingException;
    @@ -98,8 +107,10 @@ public void checkServerTrusted(
             this.defaultHeaders = config.getHeaders() != null ? Map.copyOf(config.getHeaders()) : null;
     
             // proxy
    -        if (config.getProxy() != null) {
    -            builder.proxy(config.getProxy());
    +        if (config.getProxyUrl() != null) {
    +            URI uri = URI.create(config.getProxyUrl());
    +            ProxySelector proxy = ProxySelector.of(new InetSocketAddress(uri.getHost(), uri.getPort()));
    +            builder.proxy(proxy);
                 if (config.getAuthenticator() != null) {
                     builder.authenticator(config.getAuthenticator());
                 }
    @@ -107,15 +118,15 @@ public void checkServerTrusted(
     
             if (baseUrl.startsWith("https")) {
                 try {
    -                SSLContext sslContext;
    -                sslContext = SSLContext.getInstance("TLS");
    -                SSLContext customeSslContext = config.getSslContext();
    -                if (customeSslContext == null && config.getDisableServerCertificateValidation()) {
    +                SSLContext sslContext = SSLContext.getInstance("TLS");
    +                if (config.getDisableServerCertificateValidation()) {
                         sslContext.init(null, TRUST_ALL_CERTS, new SecureRandom());
                         builder.sslContext(sslContext);
    -                } else {
    -                    sslContext.init(null, null, new SecureRandom());
    -                    builder.sslContext(customeSslContext != null ? customeSslContext : sslContext);
    +                }
    +
    +                if (config.certificateFilePath() != null && !config.getDisableServerCertificateValidation()) {
    +                    X509TrustManager x509TrustManager = getX509TrustManagerFromFile(config.certificateFilePath());
    +                    sslContext.init(null, new X509TrustManager[]{x509TrustManager}, new SecureRandom());
                     }
                 } catch (Exception e) {
                     throw new RuntimeException(e);
    @@ -222,6 +233,36 @@ void request(@Nonnull final String path,
             }
         }
     
    +    private X509TrustManager getX509TrustManagerFromFile(@Nonnull String filePath) {
    +        try {
    +            KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
    +            trustStore.load(null);
    +
    +            FileInputStream fis = new FileInputStream(filePath);
    +            List certificates = new ArrayList(
    +                    CertificateFactory.getInstance("X.509")
    +                            .generateCertificates(fis)
    +            );
    +
    +            for (int i = 0; i < certificates.size(); i++) {
    +                Certificate cert = certificates.get(i);
    +                trustStore.setCertificateEntry("alias" + i, cert);
    +            }
    +
    +            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    +            trustManagerFactory.init(trustStore);
    +            X509TrustManager x509TrustManager = null;
    +            for (TrustManager trustManager : trustManagerFactory.getTrustManagers()) {
    +                if (trustManager instanceof X509TrustManager) {
    +                    x509TrustManager = (X509TrustManager) trustManager;
    +                }
    +            }
    +            return x509TrustManager;
    +        } catch (Exception e) {
    +            throw new RuntimeException(e);
    +        }
    +    }
    +
         @Override
         public void close() {
         }
    diff --git a/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java b/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java
    index 1b7dddc7..af6f718f 100644
    --- a/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java
    +++ b/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java
    @@ -28,10 +28,8 @@
     import java.util.Properties;
     import java.util.UUID;
     import java.util.stream.Stream;
    -import javax.net.ssl.SSLContext;
     import javax.net.ssl.SSLException;
     
    -import io.netty.handler.ssl.SslContext;
     import org.assertj.core.api.Assertions;
     import org.junit.jupiter.api.Test;
     import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
    @@ -42,23 +40,45 @@
     
     public class InfluxDBClientTest {
     
    +    @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_URL", matches = ".*")
    +    @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_TOKEN", matches = ".*")
    +    @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_DATABASE", matches = ".*")
         @Test
    -    void testCustomSslContext() throws NoSuchAlgorithmException, SSLException {
    -        // Test for java.net SslContext
    -        ClientConfig.Builder builder = new ClientConfig.Builder();
    -        ClientConfig clientConfig = builder.sslContext(null).build();
    -        Assertions.assertThat(clientConfig.getSslContext()).isNull();
    -
    -        clientConfig = builder.sslContext(SSLContext.getDefault()).build();
    -        Assertions.assertThat(clientConfig.getSslContext()).isNotNull();
    -
    -        // Test for grpc SslContext
    -        ClientConfig.Builder builder1 = new ClientConfig.Builder();
    -        ClientConfig clientConfig1 = builder1.grpcSslContext(null).build();
    -        Assertions.assertThat(clientConfig1.getGrpcSslContext()).isNull();
    +    void testQueryProxy() {
    +        String proxyUrl = "http://127.0.0.1:10000";
    +
    +        //todo remove
    +        //todo add test for proxy and certificates path
    +//        String certificateFilePath = "/Users/home/Downloads/influxdb3-java/src/test/java/com/influxdb/v3/client/valid-certificates.pem";
    +
    +        ClientConfig clientConfig = new ClientConfig.Builder()
    +                .host(System.getenv("TESTING_INFLUXDB_URL"))
    +                .token(System.getenv("TESTING_INFLUXDB_TOKEN").toCharArray())
    +                .database(System.getenv("TESTING_INFLUXDB_DATABASE"))
    +                .proxyUrl(proxyUrl)
    +//                .certificateFilePath(certificateFilePath)
    +                .build();
    +
    +        InfluxDBClient influxDBClient = InfluxDBClient.getInstance(clientConfig);
    +        influxDBClient.writePoint(
    +                Point.measurement("test1")
    +                        .setField("field", "field1")
    +        );
    +
    +        try (Stream stream = influxDBClient.queryPoints("SELECT * FROM test1")) {
    +            stream.findFirst()
    +                    .ifPresent(pointValues -> {
    +                        Assertions.assertThat(pointValues.getField("field")).isEqualTo("field1");
    +                    });
    +        }
    +    }
     
    -        clientConfig1 = builder1.grpcSslContext(SslContext.newClientContext()).build();
    -        Assertions.assertThat(clientConfig1.getGrpcSslContext()).isNotNull();
    +    @Test
    +    void withProxyUrl() throws NoSuchAlgorithmException, SSLException {
    +        ClientConfig.Builder builder = new ClientConfig.Builder();
    +        builder.proxyUrl("http://127.0.0.1:10000");
    +        ClientConfig clientConfig = builder.build();
    +        Assertions.assertThat(clientConfig.getProxyUrl()).isEqualTo("http://127.0.0.1:10000");
         }
     
         @Test
    diff --git a/src/test/java/com/influxdb/v3/client/internal/RestClientTest.java b/src/test/java/com/influxdb/v3/client/internal/RestClientTest.java
    index bd53a3ce..19566cde 100644
    --- a/src/test/java/com/influxdb/v3/client/internal/RestClientTest.java
    +++ b/src/test/java/com/influxdb/v3/client/internal/RestClientTest.java
    @@ -279,7 +279,7 @@ public void proxy() throws InterruptedException {
     
             restClient = new RestClient(new ClientConfig.Builder()
                     .host("http://foo.com:8086")
    -                .proxy(ProxySelector.of((InetSocketAddress) mockServer.toProxyAddress().address()))
    +                .proxyUrl(String.format("http://%s:%s", mockServer.getHostName(), mockServer.getPort()))
                     .build());
     
             restClient.request("ping", HttpMethod.GET, null, null, null);
    @@ -298,7 +298,7 @@ public void proxyWithAuthentication() throws InterruptedException {
     
             restClient = new RestClient(new ClientConfig.Builder()
                     .host("http://foo.com:8086")
    -                .proxy(ProxySelector.of((InetSocketAddress) mockServer.toProxyAddress().address()))
    +                .proxyUrl(String.format("http://%s:%s", mockServer.getHostName(), mockServer.getPort()))
                     .authenticator(new Authenticator() {
                         @Override
                         protected PasswordAuthentication getPasswordAuthentication() {
    
    From 7b167bb8e861b7e9bcf0b2ec392d77fe80866e41 Mon Sep 17 00:00:00 2001
    From: NguyenHoangSon96 
    Date: Mon, 17 Mar 2025 09:15:22 +0700
    Subject: [PATCH 06/52] feat: install envoy circleci
    
    ---
     .circleci/config.yml | 8 ++++++++
     1 file changed, 8 insertions(+)
    
    diff --git a/.circleci/config.yml b/.circleci/config.yml
    index 3dca04ff..92e850d5 100644
    --- a/.circleci/config.yml
    +++ b/.circleci/config.yml
    @@ -18,6 +18,14 @@ jobs:
               keys:
                 - &cache-key maven-cache_v1-<< parameters.maven-image >>-{{ checksum "pom.xml" }}
                 - maven-cache_v3-<< parameters.maven-image >>-
    +      - run:
    +          name: "Run Envoy"
    +          command: |
    +            curl -sL 'https://apt.envoyproxy.io/signing.key | sudo gpg --dearmor -o /etc/apt/keyrings/envoy-keyring.gpg'
    +            sudo apt-get update
    +            sudo apt-get install envoy
    +            echo "helllo"
    +            envoy --version
           - run:
               name: "Running tests"
               command: |
    
    From 5802d901e533d7686c410fd8c477f63e94c4c8c0 Mon Sep 17 00:00:00 2001
    From: NguyenHoangSon96 
    Date: Mon, 17 Mar 2025 15:57:32 +0700
    Subject: [PATCH 07/52] feat: install envoy circleci
    
    ---
     .circleci/config.yml | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    diff --git a/.circleci/config.yml b/.circleci/config.yml
    index 92e850d5..447b38f1 100644
    --- a/.circleci/config.yml
    +++ b/.circleci/config.yml
    @@ -21,10 +21,10 @@ jobs:
           - run:
               name: "Run Envoy"
               command: |
    -            curl -sL 'https://apt.envoyproxy.io/signing.key | sudo gpg --dearmor -o /etc/apt/keyrings/envoy-keyring.gpg'
    +            wget -O- https://apt.envoyproxy.io/signing.key | sudo gpg --dearmor -o /etc/apt/keyrings/envoy-keyring.gpg
    +            echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/envoy-keyring.gpg] https://apt.envoyproxy.io focal main" | sudo tee /etc/apt/sources.list.d/envoy.list
                 sudo apt-get update
                 sudo apt-get install envoy
    -            echo "helllo"
                 envoy --version
           - run:
               name: "Running tests"
    
    From 91775ed3324f13d2ec920401dd9c6d7953bd2b37 Mon Sep 17 00:00:00 2001
    From: NguyenHoangSon96 
    Date: Mon, 17 Mar 2025 16:18:57 +0700
    Subject: [PATCH 08/52] feat: add envoy.yaml for circleci
    
    ---
     .circleci/config.yml |  2 +-
     .circleci/envoy.yaml | 84 ++++++++++++++++++++++++++++++++++++++++++++
     2 files changed, 85 insertions(+), 1 deletion(-)
     create mode 100644 .circleci/envoy.yaml
    
    diff --git a/.circleci/config.yml b/.circleci/config.yml
    index 447b38f1..6862a72b 100644
    --- a/.circleci/config.yml
    +++ b/.circleci/config.yml
    @@ -25,7 +25,7 @@ jobs:
                 echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/envoy-keyring.gpg] https://apt.envoyproxy.io focal main" | sudo tee /etc/apt/sources.list.d/envoy.list
                 sudo apt-get update
                 sudo apt-get install envoy
    -            envoy --version
    +            envoy -c .circleci/envoy.yaml
           - run:
               name: "Running tests"
               command: |
    diff --git a/.circleci/envoy.yaml b/.circleci/envoy.yaml
    new file mode 100644
    index 00000000..ab539c73
    --- /dev/null
    +++ b/.circleci/envoy.yaml
    @@ -0,0 +1,84 @@
    +#
    +# The MIT License
    +#
    +# Permission is hereby granted, free of charge, to any person obtaining a copy
    +# of this software and associated documentation files (the "Software"), to deal
    +# in the Software without restriction, including without limitation the rights
    +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    +# copies of the Software, and to permit persons to whom the Software is
    +# furnished to do so, subject to the following conditions:
    +#
    +# The above copyright notice and this permission notice shall be included in
    +# all copies or substantial portions of the Software.
    +#
    +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    +# THE SOFTWARE.
    +#
    +
    +static_resources:
    +  listeners:
    +    - name: listener_0
    +      address:
    +        socket_address: { address: 0.0.0.0, port_value: 10000 }
    +      filter_chains:
    +        - filter_chain_match:
    +          filters:
    +            - name: envoy.filters.network.http_connection_manager
    +              typed_config:
    +                "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
    +                stat_prefix: ingress_http
    +                access_log:
    +                  - name: envoy.access_loggers.stdout
    +                    typed_config:
    +                      "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog
    +                http2_protocol_options:
    +                  allow_connect: true
    +                upgrade_configs:
    +                  - upgrade_type: CONNECT
    +                http_filters:
    +                  - name: envoy.filters.http.router
    +                    typed_config:
    +                      "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
    +
    +                route_config:
    +                  name: local_route
    +                  virtual_hosts:
    +                    - name: local_service
    +                      domains: [ "*" ]
    +                      routes:
    +                        - match:
    +                            connect_matcher: { }
    +                          route:
    +                            cluster: influxdb_cluster
    +                            upgrade_configs:
    +                              upgrade_type: CONNECT
    +                              connect_config: { }
    +                        - match:
    +                            prefix: "/"
    +                          route:
    +                            cluster: influxdb_cluster
    +                            prefix_rewrite: "/"
    +                            auto_host_rewrite: true
    +                            timeout: 10s
    +                      cors:
    +                        allow_origin_string_match:
    +                          - prefix: "*"
    +                        allow_methods: GET, PUT, DELETE, POST, OPTIONS
    +  clusters:
    +    - name: influxdb_cluster
    +      connect_timeout: 10s
    +      type: STRICT_DNS
    +      load_assignment:
    +        cluster_name: influxdb_cluster
    +        endpoints:
    +          - lb_endpoints:
    +              - endpoint:
    +                  address:
    +                    socket_address:
    +                      address: "us-east-1-1.aws.cloud2.influxdata.com"
    +                      port_value: 443
    \ No newline at end of file
    
    From 22a0e4107cea4613d2dcd8260f2e6880fa51337e Mon Sep 17 00:00:00 2001
    From: NguyenHoangSon96 
    Date: Mon, 17 Mar 2025 16:27:45 +0700
    Subject: [PATCH 09/52] fix: linter
    
    ---
     .../com/influxdb/v3/client/config/ClientConfig.java    | 10 +++++++---
     .../influxdb/v3/client/internal/FlightSqlClient.java   |  2 +-
     .../com/influxdb/v3/client/internal/RestClient.java    |  2 +-
     .../influxdb/v3/client/internal/RestClientTest.java    |  2 --
     4 files changed, 9 insertions(+), 7 deletions(-)
    
    diff --git a/src/main/java/com/influxdb/v3/client/config/ClientConfig.java b/src/main/java/com/influxdb/v3/client/config/ClientConfig.java
    index 39ed7418..a2df4a6d 100644
    --- a/src/main/java/com/influxdb/v3/client/config/ClientConfig.java
    +++ b/src/main/java/com/influxdb/v3/client/config/ClientConfig.java
    @@ -66,7 +66,9 @@
      * If you want to create a client with custom configuration, you can use following code:
      * 
      * ClientConfig config = new ClientConfig.Builder()
    - *     .host("https://us-east-1-1.aws.cloud2.influxdata.com")
    + *     .host("
    + *         https://us-east-1-1.aws.cloud2.influxdata.com
    + *         ")
      *     .token("my-token".toCharArray())
      *     .database("my-database")
      *     .writePrecision(WritePrecision.S)
    @@ -223,7 +225,7 @@ public String getProxyUrl() {
         }
     
         /**
    -     * Gets certificates file path
    +     * Gets certificates file path.
          *
          * @return the certificates file path, may be null
          */
    @@ -514,7 +516,9 @@ public Builder authenticator(@Nullable final Authenticator authenticator) {
              * such as tracing headers. To add custom headers use following code:
              * 
              * ClientConfig config = new ClientConfig.Builder()
    -         *     .host("https://us-east-1-1.aws.cloud2.influxdata.com")
    +         *     .host("
    +         *         https://us-east-1-1.aws.cloud2.influxdata.com
    +         *         ")
              *     .token("my-token".toCharArray())
              *     .database("my-database")
              *     .headers(Map.of("X-Tracing-Id", "123"))
    diff --git a/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java b/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java
    index 93c7821c..ed1769d9 100644
    --- a/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java
    +++ b/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java
    @@ -263,7 +263,7 @@ private void setChannelTypeAndEventLoop(@Nonnull final NettyChannelBuilder netty
             }
         }
     
    -    private ProxyDetector createProxyDetector(@Nonnull String url) {
    +    private ProxyDetector createProxyDetector(@Nonnull final String url) {
             URI proxyUri = URI.create(url);
             return (targetServerAddress) -> {
                 InetSocketAddress targetAddress = (InetSocketAddress) targetServerAddress;
    diff --git a/src/main/java/com/influxdb/v3/client/internal/RestClient.java b/src/main/java/com/influxdb/v3/client/internal/RestClient.java
    index 8bfdaf7d..966da306 100644
    --- a/src/main/java/com/influxdb/v3/client/internal/RestClient.java
    +++ b/src/main/java/com/influxdb/v3/client/internal/RestClient.java
    @@ -233,7 +233,7 @@ void request(@Nonnull final String path,
             }
         }
     
    -    private X509TrustManager getX509TrustManagerFromFile(@Nonnull String filePath) {
    +    private X509TrustManager getX509TrustManagerFromFile(@Nonnull final String filePath) {
             try {
                 KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
                 trustStore.load(null);
    diff --git a/src/test/java/com/influxdb/v3/client/internal/RestClientTest.java b/src/test/java/com/influxdb/v3/client/internal/RestClientTest.java
    index 19566cde..16aa6fe2 100644
    --- a/src/test/java/com/influxdb/v3/client/internal/RestClientTest.java
    +++ b/src/test/java/com/influxdb/v3/client/internal/RestClientTest.java
    @@ -22,9 +22,7 @@
     package com.influxdb.v3.client.internal;
     
     import java.net.Authenticator;
    -import java.net.InetSocketAddress;
     import java.net.PasswordAuthentication;
    -import java.net.ProxySelector;
     import java.net.http.HttpClient;
     import java.net.http.HttpHeaders;
     import java.time.Duration;
    
    From 6319f0abed823bf00b8093819ddf610d1405df95 Mon Sep 17 00:00:00 2001
    From: NguyenHoangSon96 
    Date: Mon, 17 Mar 2025 16:49:19 +0700
    Subject: [PATCH 10/52] feat: add test case
    
    ---
     .../v3/client/InfluxDBClientTest.java         |  27 ++--
     .../v3/client/testdata/valid-certificates.pem | 138 ++++++++++++++++++
     2 files changed, 155 insertions(+), 10 deletions(-)
     create mode 100644 src/test/java/com/influxdb/v3/client/testdata/valid-certificates.pem
    
    diff --git a/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java b/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java
    index af6f718f..66e6a6dd 100644
    --- a/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java
    +++ b/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java
    @@ -22,13 +22,11 @@
     package com.influxdb.v3.client;
     
     import java.math.BigInteger;
    -import java.security.NoSuchAlgorithmException;
     import java.time.Instant;
     import java.util.Map;
     import java.util.Properties;
     import java.util.UUID;
     import java.util.stream.Stream;
    -import javax.net.ssl.SSLException;
     
     import org.assertj.core.api.Assertions;
     import org.junit.jupiter.api.Test;
    @@ -44,19 +42,18 @@ public class InfluxDBClientTest {
         @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_TOKEN", matches = ".*")
         @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_DATABASE", matches = ".*")
         @Test
    -    void testQueryProxy() {
    +    void testQueryProxyAndSslCertificate() {
             String proxyUrl = "http://127.0.0.1:10000";
     
    -        //todo remove
    -        //todo add test for proxy and certificates path
    -//        String certificateFilePath = "/Users/home/Downloads/influxdb3-java/src/test/java/com/influxdb/v3/client/valid-certificates.pem";
    +        // This is real certificate downloaded from https://cloud2.influxdata.com
    +        String certificateFilePath = "src/test/java/com/influxdb/v3/client/testdata/valid-certificates.pem";
     
             ClientConfig clientConfig = new ClientConfig.Builder()
                     .host(System.getenv("TESTING_INFLUXDB_URL"))
                     .token(System.getenv("TESTING_INFLUXDB_TOKEN").toCharArray())
                     .database(System.getenv("TESTING_INFLUXDB_DATABASE"))
                     .proxyUrl(proxyUrl)
    -//                .certificateFilePath(certificateFilePath)
    +                .certificateFilePath(certificateFilePath)
                     .build();
     
             InfluxDBClient influxDBClient = InfluxDBClient.getInstance(clientConfig);
    @@ -74,11 +71,21 @@ void testQueryProxy() {
         }
     
         @Test
    -    void withProxyUrl() throws NoSuchAlgorithmException, SSLException {
    +    void withProxyUrl() {
    +        String proxyUrl = "http://127.0.0.1:10000";
    +        ClientConfig.Builder builder = new ClientConfig.Builder();
    +        builder.proxyUrl(proxyUrl);
    +        ClientConfig clientConfig = builder.build();
    +        Assertions.assertThat(clientConfig.getProxyUrl()).isEqualTo(proxyUrl);
    +    }
    +
    +    @Test
    +    void withCertificateFilePath() {
    +        String path = "/path/to/cert";
             ClientConfig.Builder builder = new ClientConfig.Builder();
    -        builder.proxyUrl("http://127.0.0.1:10000");
    +        builder.certificateFilePath(path);
             ClientConfig clientConfig = builder.build();
    -        Assertions.assertThat(clientConfig.getProxyUrl()).isEqualTo("http://127.0.0.1:10000");
    +        Assertions.assertThat(clientConfig.certificateFilePath()).isEqualTo(path);
         }
     
         @Test
    diff --git a/src/test/java/com/influxdb/v3/client/testdata/valid-certificates.pem b/src/test/java/com/influxdb/v3/client/testdata/valid-certificates.pem
    new file mode 100644
    index 00000000..1613beac
    --- /dev/null
    +++ b/src/test/java/com/influxdb/v3/client/testdata/valid-certificates.pem
    @@ -0,0 +1,138 @@
    +-----BEGIN CERTIFICATE-----
    +MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
    +TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
    +cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
    +WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
    +ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
    +MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
    +h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
    +0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
    +A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
    +T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
    +B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
    +B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
    +KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
    +OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
    +jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
    +qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
    +rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
    +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
    +hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
    +ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
    +3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
    +NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
    +ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
    +TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
    +jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
    +oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
    +4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
    +mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
    +emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
    +-----END CERTIFICATE-----
    +
    +-----BEGIN CERTIFICATE-----
    +MIINYTCCDQagAwIBAgIRALQPM3zi5SVWCcng/hZpShIwCgYIKoZIzj0EAwIwOzEL
    +MAkGA1UEBhMCVVMxHjAcBgNVBAoTFUdvb2dsZSBUcnVzdCBTZXJ2aWNlczEMMAoG
    +A1UEAxMDV0UyMB4XDTI1MDIyNjE1MzMwM1oXDTI1MDUyMTE1MzMwMlowFzEVMBMG
    +A1UEAwwMKi5nb29nbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEgY2u
    +jvbPkuQiKZw9XHFP0GrdujA0tw6feXg2eVb3bWPQ7M0lJ/of3dlc9J/NQ8BjBrrn
    +bObLpB/4C3PjqziyQqOCDA0wggwJMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAK
    +BggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBTKaaMWpKmNeZC6ky5y
    +0iHRZX20szAfBgNVHSMEGDAWgBR1vsR3ron2RDd9z7FoHx0a69w0WTBYBggrBgEF
    +BQcBAQRMMEowIQYIKwYBBQUHMAGGFWh0dHA6Ly9vLnBraS5nb29nL3dlMjAlBggr
    +BgEFBQcwAoYZaHR0cDovL2kucGtpLmdvb2cvd2UyLmNydDCCCeQGA1UdEQSCCdsw
    +ggnXggwqLmdvb2dsZS5jb22CFiouYXBwZW5naW5lLmdvb2dsZS5jb22CCSouYmRu
    +LmRldoIVKi5vcmlnaW4tdGVzdC5iZG4uZGV2ghIqLmNsb3VkLmdvb2dsZS5jb22C
    +GCouY3Jvd2Rzb3VyY2UuZ29vZ2xlLmNvbYIYKi5kYXRhY29tcHV0ZS5nb29nbGUu
    +Y29tggsqLmdvb2dsZS5jYYILKi5nb29nbGUuY2yCDiouZ29vZ2xlLmNvLmlugg4q
    +Lmdvb2dsZS5jby5qcIIOKi5nb29nbGUuY28udWuCDyouZ29vZ2xlLmNvbS5hcoIP
    +Ki5nb29nbGUuY29tLmF1gg8qLmdvb2dsZS5jb20uYnKCDyouZ29vZ2xlLmNvbS5j
    +b4IPKi5nb29nbGUuY29tLm14gg8qLmdvb2dsZS5jb20udHKCDyouZ29vZ2xlLmNv
    +bS52boILKi5nb29nbGUuZGWCCyouZ29vZ2xlLmVzggsqLmdvb2dsZS5mcoILKi5n
    +b29nbGUuaHWCCyouZ29vZ2xlLml0ggsqLmdvb2dsZS5ubIILKi5nb29nbGUucGyC
    +CyouZ29vZ2xlLnB0gg8qLmdvb2dsZWFwaXMuY26CESouZ29vZ2xldmlkZW8uY29t
    +ggwqLmdzdGF0aWMuY26CECouZ3N0YXRpYy1jbi5jb22CD2dvb2dsZWNuYXBwcy5j
    +boIRKi5nb29nbGVjbmFwcHMuY26CEWdvb2dsZWFwcHMtY24uY29tghMqLmdvb2ds
    +ZWFwcHMtY24uY29tggxna2VjbmFwcHMuY26CDiouZ2tlY25hcHBzLmNughJnb29n
    +bGVkb3dubG9hZHMuY26CFCouZ29vZ2xlZG93bmxvYWRzLmNughByZWNhcHRjaGEu
    +bmV0LmNughIqLnJlY2FwdGNoYS5uZXQuY26CEHJlY2FwdGNoYS1jbi5uZXSCEiou
    +cmVjYXB0Y2hhLWNuLm5ldIILd2lkZXZpbmUuY26CDSoud2lkZXZpbmUuY26CEWFt
    +cHByb2plY3Qub3JnLmNughMqLmFtcHByb2plY3Qub3JnLmNughFhbXBwcm9qZWN0
    +Lm5ldC5jboITKi5hbXBwcm9qZWN0Lm5ldC5jboIXZ29vZ2xlLWFuYWx5dGljcy1j
    +bi5jb22CGSouZ29vZ2xlLWFuYWx5dGljcy1jbi5jb22CF2dvb2dsZWFkc2Vydmlj
    +ZXMtY24uY29tghkqLmdvb2dsZWFkc2VydmljZXMtY24uY29tghFnb29nbGV2YWRz
    +LWNuLmNvbYITKi5nb29nbGV2YWRzLWNuLmNvbYIRZ29vZ2xlYXBpcy1jbi5jb22C
    +EyouZ29vZ2xlYXBpcy1jbi5jb22CFWdvb2dsZW9wdGltaXplLWNuLmNvbYIXKi5n
    +b29nbGVvcHRpbWl6ZS1jbi5jb22CEmRvdWJsZWNsaWNrLWNuLm5ldIIUKi5kb3Vi
    +bGVjbGljay1jbi5uZXSCGCouZmxzLmRvdWJsZWNsaWNrLWNuLm5ldIIWKi5nLmRv
    +dWJsZWNsaWNrLWNuLm5ldIIOZG91YmxlY2xpY2suY26CECouZG91YmxlY2xpY2su
    +Y26CFCouZmxzLmRvdWJsZWNsaWNrLmNughIqLmcuZG91YmxlY2xpY2suY26CEWRh
    +cnRzZWFyY2gtY24ubmV0ghMqLmRhcnRzZWFyY2gtY24ubmV0gh1nb29nbGV0cmF2
    +ZWxhZHNlcnZpY2VzLWNuLmNvbYIfKi5nb29nbGV0cmF2ZWxhZHNlcnZpY2VzLWNu
    +LmNvbYIYZ29vZ2xldGFnc2VydmljZXMtY24uY29tghoqLmdvb2dsZXRhZ3NlcnZp
    +Y2VzLWNuLmNvbYIXZ29vZ2xldGFnbWFuYWdlci1jbi5jb22CGSouZ29vZ2xldGFn
    +bWFuYWdlci1jbi5jb22CGGdvb2dsZXN5bmRpY2F0aW9uLWNuLmNvbYIaKi5nb29n
    +bGVzeW5kaWNhdGlvbi1jbi5jb22CJCouc2FmZWZyYW1lLmdvb2dsZXN5bmRpY2F0
    +aW9uLWNuLmNvbYIWYXBwLW1lYXN1cmVtZW50LWNuLmNvbYIYKi5hcHAtbWVhc3Vy
    +ZW1lbnQtY24uY29tggtndnQxLWNuLmNvbYINKi5ndnQxLWNuLmNvbYILZ3Z0Mi1j
    +bi5jb22CDSouZ3Z0Mi1jbi5jb22CCzJtZG4tY24ubmV0gg0qLjJtZG4tY24ubmV0
    +ghRnb29nbGVmbGlnaHRzLWNuLm5ldIIWKi5nb29nbGVmbGlnaHRzLWNuLm5ldIIM
    +YWRtb2ItY24uY29tgg4qLmFkbW9iLWNuLmNvbYIUZ29vZ2xlc2FuZGJveC1jbi5j
    +b22CFiouZ29vZ2xlc2FuZGJveC1jbi5jb22CHiouc2FmZW51cC5nb29nbGVzYW5k
    +Ym94LWNuLmNvbYINKi5nc3RhdGljLmNvbYIUKi5tZXRyaWMuZ3N0YXRpYy5jb22C
    +CiouZ3Z0MS5jb22CESouZ2NwY2RuLmd2dDEuY29tggoqLmd2dDIuY29tgg4qLmdj
    +cC5ndnQyLmNvbYIQKi51cmwuZ29vZ2xlLmNvbYIWKi55b3V0dWJlLW5vY29va2ll
    +LmNvbYILKi55dGltZy5jb22CC2FuZHJvaWQuY29tgg0qLmFuZHJvaWQuY29tghMq
    +LmZsYXNoLmFuZHJvaWQuY29tggRnLmNuggYqLmcuY26CBGcuY2+CBiouZy5jb4IG
    +Z29vLmdsggp3d3cuZ29vLmdsghRnb29nbGUtYW5hbHl0aWNzLmNvbYIWKi5nb29n
    +bGUtYW5hbHl0aWNzLmNvbYIKZ29vZ2xlLmNvbYISZ29vZ2xlY29tbWVyY2UuY29t
    +ghQqLmdvb2dsZWNvbW1lcmNlLmNvbYIIZ2dwaHQuY26CCiouZ2dwaHQuY26CCnVy
    +Y2hpbi5jb22CDCoudXJjaGluLmNvbYIIeW91dHUuYmWCC3lvdXR1YmUuY29tgg0q
    +LnlvdXR1YmUuY29tghFtdXNpYy55b3V0dWJlLmNvbYITKi5tdXNpYy55b3V0dWJl
    +LmNvbYIUeW91dHViZWVkdWNhdGlvbi5jb22CFioueW91dHViZWVkdWNhdGlvbi5j
    +b22CD3lvdXR1YmVraWRzLmNvbYIRKi55b3V0dWJla2lkcy5jb22CBXl0LmJlggcq
    +Lnl0LmJlghphbmRyb2lkLmNsaWVudHMuZ29vZ2xlLmNvbYITKi5hbmRyb2lkLmdv
    +b2dsZS5jboISKi5jaHJvbWUuZ29vZ2xlLmNughYqLmRldmVsb3BlcnMuZ29vZ2xl
    +LmNughUqLmFpc3R1ZGlvLmdvb2dsZS5jb20wEwYDVR0gBAwwCjAIBgZngQwBAgEw
    +NgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2MucGtpLmdvb2cvd2UyLzY0T1VJVnpw
    +WlY0LmNybDCCAQMGCisGAQQB1nkCBAIEgfQEgfEA7wB1AM8RVu7VLnyv84db2Wku
    +m+kacWdKsBfsrAHSW3fOzDsIAAABlUMa3KQAAAQDAEYwRAIgbFT96GaW9xdF/H3T
    +R9A8aKomiq6jRak+HuHJKeYZKbICIFj0lmIw2MOCmAFoPML8Do+XUopVVJGpvKum
    +UZ3/H1ZBAHYAfVkeEuF4KnscYWd8Xv340IdcFKBOlZ65Ay/ZDowuebgAAAGVQxrc
    +mAAABAMARzBFAiA1pA/zxlqWAUktHGVu/3MlUzPsjEcaRHOEqw4qFdXIcgIhALwo
    +K02gj5Eep6saapUuV9BRJ8S5T4iydYXSoKuINbtcMAoGCCqGSM49BAMCA0kAMEYC
    +IQCe7kXY4zHS22OUlCThOBy44kLyCaMS20ylMx0JWcjHqQIhAIiNQSfvChn4LD5B
    +TtlK9da3ocqcq85/6pDQ4Cx7a2Ej
    +-----END CERTIFICATE-----
    +
    +-----BEGIN CERTIFICATE-----
    +MIIFSzCCBDOgAwIBAgISA+oZlVmojyzdwsUR47BXXUkOMA0GCSqGSIb3DQEBCwUA
    +MDMxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQwwCgYDVQQD
    +EwNSMTAwHhcNMjUwMzA2MDUxNDM2WhcNMjUwNjA0MDUxNDM1WjAuMSwwKgYDVQQD
    +EyNjbi1wcm9kMzAxLXVzLWVhc3QtNC5pbmZsdXhkYXRhLmNvbTCCASIwDQYJKoZI
    +hvcNAQEBBQADggEPADCCAQoCggEBANufjJuDVC5JX7FkgtJTsTY4BgXKhJ2CNr7S
    +Y0JRZWEMGiPE1LIusHYTIgSMR7DqkQubXTIst+GQCd1I0TaPq0JOgUcElPJ/Hroc
    +UeDXUmkwPB9oyUqAEZE7N1QhZPfrzKtizvt3y+lcMLSrD2npFnSQXDotUonnCgnV
    +/wviPowV3rEBqUkEmfeNaPqWwNhS5vGAS9nHq+VhJl63i4MV6VVUhsmXKNJpwj+S
    +6pferlhLRkPFO7T+IOLMOoM50lrZZk2D359+JVG2UVQknlWzPljteikY2GRahIam
    +mbQwAtdCX0dcz5x5EXtN4/Au4SFzHZAWuhIm0i3VMcvs36RcW18CAwEAAaOCAlww
    +ggJYMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUH
    +AwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUi2nfPdxKxh481jUurQRTJ01g8JQw
    +HwYDVR0jBBgwFoAUu7zDR6XkvKnGw6RyDBCNojXhyOgwVwYIKwYBBQUHAQEESzBJ
    +MCIGCCsGAQUFBzABhhZodHRwOi8vcjEwLm8ubGVuY3Iub3JnMCMGCCsGAQUFBzAC
    +hhdodHRwOi8vcjEwLmkubGVuY3Iub3JnLzBkBgNVHREEXTBbghVjbG91ZDIuaW5m
    +bHV4ZGF0YS5jb22CI2NuLXByb2QzMDEtdXMtZWFzdC00LmluZmx1eGRhdGEuY29t
    +gh1zdGFnaW5nLmNsb3VkMi5pbmZsdXhkYXRhLmNvbTATBgNVHSAEDDAKMAgGBmeB
    +DAECATCCAQMGCisGAQQB1nkCBAIEgfQEgfEA7wB1AKLjCuRF772tm3447Udnd1PX
    +gluElNcrXhssxLlQpEfnAAABlWoWE1IAAAQDAEYwRAIgQNybPpI1UMVzFtTaaZAz
    +7m/XcSglDuT/mvEv6nrdt3YCIGfx58c5llPJGjWNUSPbbEpL22sKFPbXuLEO78nB
    +rHPTAHYAE0rfGrWYQgl4DG/vTHqRpBa3I0nOWFdq367ap8Kr4CIAAAGVahYUxwAA
    +BAMARzBFAiBHSneDjE19jyyftoe1V5J1XQBVcm7ftufbswguI4qB/QIhAOegRql3
    +XPu0n8tq7/dfFeI1ChN7WhqqZxXZinDcr9rCMA0GCSqGSIb3DQEBCwUAA4IBAQAC
    +dgqfe0okFZ1g08EI4c8VMwYE8ii9z5VtM9bDf+2ukubahIlOBQ61glKuFkwr6yqU
    +yS5x/FUooq7yWYqMb/7zo/Xgb5/vpDfJblGi2oeuI3NBW1vu8Zkxa4rO1D8ypAPM
    +4JgsgtjYA4XOtTRoRmltlet3KvILPwFh0pTn9iDuLv0G8qf4eqezXpVj9QeZJknp
    +cr+tx8H7/0Kesy8coOzhkTXx3rjYbGce6JYlXHkyhMtppNcgHP8ly7CQCJjr4784
    ++mVdGOYN+rswgsnwMDwGEjbQfvErSqKS1DZNxIpy8CJLwfWJUNU3pqHqKM9lp4dY
    +ZWSUzpxgWgtYEdvcvDIi
    +-----END CERTIFICATE-----
    \ No newline at end of file
    
    From 43afa02d476208510ff0069844bcd1d853748052 Mon Sep 17 00:00:00 2001
    From: NguyenHoangSon96 
    Date: Mon, 17 Mar 2025 16:56:37 +0700
    Subject: [PATCH 11/52] feat: edit example
    
    ---
     .../java/com/influxdb/v3/ProxyExample.java    | 28 ++++++-------------
     .../v3/client/internal/RestClient.java        |  4 ++-
     2 files changed, 11 insertions(+), 21 deletions(-)
    
    diff --git a/examples/src/main/java/com/influxdb/v3/ProxyExample.java b/examples/src/main/java/com/influxdb/v3/ProxyExample.java
    index d2ef59e9..293cc783 100644
    --- a/examples/src/main/java/com/influxdb/v3/ProxyExample.java
    +++ b/examples/src/main/java/com/influxdb/v3/ProxyExample.java
    @@ -41,26 +41,14 @@ private ProxyExample() { }
         public static void main(final String[] args) throws Exception {
             // Run docker-compose.yml file to start Envoy proxy
     
    -        URI queryProxyUri = new URI("proxyUrl");
    -        URI uri = new URI(System.getenv("url"));
    -
    -        ProxyDetector proxyDetector = (targetServerAddress) -> {
    -            InetSocketAddress targetAddress = (InetSocketAddress) targetServerAddress;
    -            if (uri.getHost().equals(targetAddress.getHostString())) {
    -                return HttpConnectProxiedSocketAddress.newBuilder()
    -                        .setProxyAddress(new InetSocketAddress(queryProxyUri.getHost(), queryProxyUri.getPort()))
    -                        .setTargetAddress(targetAddress)
    -                        .build();
    -            }
    -            return null;
    -        };
    -        ProxySelector proxy = ProxySelector.of(new InetSocketAddress(queryProxyUri.getHost(), queryProxyUri.getPort()));
    +        String proxyUrl = "http://127.0.0.1:10000";
    +        String certificateFilePath = "src/test/java/com/influxdb/v3/client/testdata/valid-certificates.pem";
             ClientConfig clientConfig = new ClientConfig.Builder()
    -                .host(uri.toString())
    -                .token(System.getenv("token").toCharArray())
    -                .database(System.getenv("database"))
    -                .proxy(proxy)
    -                .queryApiProxy(proxyDetector)
    +                .host(System.getenv("TESTING_INFLUXDB_URL"))
    +                .token(System.getenv("TESTING_INFLUXDB_TOKEN").toCharArray())
    +                .database(System.getenv("TESTING_INFLUXDB_DATABASE"))
    +                .proxyUrl(proxyUrl)
    +                .certificateFilePath(certificateFilePath)
                     .build();
     
             InfluxDBClient influxDBClient = InfluxDBClient.getInstance(clientConfig);
    @@ -72,7 +60,7 @@ public static void main(final String[] args) throws Exception {
             try (Stream stream = influxDBClient.queryPoints("SELECT * FROM test1")) {
                 stream.findFirst()
                         .ifPresent(pointValues -> {
    -                        // do something
    +                        Assertions.assertThat(pointValues.getField("field")).isEqualTo("field1");
                         });
             }
         }
    diff --git a/src/main/java/com/influxdb/v3/client/internal/RestClient.java b/src/main/java/com/influxdb/v3/client/internal/RestClient.java
    index 966da306..be6c33f5 100644
    --- a/src/main/java/com/influxdb/v3/client/internal/RestClient.java
    +++ b/src/main/java/com/influxdb/v3/client/internal/RestClient.java
    @@ -249,7 +249,9 @@ private X509TrustManager getX509TrustManagerFromFile(@Nonnull final String fileP
                     trustStore.setCertificateEntry("alias" + i, cert);
                 }
     
    -            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    +            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
    +                    TrustManagerFactory.getDefaultAlgorithm()
    +            );
                 trustManagerFactory.init(trustStore);
                 X509TrustManager x509TrustManager = null;
                 for (TrustManager trustManager : trustManagerFactory.getTrustManagers()) {
    
    From da781eb72d2ddc0c6e96b2a1b23c4fa11d0fe97b Mon Sep 17 00:00:00 2001
    From: NguyenHoangSon96 
    Date: Mon, 17 Mar 2025 17:15:56 +0700
    Subject: [PATCH 12/52] fix: linter
    
    ---
     examples/src/main/java/com/influxdb/v3/ProxyExample.java | 6 ------
     1 file changed, 6 deletions(-)
    
    diff --git a/examples/src/main/java/com/influxdb/v3/ProxyExample.java b/examples/src/main/java/com/influxdb/v3/ProxyExample.java
    index 293cc783..dd43333b 100644
    --- a/examples/src/main/java/com/influxdb/v3/ProxyExample.java
    +++ b/examples/src/main/java/com/influxdb/v3/ProxyExample.java
    @@ -21,14 +21,8 @@
      */
     package com.influxdb.v3;
     
    -import java.net.InetSocketAddress;
    -import java.net.ProxySelector;
    -import java.net.URI;
     import java.util.stream.Stream;
     
    -import io.grpc.HttpConnectProxiedSocketAddress;
    -import io.grpc.ProxyDetector;
    -
     import com.influxdb.v3.client.InfluxDBClient;
     import com.influxdb.v3.client.Point;
     import com.influxdb.v3.client.PointValues;
    
    From 31d04dcaf99a29d8e9e59d08906113af08011893 Mon Sep 17 00:00:00 2001
    From: NguyenHoangSon96 
    Date: Mon, 17 Mar 2025 17:40:22 +0700
    Subject: [PATCH 13/52] feat: exclude .pem file license
    
    ---
     pom.xml | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/pom.xml b/pom.xml
    index cc9af3c1..f4cfc172 100644
    --- a/pom.xml
    +++ b/pom.xml
    @@ -399,7 +399,7 @@
                                     **/target/**, **/*.jar, **/.git/**, **/.*, **/*.png, **/*.iml, **/*.bolt, .idea/**,
                                     **/*nightly*/**, **/.m2/**, LICENSE, **/*.md, **/.github/**, license_header.txt,
                                     release.properties/, **/pom.xml.releaseBackup, **/pom.xml.tag, **/semantic.yml,
    -                                .circleci/config.yml
    +                                .circleci/config.yml, **/*.pem
                                 
                             
                         
    
    From aa5574f71891d0c0f7b9d6a40960167d2b24c995 Mon Sep 17 00:00:00 2001
    From: NguyenHoangSon96 
    Date: Tue, 18 Mar 2025 14:54:10 +0700
    Subject: [PATCH 14/52] [EMPTY] trigger CI
    
    
    From 315aac75935ca7e2eaa8072b49171c112a597c25 Mon Sep 17 00:00:00 2001
    From: NguyenHoangSon96 
    Date: Tue, 18 Mar 2025 15:09:25 +0700
    Subject: [PATCH 15/52] [EMPTY] trigger CI
    
    
    From a62d3759a705faca6b42f2409399625f5010f8f8 Mon Sep 17 00:00:00 2001
    From: NguyenHoangSon96 
    Date: Tue, 18 Mar 2025 17:40:26 +0700
    Subject: [PATCH 16/52] feat: run background command cicd
    
    ---
     .circleci/config.yml | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/.circleci/config.yml b/.circleci/config.yml
    index 6862a72b..ca419dd6 100644
    --- a/.circleci/config.yml
    +++ b/.circleci/config.yml
    @@ -20,10 +20,10 @@ jobs:
                 - maven-cache_v3-<< parameters.maven-image >>-
           - run:
               name: "Run Envoy"
    +          background: true
               command: |
                 wget -O- https://apt.envoyproxy.io/signing.key | sudo gpg --dearmor -o /etc/apt/keyrings/envoy-keyring.gpg
                 echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/envoy-keyring.gpg] https://apt.envoyproxy.io focal main" | sudo tee /etc/apt/sources.list.d/envoy.list
    -            sudo apt-get update
                 sudo apt-get install envoy
                 envoy -c .circleci/envoy.yaml
           - run:
    
    From 40e0de0f026d8a260ba8869a6b676066fbeb59f1 Mon Sep 17 00:00:00 2001
    From: NguyenHoangSon96 
    Date: Tue, 18 Mar 2025 17:43:05 +0700
    Subject: [PATCH 17/52] feat: run background command cicd
    
    ---
     .circleci/config.yml | 1 +
     1 file changed, 1 insertion(+)
    
    diff --git a/.circleci/config.yml b/.circleci/config.yml
    index ca419dd6..97c3ed0b 100644
    --- a/.circleci/config.yml
    +++ b/.circleci/config.yml
    @@ -24,6 +24,7 @@ jobs:
               command: |
                 wget -O- https://apt.envoyproxy.io/signing.key | sudo gpg --dearmor -o /etc/apt/keyrings/envoy-keyring.gpg
                 echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/envoy-keyring.gpg] https://apt.envoyproxy.io focal main" | sudo tee /etc/apt/sources.list.d/envoy.list
    +            sudo apt-get update
                 sudo apt-get install envoy
                 envoy -c .circleci/envoy.yaml
           - run:
    
    From 71eb25df515a456634becb06ac7cb2e8d5d3939f Mon Sep 17 00:00:00 2001
    From: NguyenHoangSon96 
    Date: Tue, 18 Mar 2025 17:48:20 +0700
    Subject: [PATCH 18/52] feat: run background command cicd
    
    ---
     .circleci/config.yml | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/.circleci/config.yml b/.circleci/config.yml
    index 97c3ed0b..ba97b65b 100644
    --- a/.circleci/config.yml
    +++ b/.circleci/config.yml
    @@ -20,7 +20,7 @@ jobs:
                 - maven-cache_v3-<< parameters.maven-image >>-
           - run:
               name: "Run Envoy"
    -          background: true
    +          background: true # this is maybe a bad idea
               command: |
                 wget -O- https://apt.envoyproxy.io/signing.key | sudo gpg --dearmor -o /etc/apt/keyrings/envoy-keyring.gpg
                 echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/envoy-keyring.gpg] https://apt.envoyproxy.io focal main" | sudo tee /etc/apt/sources.list.d/envoy.list
    
    From 7fdbb4d534b2c953c4e7620f8fc2e4c56c6feae8 Mon Sep 17 00:00:00 2001
    From: NguyenHoangSon96 
    Date: Wed, 19 Mar 2025 08:34:03 +0700
    Subject: [PATCH 19/52] refactor: add new function
    
    ---
     .../v3/client/internal/FlightSqlClient.java   | 56 ++++++++++---------
     1 file changed, 29 insertions(+), 27 deletions(-)
    
    diff --git a/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java b/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java
    index ed1769d9..83107e86 100644
    --- a/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java
    +++ b/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java
    @@ -22,7 +22,6 @@
     package com.influxdb.v3.client.internal;
     
     import java.io.FileInputStream;
    -import java.io.IOException;
     import java.lang.reflect.InvocationTargetException;
     import java.net.InetSocketAddress;
     import java.net.URI;
    @@ -40,7 +39,6 @@
     import java.util.stream.StreamSupport;
     import javax.annotation.Nonnull;
     import javax.annotation.Nullable;
    -import javax.net.ssl.SSLException;
     
     import com.fasterxml.jackson.core.JsonProcessingException;
     import com.fasterxml.jackson.databind.ObjectMapper;
    @@ -51,6 +49,7 @@
     import io.grpc.netty.NettyChannelBuilder;
     import io.netty.channel.EventLoopGroup;
     import io.netty.channel.ServerChannel;
    +import io.netty.handler.ssl.SslContext;
     import io.netty.handler.ssl.SslContextBuilder;
     import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
     import org.apache.arrow.flight.FlightClient;
    @@ -140,7 +139,7 @@ public void close() throws Exception {
         }
     
         @Nonnull
    -    private FlightClient createFlightClient(@Nonnull final ClientConfig config) {
    +    FlightClient createFlightClient(@Nonnull final ClientConfig config) {
             Location location = createLocation(config);
     
             final NettyChannelBuilder nettyChannelBuilder = NettyChannelBuilder.forTarget(location.getUri().getHost());
    @@ -162,32 +161,14 @@ private FlightClient createFlightClient(@Nonnull final ClientConfig config) {
             if (LocationSchemes.GRPC_TLS.equals(location.getUri().getScheme())) {
                 nettyChannelBuilder.useTransportSecurity();
     
    -            SslContextBuilder sslContextBuilder;
    -            sslContextBuilder = GrpcSslContexts.forClient();
    -            if (!config.getDisableServerCertificateValidation()) {
    -                if (config.certificateFilePath() != null) {
    -                    try (FileInputStream fileInputStream = new FileInputStream(config.certificateFilePath())) {
    -                        sslContextBuilder.trustManager(fileInputStream);
    -                    } catch (IOException e) {
    -                        throw new RuntimeException(e);
    -                    }
    -                }
    -            } else {
    -                sslContextBuilder.trustManager(InsecureTrustManagerFactory.INSTANCE);
    -            }
    -
    -            try {
    -                nettyChannelBuilder.sslContext(sslContextBuilder.build());
    -            } catch (SSLException e) {
    -                throw new RuntimeException(e);
    -            }
    -
    +            SslContext nettySslContext = createNettySslContext(config);
    +            nettyChannelBuilder.sslContext(nettySslContext);
             } else {
                 nettyChannelBuilder.usePlaintext();
             }
     
             if (config.getProxyUrl() != null) {
    -            ProxyDetector proxyDetector = createProxyDetector(config.getProxyUrl());
    +            ProxyDetector proxyDetector = createProxyDetector(config.getHost(), config.getProxyUrl());
                 nettyChannelBuilder.proxyDetector(proxyDetector);
             }
     
    @@ -198,6 +179,26 @@ private FlightClient createFlightClient(@Nonnull final ClientConfig config) {
             return FlightGrpcUtils.createFlightClient(new RootAllocator(Long.MAX_VALUE), nettyChannelBuilder.build());
         }
     
    +    @Nonnull
    +    SslContext createNettySslContext(@Nonnull final ClientConfig config) {
    +        try {
    +            SslContextBuilder sslContextBuilder;
    +            sslContextBuilder = GrpcSslContexts.forClient();
    +            if (!config.getDisableServerCertificateValidation()) {
    +                if (config.certificateFilePath() != null) {
    +                    try (FileInputStream fileInputStream = new FileInputStream(config.certificateFilePath())) {
    +                        sslContextBuilder.trustManager(fileInputStream);
    +                    }
    +                }
    +            } else {
    +                sslContextBuilder.trustManager(InsecureTrustManagerFactory.INSTANCE);
    +            }
    +            return sslContextBuilder.build();
    +        } catch (Exception e) {
    +            throw new RuntimeException(e);
    +        }
    +    }
    +
         @Nonnull
         private Location createLocation(@Nonnull final ClientConfig config) {
             try {
    @@ -263,11 +264,12 @@ private void setChannelTypeAndEventLoop(@Nonnull final NettyChannelBuilder netty
             }
         }
     
    -    private ProxyDetector createProxyDetector(@Nonnull final String url) {
    -        URI proxyUri = URI.create(url);
    +    private ProxyDetector createProxyDetector(@Nonnull final String hostUrl, @Nonnull final String proxyUrl) {
    +        URI proxyUri = URI.create(proxyUrl);
    +        URI hostUri = URI.create(hostUrl);
             return (targetServerAddress) -> {
                 InetSocketAddress targetAddress = (InetSocketAddress) targetServerAddress;
    -            if (proxyUri.getHost().equals(targetAddress.getHostString())) {
    +            if (hostUri.getHost().equals(targetAddress.getHostString())) {
                     return HttpConnectProxiedSocketAddress.newBuilder()
                             .setProxyAddress(new InetSocketAddress(proxyUri.getHost(), proxyUri.getPort()))
                             .setTargetAddress(targetAddress)
    
    From e61af34913de3d2e5dff35a7402618c5bb9bcc5d Mon Sep 17 00:00:00 2001
    From: NguyenHoangSon96 
    Date: Wed, 19 Mar 2025 09:02:40 +0700
    Subject: [PATCH 20/52] chore: add comment
    
    ---
     src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java | 1 +
     1 file changed, 1 insertion(+)
    
    diff --git a/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java b/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java
    index 66e6a6dd..07b5a45d 100644
    --- a/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java
    +++ b/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java
    @@ -43,6 +43,7 @@ public class InfluxDBClientTest {
         @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_DATABASE", matches = ".*")
         @Test
         void testQueryProxyAndSslCertificate() {
    +        // This test need Envoy proxy to run as this address
             String proxyUrl = "http://127.0.0.1:10000";
     
             // This is real certificate downloaded from https://cloud2.influxdata.com
    
    From 15ca3ced1130cb11537e0b8f235cf6e0b1e19fac Mon Sep 17 00:00:00 2001
    From: NguyenHoangSon96 
    Date: Wed, 19 Mar 2025 09:30:58 +0700
    Subject: [PATCH 21/52] refactor: revert proxy property
    
    ---
     .../v3/client/config/ClientConfig.java        | 43 +++++++++++++++++--
     .../v3/client/internal/FlightSqlClient.java   |  9 ++++
     .../v3/client/internal/RestClient.java        |  6 ++-
     .../v3/client/InfluxDBClientTest.java         |  8 ++--
     .../v3/client/internal/RestClientTest.java    | 20 +++++++++
     5 files changed, 77 insertions(+), 9 deletions(-)
    
    diff --git a/src/main/java/com/influxdb/v3/client/config/ClientConfig.java b/src/main/java/com/influxdb/v3/client/config/ClientConfig.java
    index a2df4a6d..713cc74c 100644
    --- a/src/main/java/com/influxdb/v3/client/config/ClientConfig.java
    +++ b/src/main/java/com/influxdb/v3/client/config/ClientConfig.java
    @@ -23,6 +23,7 @@
     
     import java.net.Authenticator;
     import java.net.MalformedURLException;
    +import java.net.ProxySelector;
     import java.net.URL;
     import java.time.Duration;
     import java.util.Arrays;
    @@ -87,8 +88,6 @@
      * Immutable class.
      */
     public final class ClientConfig {
    -    //todo check if main use proxySelector for backward compality
    -    //todo check comments
         private final String host;
         private final char[] token;
         private final String authScheme;
    @@ -105,6 +104,12 @@ public final class ClientConfig {
         private final Map headers;
         private final String certificateFilePath;
     
    +    /**
    +     * @deprecated use {@link #proxyUrl}
    +     */
    +    @Deprecated
    +    private final ProxySelector proxy;
    +
         /**
          * Gets URL of the InfluxDB server.
          *
    @@ -214,6 +219,18 @@ public Boolean getDisableServerCertificateValidation() {
             return disableServerCertificateValidation;
         }
     
    +    /**
    +     * Gets the proxy.
    +     *
    +     * @return the proxy, may be null
    +     * @derepcated use {@link #proxyUrl}
    +     */
    +    @Nullable
    +    @Deprecated
    +    public ProxySelector getProxy() {
    +        return proxy;
    +    }
    +
         /**
          * Gets the proxy url.
          *
    @@ -283,6 +300,7 @@ public boolean equals(final Object o) {
                     && Objects.equals(timeout, that.timeout)
                     && Objects.equals(allowHttpRedirects, that.allowHttpRedirects)
                     && Objects.equals(disableServerCertificateValidation, that.disableServerCertificateValidation)
    +                && Objects.equals(proxy, that.proxy)
                     && Objects.equals(proxyUrl, that.proxyUrl)
                     && Objects.equals(authenticator, that.authenticator)
                     && Objects.equals(headers, that.headers)
    @@ -294,7 +312,7 @@ public int hashCode() {
             return Objects.hash(host, Arrays.hashCode(token), authScheme, organization,
                     database, writePrecision, gzipThreshold,
                     timeout, allowHttpRedirects, disableServerCertificateValidation,
    -                proxyUrl, authenticator, headers,
    +                proxy, proxyUrl, authenticator, headers,
                     defaultTags, certificateFilePath);
         }
     
    @@ -309,7 +327,8 @@ public String toString() {
                     .add("timeout=" + timeout)
                     .add("allowHttpRedirects=" + allowHttpRedirects)
                     .add("disableServerCertificateValidation=" + disableServerCertificateValidation)
    -                .add("proxy=" + proxyUrl)
    +                .add("proxy=" + proxy)
    +                .add("proxyUrl=" + proxyUrl)
                     .add("authenticator=" + authenticator)
                     .add("headers=" + headers)
                     .add("defaultTags=" + defaultTags)
    @@ -334,6 +353,7 @@ public static final class Builder {
             private Duration timeout;
             private Boolean allowHttpRedirects;
             private Boolean disableServerCertificateValidation;
    +        private ProxySelector proxy;
             private String proxyUrl;
             private Authenticator authenticator;
             private Map headers;
    @@ -485,6 +505,20 @@ public Builder disableServerCertificateValidation(@Nullable final Boolean disabl
                 return this;
             }
     
    +        /**
    +         * Sets the proxy selector. Default is 'null'.
    +         *
    +         * @param proxy Proxy selector.
    +         * @return this
    +         * @deprecated use {@link #proxyUrl}
    +         */
    +        @Nonnull
    +        public Builder proxy(@Nullable final ProxySelector proxy) {
    +
    +            this.proxy = proxy;
    +            return this;
    +        }
    +
             /**
              * Sets the proxy url. Default is 'null'.
              *
    @@ -690,6 +724,7 @@ private ClientConfig(@Nonnull final Builder builder) {
             allowHttpRedirects = builder.allowHttpRedirects != null ? builder.allowHttpRedirects : false;
             disableServerCertificateValidation = builder.disableServerCertificateValidation != null
                     ? builder.disableServerCertificateValidation : false;
    +        proxy = builder.proxy;
             proxyUrl = builder.proxyUrl;
             authenticator = builder.authenticator;
             headers = builder.headers;
    diff --git a/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java b/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java
    index 83107e86..1ff672b8 100644
    --- a/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java
    +++ b/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java
    @@ -24,6 +24,7 @@
     import java.io.FileInputStream;
     import java.lang.reflect.InvocationTargetException;
     import java.net.InetSocketAddress;
    +import java.net.ProxySelector;
     import java.net.URI;
     import java.net.URISyntaxException;
     import java.nio.charset.StandardCharsets;
    @@ -63,12 +64,16 @@
     import org.apache.arrow.memory.RootAllocator;
     import org.apache.arrow.util.AutoCloseables;
     import org.apache.arrow.vector.VectorSchemaRoot;
    +import org.slf4j.Logger;
    +import org.slf4j.LoggerFactory;
     
     import com.influxdb.v3.client.config.ClientConfig;
     import com.influxdb.v3.client.query.QueryType;
     
     final class FlightSqlClient implements AutoCloseable {
     
    +    private static final Logger LOG = LoggerFactory.getLogger(FlightSqlClient.class);
    +
         private final FlightClient client;
     
         private final Map defaultHeaders = new HashMap<>();
    @@ -172,6 +177,10 @@ FlightClient createFlightClient(@Nonnull final ClientConfig config) {
                 nettyChannelBuilder.proxyDetector(proxyDetector);
             }
     
    +        if (config.getProxy() != null) {
    +            LOG.warn("proxy property is deprecated, use proxyUrl property instead");
    +        }
    +
             nettyChannelBuilder.maxTraceEvents(0)
                     .maxInboundMessageSize(Integer.MAX_VALUE)
                     .maxInboundMetadataSize(Integer.MAX_VALUE);
    diff --git a/src/main/java/com/influxdb/v3/client/internal/RestClient.java b/src/main/java/com/influxdb/v3/client/internal/RestClient.java
    index be6c33f5..f08b705c 100644
    --- a/src/main/java/com/influxdb/v3/client/internal/RestClient.java
    +++ b/src/main/java/com/influxdb/v3/client/internal/RestClient.java
    @@ -106,7 +106,6 @@ public void checkServerTrusted(
             // default headers
             this.defaultHeaders = config.getHeaders() != null ? Map.copyOf(config.getHeaders()) : null;
     
    -        // proxy
             if (config.getProxyUrl() != null) {
                 URI uri = URI.create(config.getProxyUrl());
                 ProxySelector proxy = ProxySelector.of(new InetSocketAddress(uri.getHost(), uri.getPort()));
    @@ -114,6 +113,11 @@ public void checkServerTrusted(
                 if (config.getAuthenticator() != null) {
                     builder.authenticator(config.getAuthenticator());
                 }
    +        } else if (config.getProxy() != null) {
    +            builder.proxy(config.getProxy());
    +            if (config.getAuthenticator() != null) {
    +                builder.authenticator(config.getAuthenticator());
    +            }
             }
     
             if (baseUrl.startsWith("https")) {
    diff --git a/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java b/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java
    index 07b5a45d..f431f1d7 100644
    --- a/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java
    +++ b/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java
    @@ -154,10 +154,10 @@ void withDefaultTags() throws Exception {
             Map defaultTags = Map.of("unit", "U2", "model", "M1");
     
             try (InfluxDBClient client = InfluxDBClient.getInstance(
    -                "http://localhost:8086",
    -                "MY-TOKEN".toCharArray(),
    -                "MY-DATABASE",
    -                defaultTags)) {
    +          "http://localhost:8086",
    +          "MY-TOKEN".toCharArray(),
    +          "MY-DATABASE",
    +          defaultTags)) {
                 Assertions.assertThat(client).isNotNull();
             }
         }
    diff --git a/src/test/java/com/influxdb/v3/client/internal/RestClientTest.java b/src/test/java/com/influxdb/v3/client/internal/RestClientTest.java
    index 16aa6fe2..6ec792ad 100644
    --- a/src/test/java/com/influxdb/v3/client/internal/RestClientTest.java
    +++ b/src/test/java/com/influxdb/v3/client/internal/RestClientTest.java
    @@ -22,7 +22,9 @@
     package com.influxdb.v3.client.internal;
     
     import java.net.Authenticator;
    +import java.net.InetSocketAddress;
     import java.net.PasswordAuthentication;
    +import java.net.ProxySelector;
     import java.net.http.HttpClient;
     import java.net.http.HttpHeaders;
     import java.time.Duration;
    @@ -275,6 +277,24 @@ public void allowHttpRedirects() {
         public void proxy() throws InterruptedException {
             mockServer.enqueue(createResponse(200));
     
    +        restClient = new RestClient(new ClientConfig.Builder()
    +                .host("http://foo.com:8086")
    +                .proxy(ProxySelector.of((InetSocketAddress) mockServer.toProxyAddress().address()))
    +                .build());
    +
    +        restClient.request("ping", HttpMethod.GET, null, null, null);
    +
    +        RecordedRequest recordedRequest = mockServer.takeRequest();
    +
    +        Assertions.assertThat(recordedRequest.getRequestUrl()).isNotNull();
    +        Assertions.assertThat(recordedRequest.getRequestUrl().toString()).isEqualTo(baseURL); // server is used as proxy
    +        Assertions.assertThat(recordedRequest.getRequestLine()).isEqualTo("GET http://foo.com:8086/ping HTTP/1.1");
    +    }
    +
    +    @Test
    +    public void proxyUrl() throws InterruptedException {
    +        mockServer.enqueue(createResponse(200));
    +
             restClient = new RestClient(new ClientConfig.Builder()
                     .host("http://foo.com:8086")
                     .proxyUrl(String.format("http://%s:%s", mockServer.getHostName(), mockServer.getPort()))
    
    From 5cd26e2347dd5c7aabf669a32302ea3e983ffd9c Mon Sep 17 00:00:00 2001
    From: NguyenHoangSon96 
    Date: Wed, 19 Mar 2025 09:31:57 +0700
    Subject: [PATCH 22/52] refactor: revert proxy property
    
    ---
     .../java/com/influxdb/v3/client/internal/FlightSqlClient.java   | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java b/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java
    index 1ff672b8..3bdafdb3 100644
    --- a/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java
    +++ b/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java
    @@ -178,7 +178,7 @@ FlightClient createFlightClient(@Nonnull final ClientConfig config) {
             }
     
             if (config.getProxy() != null) {
    -            LOG.warn("proxy property is deprecated, use proxyUrl property instead");
    +            LOG.warn("proxy property will not work in query api, use proxyUrl property instead");
             }
     
             nettyChannelBuilder.maxTraceEvents(0)
    
    From 173f571eea315a519d23c4587688fb26be1b9cfc Mon Sep 17 00:00:00 2001
    From: NguyenHoangSon96 
    Date: Wed, 19 Mar 2025 10:20:09 +0700
    Subject: [PATCH 23/52] feat: add dockerfile for circleci
    
    ---
     .circleci/config.yml        | 18 +++++++++---------
     .circleci/images/Dockerfile | 11 +++++++++++
     2 files changed, 20 insertions(+), 9 deletions(-)
     create mode 100644 .circleci/images/Dockerfile
    
    diff --git a/.circleci/config.yml b/.circleci/config.yml
    index ba97b65b..8ceefc7b 100644
    --- a/.circleci/config.yml
    +++ b/.circleci/config.yml
    @@ -11,6 +11,7 @@ jobs:
             default: ""
         docker:
           - image: << parameters.maven-image >>
    +      - image: sonnh96/influxdb3-java-envoy:0.0.1
         steps:
           - checkout
           - restore_cache:
    @@ -18,15 +19,14 @@ jobs:
               keys:
                 - &cache-key maven-cache_v1-<< parameters.maven-image >>-{{ checksum "pom.xml" }}
                 - maven-cache_v3-<< parameters.maven-image >>-
    -      - run:
    -          name: "Run Envoy"
    -          background: true # this is maybe a bad idea
    -          command: |
    -            wget -O- https://apt.envoyproxy.io/signing.key | sudo gpg --dearmor -o /etc/apt/keyrings/envoy-keyring.gpg
    -            echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/envoy-keyring.gpg] https://apt.envoyproxy.io focal main" | sudo tee /etc/apt/sources.list.d/envoy.list
    -            sudo apt-get update
    -            sudo apt-get install envoy
    -            envoy -c .circleci/envoy.yaml
    +#      - run:
    +#          name: "Run Envoy"
    +#          command: |
    +#            wget -O- https://apt.envoyproxy.io/signing.key | sudo gpg --dearmor -o /etc/apt/keyrings/envoy-keyring.gpg
    +#            echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/envoy-keyring.gpg] https://apt.envoyproxy.io focal main" | sudo tee /etc/apt/sources.list.d/envoy.list
    +#            sudo apt-get update
    +#            sudo apt-get install envoy
    +#            envoy -c .circleci/envoy.yaml
           - run:
               name: "Running tests"
               command: |
    diff --git a/.circleci/images/Dockerfile b/.circleci/images/Dockerfile
    new file mode 100644
    index 00000000..cb6a6cfe
    --- /dev/null
    +++ b/.circleci/images/Dockerfile
    @@ -0,0 +1,11 @@
    +FROM cimg/base:current
    +
    +RUN wget -O- https://apt.envoyproxy.io/signing.key | sudo gpg --dearmor -o /etc/apt/keyrings/envoy-keyring.gpg
    +RUN sudo echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/envoy-keyring.gpg] https://apt.envoyproxy.io jammy main" | sudo tee /etc/apt/sources.list.d/envoy.list
    +RUN sudo apt-get update
    +RUN sudo apt-get install envoy
    +
    +COPY ./envoy.yml /etc
    +EXPOSE 10000
    +
    +ENTRYPOINT ["/usr/bin/envoy", "-c", "/etc/envoy.yml", "-l", "debug"]
    \ No newline at end of file
    
    From 70123b2c8fd2eeffc1d7375738d44417a38c53f4 Mon Sep 17 00:00:00 2001
    From: NguyenHoangSon96 
    Date: Wed, 19 Mar 2025 10:40:27 +0700
    Subject: [PATCH 24/52] feat: update config.yml
    
    ---
     .circleci/config.yml | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/.circleci/config.yml b/.circleci/config.yml
    index 8ceefc7b..6a093b37 100644
    --- a/.circleci/config.yml
    +++ b/.circleci/config.yml
    @@ -11,7 +11,7 @@ jobs:
             default: ""
         docker:
           - image: << parameters.maven-image >>
    -      - image: sonnh96/influxdb3-java-envoy:0.0.1
    +      - image: sonnh96/influxdb3-java-envoy:0.0.2
         steps:
           - checkout
           - restore_cache:
    
    From 35f3cc125da0879b4b8c8c5a9782bb5d261b055a Mon Sep 17 00:00:00 2001
    From: NguyenHoangSon96 
    Date: Wed, 19 Mar 2025 10:46:08 +0700
    Subject: [PATCH 25/52] chore: update comments
    
    ---
     .../java/com/influxdb/v3/client/config/ClientConfig.java     | 5 +++--
     1 file changed, 3 insertions(+), 2 deletions(-)
    
    diff --git a/src/main/java/com/influxdb/v3/client/config/ClientConfig.java b/src/main/java/com/influxdb/v3/client/config/ClientConfig.java
    index 713cc74c..a3995134 100644
    --- a/src/main/java/com/influxdb/v3/client/config/ClientConfig.java
    +++ b/src/main/java/com/influxdb/v3/client/config/ClientConfig.java
    @@ -57,6 +57,7 @@
      *     
  • disableServerCertificateValidation - * disable server certificate validation for HTTPS connections *
  • + *
  • proxy - HTTP proxy selector
  • *
  • proxyUrl - Proxy url for query api and write api
  • *
  • queryApiProxy - HTTP query detector
  • *
  • authenticator - HTTP proxy authenticator
  • @@ -105,7 +106,7 @@ public final class ClientConfig { private final String certificateFilePath; /** - * @deprecated use {@link #proxyUrl} + * Deprecated use {@link #proxyUrl} */ @Deprecated private final ProxySelector proxy; @@ -510,7 +511,7 @@ public Builder disableServerCertificateValidation(@Nullable final Boolean disabl * * @param proxy Proxy selector. * @return this - * @deprecated use {@link #proxyUrl} + * Deprecated use {@link #proxyUrl} */ @Nonnull public Builder proxy(@Nullable final ProxySelector proxy) { From eb2d42935c5b0f7aa0f72a2cb16e1bb89143fba8 Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Wed, 19 Mar 2025 10:49:09 +0700 Subject: [PATCH 26/52] chore: add licence --- .circleci/images/Dockerfile | 22 +++++++++++++++++++ .../v3/client/config/ClientConfig.java | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/.circleci/images/Dockerfile b/.circleci/images/Dockerfile index cb6a6cfe..15a6de9c 100644 --- a/.circleci/images/Dockerfile +++ b/.circleci/images/Dockerfile @@ -1,3 +1,25 @@ +# +# The MIT License +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# + FROM cimg/base:current RUN wget -O- https://apt.envoyproxy.io/signing.key | sudo gpg --dearmor -o /etc/apt/keyrings/envoy-keyring.gpg diff --git a/src/main/java/com/influxdb/v3/client/config/ClientConfig.java b/src/main/java/com/influxdb/v3/client/config/ClientConfig.java index a3995134..973a921a 100644 --- a/src/main/java/com/influxdb/v3/client/config/ClientConfig.java +++ b/src/main/java/com/influxdb/v3/client/config/ClientConfig.java @@ -224,7 +224,7 @@ public Boolean getDisableServerCertificateValidation() { * Gets the proxy. * * @return the proxy, may be null - * @derepcated use {@link #proxyUrl} + * Deprecated use {@link #proxyUrl} */ @Nullable @Deprecated From d604a2a9e419333139bd0219a64d7fe1634f4010 Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Wed, 19 Mar 2025 10:52:12 +0700 Subject: [PATCH 27/52] fix: linter --- src/main/java/com/influxdb/v3/client/config/ClientConfig.java | 2 +- .../java/com/influxdb/v3/client/internal/FlightSqlClient.java | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/com/influxdb/v3/client/config/ClientConfig.java b/src/main/java/com/influxdb/v3/client/config/ClientConfig.java index 973a921a..e9d5f4ad 100644 --- a/src/main/java/com/influxdb/v3/client/config/ClientConfig.java +++ b/src/main/java/com/influxdb/v3/client/config/ClientConfig.java @@ -106,7 +106,7 @@ public final class ClientConfig { private final String certificateFilePath; /** - * Deprecated use {@link #proxyUrl} + * Deprecated use {@link #proxyUrl}. */ @Deprecated private final ProxySelector proxy; diff --git a/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java b/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java index 3bdafdb3..d650a5fc 100644 --- a/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java +++ b/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java @@ -24,7 +24,6 @@ import java.io.FileInputStream; import java.lang.reflect.InvocationTargetException; import java.net.InetSocketAddress; -import java.net.ProxySelector; import java.net.URI; import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; From c7f1feddf64bc86054c0b167025adc29ee57bf25 Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Wed, 19 Mar 2025 11:24:00 +0700 Subject: [PATCH 28/52] feat: update test case --- .../v3/client/internal/FlightSqlClient.java | 2 +- .../client/internal/FlightSqlClientTest.java | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java b/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java index d650a5fc..3b666236 100644 --- a/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java +++ b/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java @@ -272,7 +272,7 @@ private void setChannelTypeAndEventLoop(@Nonnull final NettyChannelBuilder netty } } - private ProxyDetector createProxyDetector(@Nonnull final String hostUrl, @Nonnull final String proxyUrl) { + ProxyDetector createProxyDetector(@Nonnull final String hostUrl, @Nonnull final String proxyUrl) { URI proxyUri = URI.create(proxyUrl); URI hostUri = URI.create(hostUrl); return (targetServerAddress) -> { diff --git a/src/test/java/com/influxdb/v3/client/internal/FlightSqlClientTest.java b/src/test/java/com/influxdb/v3/client/internal/FlightSqlClientTest.java index 19e0ea0b..387707c0 100644 --- a/src/test/java/com/influxdb/v3/client/internal/FlightSqlClientTest.java +++ b/src/test/java/com/influxdb/v3/client/internal/FlightSqlClientTest.java @@ -21,9 +21,12 @@ */ package com.influxdb.v3.client.internal; +import java.io.IOException; +import java.net.InetSocketAddress; import java.net.URISyntaxException; import java.util.Map; +import io.grpc.ProxyDetector; import io.grpc.internal.GrpcUtil; import org.apache.arrow.flight.CallHeaders; import org.apache.arrow.flight.CallInfo; @@ -272,6 +275,23 @@ public void useParamsFromQueryConfig() throws Exception { } } + @Test + void createProxyDetector() { + ClientConfig clientConfig = new ClientConfig.Builder() + .host("https://localhost:80") + .build(); + try (FlightSqlClient flightSqlClient = new FlightSqlClient(clientConfig)) { + String hostUrl = "https://youtube.com"; + String proxyUrl = "https://facebook.com"; + ProxyDetector proxyDetector = flightSqlClient.createProxyDetector(hostUrl, proxyUrl); + Assertions.assertThat(proxyDetector.proxyFor( + new InetSocketAddress("142.250.198.142", 80) + )).isNull(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + static class CallHeadersMiddleware implements FlightClientMiddleware.Factory { CallHeaders headers; From 567055dd6a605b0406ed90c746191aeaba57e0d8 Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Wed, 19 Mar 2025 11:26:47 +0700 Subject: [PATCH 29/52] fix: linter --- .../com/influxdb/v3/client/internal/FlightSqlClientTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/java/com/influxdb/v3/client/internal/FlightSqlClientTest.java b/src/test/java/com/influxdb/v3/client/internal/FlightSqlClientTest.java index 387707c0..bba68e79 100644 --- a/src/test/java/com/influxdb/v3/client/internal/FlightSqlClientTest.java +++ b/src/test/java/com/influxdb/v3/client/internal/FlightSqlClientTest.java @@ -21,7 +21,6 @@ */ package com.influxdb.v3.client.internal; -import java.io.IOException; import java.net.InetSocketAddress; import java.net.URISyntaxException; import java.util.Map; From 615a7871c007bf629e23ba15b6ec75ad7ca3f867 Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Thu, 20 Mar 2025 14:00:25 +0700 Subject: [PATCH 30/52] fix: linter --- src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java b/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java index f431f1d7..f3f8b7f9 100644 --- a/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java +++ b/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java @@ -43,7 +43,7 @@ public class InfluxDBClientTest { @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_DATABASE", matches = ".*") @Test void testQueryProxyAndSslCertificate() { - // This test need Envoy proxy to run as this address + // This test need Envoy proxy to run at this address String proxyUrl = "http://127.0.0.1:10000"; // This is real certificate downloaded from https://cloud2.influxdata.com From 5c38daa6b681f280b231244268496494785a0d60 Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Thu, 20 Mar 2025 14:11:47 +0700 Subject: [PATCH 31/52] refactor: remove unused files --- .circleci/config.yml | 9 ---- .circleci/envoy.yaml | 84 ------------------------------------- .circleci/images/Dockerfile | 33 --------------- 3 files changed, 126 deletions(-) delete mode 100644 .circleci/envoy.yaml delete mode 100644 .circleci/images/Dockerfile diff --git a/.circleci/config.yml b/.circleci/config.yml index 6a093b37..3dca04ff 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -11,7 +11,6 @@ jobs: default: "" docker: - image: << parameters.maven-image >> - - image: sonnh96/influxdb3-java-envoy:0.0.2 steps: - checkout - restore_cache: @@ -19,14 +18,6 @@ jobs: keys: - &cache-key maven-cache_v1-<< parameters.maven-image >>-{{ checksum "pom.xml" }} - maven-cache_v3-<< parameters.maven-image >>- -# - run: -# name: "Run Envoy" -# command: | -# wget -O- https://apt.envoyproxy.io/signing.key | sudo gpg --dearmor -o /etc/apt/keyrings/envoy-keyring.gpg -# echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/envoy-keyring.gpg] https://apt.envoyproxy.io focal main" | sudo tee /etc/apt/sources.list.d/envoy.list -# sudo apt-get update -# sudo apt-get install envoy -# envoy -c .circleci/envoy.yaml - run: name: "Running tests" command: | diff --git a/.circleci/envoy.yaml b/.circleci/envoy.yaml deleted file mode 100644 index ab539c73..00000000 --- a/.circleci/envoy.yaml +++ /dev/null @@ -1,84 +0,0 @@ -# -# The MIT License -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# - -static_resources: - listeners: - - name: listener_0 - address: - socket_address: { address: 0.0.0.0, port_value: 10000 } - filter_chains: - - filter_chain_match: - filters: - - name: envoy.filters.network.http_connection_manager - typed_config: - "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager - stat_prefix: ingress_http - access_log: - - name: envoy.access_loggers.stdout - typed_config: - "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog - http2_protocol_options: - allow_connect: true - upgrade_configs: - - upgrade_type: CONNECT - http_filters: - - name: envoy.filters.http.router - typed_config: - "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router - - route_config: - name: local_route - virtual_hosts: - - name: local_service - domains: [ "*" ] - routes: - - match: - connect_matcher: { } - route: - cluster: influxdb_cluster - upgrade_configs: - upgrade_type: CONNECT - connect_config: { } - - match: - prefix: "/" - route: - cluster: influxdb_cluster - prefix_rewrite: "/" - auto_host_rewrite: true - timeout: 10s - cors: - allow_origin_string_match: - - prefix: "*" - allow_methods: GET, PUT, DELETE, POST, OPTIONS - clusters: - - name: influxdb_cluster - connect_timeout: 10s - type: STRICT_DNS - load_assignment: - cluster_name: influxdb_cluster - endpoints: - - lb_endpoints: - - endpoint: - address: - socket_address: - address: "us-east-1-1.aws.cloud2.influxdata.com" - port_value: 443 \ No newline at end of file diff --git a/.circleci/images/Dockerfile b/.circleci/images/Dockerfile deleted file mode 100644 index 15a6de9c..00000000 --- a/.circleci/images/Dockerfile +++ /dev/null @@ -1,33 +0,0 @@ -# -# The MIT License -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# - -FROM cimg/base:current - -RUN wget -O- https://apt.envoyproxy.io/signing.key | sudo gpg --dearmor -o /etc/apt/keyrings/envoy-keyring.gpg -RUN sudo echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/envoy-keyring.gpg] https://apt.envoyproxy.io jammy main" | sudo tee /etc/apt/sources.list.d/envoy.list -RUN sudo apt-get update -RUN sudo apt-get install envoy - -COPY ./envoy.yml /etc -EXPOSE 10000 - -ENTRYPOINT ["/usr/bin/envoy", "-c", "/etc/envoy.yml", "-l", "debug"] \ No newline at end of file From d46b2d50ba5e87db9ba6a7defbe95c1159bb671b Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Thu, 20 Mar 2025 14:20:11 +0700 Subject: [PATCH 32/52] feat: run test if Envoy is running --- .../com/influxdb/v3/client/InfluxDBClientTest.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java b/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java index f3f8b7f9..21ea2601 100644 --- a/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java +++ b/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java @@ -21,7 +21,10 @@ */ package com.influxdb.v3.client; +import java.io.IOException; import java.math.BigInteger; +import java.net.URL; +import java.net.URLConnection; import java.time.Instant; import java.util.Map; import java.util.Properties; @@ -43,8 +46,14 @@ public class InfluxDBClientTest { @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_DATABASE", matches = ".*") @Test void testQueryProxyAndSslCertificate() { - // This test need Envoy proxy to run at this address String proxyUrl = "http://127.0.0.1:10000"; + try { + // Continue to run this test only if Envoy proxy is running in this address http://127.0.0.1:10000 + URLConnection hpCon = new URL(proxyUrl).openConnection(); + hpCon.connect(); + } catch (IOException e) { + return; + } // This is real certificate downloaded from https://cloud2.influxdata.com String certificateFilePath = "src/test/java/com/influxdb/v3/client/testdata/valid-certificates.pem"; From a32731b8cb2f7efa41dd83f1639be76cdce3e67b Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Thu, 20 Mar 2025 14:59:18 +0700 Subject: [PATCH 33/52] feat: add more test cases --- .../v3/client/internal/RestClient.java | 6 +- .../v3/client/InfluxDBClientTest.java | 69 ++++++++- .../v3/client/testdata/docker.com.pem | 33 +++++ .../client/testdata/influxdb-certificate.pem | 31 ++++ .../v3/client/testdata/valid-certificates.pem | 138 ------------------ 5 files changed, 130 insertions(+), 147 deletions(-) create mode 100644 src/test/java/com/influxdb/v3/client/testdata/docker.com.pem create mode 100644 src/test/java/com/influxdb/v3/client/testdata/influxdb-certificate.pem delete mode 100644 src/test/java/com/influxdb/v3/client/testdata/valid-certificates.pem diff --git a/src/main/java/com/influxdb/v3/client/internal/RestClient.java b/src/main/java/com/influxdb/v3/client/internal/RestClient.java index f08b705c..3474ae7f 100644 --- a/src/main/java/com/influxdb/v3/client/internal/RestClient.java +++ b/src/main/java/com/influxdb/v3/client/internal/RestClient.java @@ -123,15 +123,13 @@ public void checkServerTrusted( if (baseUrl.startsWith("https")) { try { SSLContext sslContext = SSLContext.getInstance("TLS"); - if (config.getDisableServerCertificateValidation()) { - sslContext.init(null, TRUST_ALL_CERTS, new SecureRandom()); - builder.sslContext(sslContext); - } + sslContext.init(null, TRUST_ALL_CERTS, new SecureRandom()); if (config.certificateFilePath() != null && !config.getDisableServerCertificateValidation()) { X509TrustManager x509TrustManager = getX509TrustManagerFromFile(config.certificateFilePath()); sslContext.init(null, new X509TrustManager[]{x509TrustManager}, new SecureRandom()); } + builder.sslContext(sslContext); } catch (Exception e) { throw new RuntimeException(e); } diff --git a/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java b/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java index 21ea2601..7c325b1b 100644 --- a/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java +++ b/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java @@ -45,7 +45,7 @@ public class InfluxDBClientTest { @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_TOKEN", matches = ".*") @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_DATABASE", matches = ".*") @Test - void testQueryProxyAndSslCertificate() { + void testQueryWithProxy() { String proxyUrl = "http://127.0.0.1:10000"; try { // Continue to run this test only if Envoy proxy is running in this address http://127.0.0.1:10000 @@ -55,15 +55,11 @@ void testQueryProxyAndSslCertificate() { return; } - // This is real certificate downloaded from https://cloud2.influxdata.com - String certificateFilePath = "src/test/java/com/influxdb/v3/client/testdata/valid-certificates.pem"; - ClientConfig clientConfig = new ClientConfig.Builder() .host(System.getenv("TESTING_INFLUXDB_URL")) .token(System.getenv("TESTING_INFLUXDB_TOKEN").toCharArray()) .database(System.getenv("TESTING_INFLUXDB_DATABASE")) .proxyUrl(proxyUrl) - .certificateFilePath(certificateFilePath) .build(); InfluxDBClient influxDBClient = InfluxDBClient.getInstance(clientConfig); @@ -80,6 +76,56 @@ void testQueryProxyAndSslCertificate() { } } + @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_URL", matches = ".*") + @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_TOKEN", matches = ".*") + @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_DATABASE", matches = ".*") + @Test + void correctSslCertificates() throws Exception { + // This is real certificate downloaded from https://cloud2.influxdata.com + String influxDBcertificateFile = "src/test/java/com/influxdb/v3/client/testdata/influxdb-certificate.pem"; + + ClientConfig clientConfig = new ClientConfig.Builder() + .host(System.getenv("TESTING_INFLUXDB_URL")) + .token(System.getenv("TESTING_INFLUXDB_TOKEN").toCharArray()) + .database(System.getenv("TESTING_INFLUXDB_DATABASE")) + .certificateFilePath(influxDBcertificateFile) + .build(); + InfluxDBClient influxDBClient = InfluxDBClient.getInstance(clientConfig); + assertGetdataSuccess(influxDBClient); + } + + @Test + void wrongSslCertificate() { + String certificateFile = "src/test/java/com/influxdb/v3/client/testdata/docker.com.pem"; + + ClientConfig clientConfig = new ClientConfig.Builder() + .host(System.getenv("TESTING_INFLUXDB_URL")) + .token(System.getenv("TESTING_INFLUXDB_TOKEN").toCharArray()) + .database(System.getenv("TESTING_INFLUXDB_DATABASE")) + .certificateFilePath(certificateFile) + .build(); + InfluxDBClient influxDBClient = InfluxDBClient.getInstance(clientConfig); + Assertions.assertThatThrownBy(() -> assertGetdataSuccess(influxDBClient)) + .hasMessageContaining("PKIX path building failed"); + } + + @Test + void disableServerCertificateValidation() throws Exception { + String wrongCertificateFile = "src/test/java/com/influxdb/v3/client/testdata/docker.com.pem"; + + ClientConfig clientConfig = new ClientConfig.Builder() + .host(System.getenv("TESTING_INFLUXDB_URL")) + .token(System.getenv("TESTING_INFLUXDB_TOKEN").toCharArray()) + .database(System.getenv("TESTING_INFLUXDB_DATABASE")) + .disableServerCertificateValidation(true) + .certificateFilePath(wrongCertificateFile) + .build(); + + // Test succeeded with wrong certificate file because disableServerCertificateValidation is true + InfluxDBClient influxDBClient = InfluxDBClient.getInstance(clientConfig); + assertGetdataSuccess(influxDBClient); + } + @Test void withProxyUrl() { String proxyUrl = "http://127.0.0.1:10000"; @@ -234,4 +280,17 @@ public void testQuery() throws Exception { } } } + + private void assertGetdataSuccess(InfluxDBClient influxDBClient) throws Exception { + influxDBClient.writePoint( + Point.measurement("test1") + .setField("field", "field1") + ); + try (Stream stream = influxDBClient.queryPoints("SELECT * FROM test1")) { + stream.findFirst() + .ifPresent(pointValues -> { + Assertions.assertThat(pointValues.getField("field")).isEqualTo("field1"); + }); + } + } } diff --git a/src/test/java/com/influxdb/v3/client/testdata/docker.com.pem b/src/test/java/com/influxdb/v3/client/testdata/docker.com.pem new file mode 100644 index 00000000..ac9ed44c --- /dev/null +++ b/src/test/java/com/influxdb/v3/client/testdata/docker.com.pem @@ -0,0 +1,33 @@ +-----BEGIN CERTIFICATE----- +MIIFxDCCBKygAwIBAgIQDE0Qon/WHglZ2jXwZzD0xjANBgkqhkiG9w0BAQsFADA8 +MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRwwGgYDVQQDExNBbWF6b24g +UlNBIDIwNDggTTAyMB4XDTI0MDgxODAwMDAwMFoXDTI1MDkxNjIzNTk1OVowFzEV +MBMGA1UEAwwMKi5kb2NrZXIuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAytONEwLLBXfyepD/iE7N76+xGDWE/7g21rpPRejCobpaKGVKSL4Y8Pf9 +whjh5pzBLxcpQMpYcg/oW+Cp4scjhXyi9yqrOC2Vf26DRA3ufjbescZUjPP28mPO +N1gGQhnr0Sa7mbhNo5JVE7yxLrjhAZFCdEpl1LYdfosYxeBowVOaxBsGfUWCxYuI +HbolTUUNWJKaAN7knKmrHF0a2a6BftaTyFK/6N1FV3rXs5oD+5DEYVFN8193fdz5 +DUcf5p7xzjx9yXmHfdomznUPL5Sja2FSigH+Gm6EG3cBKylVCpafwQhbYbpdkP12 +p7KtsPGUWIwBAyRr1AUqx0ceIafa9wIDAQABo4IC5TCCAuEwHwYDVR0jBBgwFoAU +wDFSzVpQw4J8dHHOy+mc+XrrguIwHQYDVR0OBBYEFFgCnhEuuG5ptVcvPfBJZssU +U6jFMBcGA1UdEQQQMA6CDCouZG9ja2VyLmNvbTATBgNVHSAEDDAKMAgGBmeBDAEC +ATAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMC +MDsGA1UdHwQ0MDIwMKAuoCyGKmh0dHA6Ly9jcmwucjJtMDIuYW1hem9udHJ1c3Qu +Y29tL3IybTAyLmNybDB1BggrBgEFBQcBAQRpMGcwLQYIKwYBBQUHMAGGIWh0dHA6 +Ly9vY3NwLnIybTAyLmFtYXpvbnRydXN0LmNvbTA2BggrBgEFBQcwAoYqaHR0cDov +L2NydC5yMm0wMi5hbWF6b250cnVzdC5jb20vcjJtMDIuY2VyMAwGA1UdEwEB/wQC +MAAwggF+BgorBgEEAdZ5AgQCBIIBbgSCAWoBaAB3AN3cyjSV1+EWBeeVMvrHn/g9 +HFDf2wA6FBJ2Ciysu8gqAAABkWTCKI4AAAQDAEgwRgIhALzND2kn+PR4aObDiWGv +7QJZ/z4i/vhAGjd/vp2hjt4HAiEAytgsAcPUFd/Y98n5EQkMg6GBSUUygBMc7+Xk +UVJXFgcAdQDm0jFjQHeMwRBBBtdxuc7B0kD2loSG+7qHMh39HjeOUAAAAZFkwiic +AAAEAwBGMEQCIGXbP5ughe+EksczYEErOqY1LZHi9/SmXcp6/vAeuXBmAiB16Sw7 +1sPB/CpKq75/pEwb5pamTdmeEIaHtGQTkTMZ5QB2AMz7D2qFcQll/pWbU87psnwi +6YVcDZeNtql+VMD+TA2wAAABkWTCKIoAAAQDAEcwRQIgX2WsD3ThDwalMCYqmf+X +ICS9imyYmwKXJbfkSnMH/HkCIQCEkDrOAJZG1fGfyOzhSPHWPMxbuGwV18jBGe52 +D9PPQTANBgkqhkiG9w0BAQsFAAOCAQEAcW8Z3+JzqfGTYX+MBk2pQvo8msx+fINU +ZzORUcFUNV0467G/Kc780S8GRxF8dr90WaFctMvw8yDOipfj0sacGJFVFFf5XoWu +1EqYyx3hgMLCQ5DzjAoY4X1KsfPRBe2DCsqf+Nt/TVzgVjOSglURBWKV2T+Av78H +HiMjtEUZbatvuKvUg5S26dvUxXseN/8Jbbt9MCCGascPOf+zXGysoBSwglt0Nz7W +hjXnY+BPeLD38ouUGx0R+sZbXICR6BIxtT4GgOcmJJ/KT3fcMObhsihiq6lO1aql +Yo4AvWpg2tJtwFrG4ooDRyyARljHMUMIkuTz9Dypl/dnJJfzAQLjVA== +-----END CERTIFICATE----- diff --git a/src/test/java/com/influxdb/v3/client/testdata/influxdb-certificate.pem b/src/test/java/com/influxdb/v3/client/testdata/influxdb-certificate.pem new file mode 100644 index 00000000..b85c8037 --- /dev/null +++ b/src/test/java/com/influxdb/v3/client/testdata/influxdb-certificate.pem @@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw +TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh +cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4 +WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu +ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY +MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc +h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+ +0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U +A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW +T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH +B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC +B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv +KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn +OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn +jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw +qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI +rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq +hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL +ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ +3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK +NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5 +ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur +TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC +jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc +oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq +4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA +mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d +emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc= +-----END CERTIFICATE----- diff --git a/src/test/java/com/influxdb/v3/client/testdata/valid-certificates.pem b/src/test/java/com/influxdb/v3/client/testdata/valid-certificates.pem deleted file mode 100644 index 1613beac..00000000 --- a/src/test/java/com/influxdb/v3/client/testdata/valid-certificates.pem +++ /dev/null @@ -1,138 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw -TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh -cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4 -WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu -ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY -MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc -h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+ -0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U -A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW -T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH -B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC -B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv -KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn -OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn -jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw -qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI -rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV -HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq -hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL -ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ -3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK -NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5 -ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur -TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC -jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc -oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq -4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA -mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d -emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc= ------END CERTIFICATE----- - ------BEGIN CERTIFICATE----- -MIINYTCCDQagAwIBAgIRALQPM3zi5SVWCcng/hZpShIwCgYIKoZIzj0EAwIwOzEL -MAkGA1UEBhMCVVMxHjAcBgNVBAoTFUdvb2dsZSBUcnVzdCBTZXJ2aWNlczEMMAoG -A1UEAxMDV0UyMB4XDTI1MDIyNjE1MzMwM1oXDTI1MDUyMTE1MzMwMlowFzEVMBMG -A1UEAwwMKi5nb29nbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEgY2u -jvbPkuQiKZw9XHFP0GrdujA0tw6feXg2eVb3bWPQ7M0lJ/of3dlc9J/NQ8BjBrrn -bObLpB/4C3PjqziyQqOCDA0wggwJMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAK -BggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBTKaaMWpKmNeZC6ky5y -0iHRZX20szAfBgNVHSMEGDAWgBR1vsR3ron2RDd9z7FoHx0a69w0WTBYBggrBgEF -BQcBAQRMMEowIQYIKwYBBQUHMAGGFWh0dHA6Ly9vLnBraS5nb29nL3dlMjAlBggr -BgEFBQcwAoYZaHR0cDovL2kucGtpLmdvb2cvd2UyLmNydDCCCeQGA1UdEQSCCdsw -ggnXggwqLmdvb2dsZS5jb22CFiouYXBwZW5naW5lLmdvb2dsZS5jb22CCSouYmRu -LmRldoIVKi5vcmlnaW4tdGVzdC5iZG4uZGV2ghIqLmNsb3VkLmdvb2dsZS5jb22C -GCouY3Jvd2Rzb3VyY2UuZ29vZ2xlLmNvbYIYKi5kYXRhY29tcHV0ZS5nb29nbGUu -Y29tggsqLmdvb2dsZS5jYYILKi5nb29nbGUuY2yCDiouZ29vZ2xlLmNvLmlugg4q -Lmdvb2dsZS5jby5qcIIOKi5nb29nbGUuY28udWuCDyouZ29vZ2xlLmNvbS5hcoIP -Ki5nb29nbGUuY29tLmF1gg8qLmdvb2dsZS5jb20uYnKCDyouZ29vZ2xlLmNvbS5j -b4IPKi5nb29nbGUuY29tLm14gg8qLmdvb2dsZS5jb20udHKCDyouZ29vZ2xlLmNv -bS52boILKi5nb29nbGUuZGWCCyouZ29vZ2xlLmVzggsqLmdvb2dsZS5mcoILKi5n -b29nbGUuaHWCCyouZ29vZ2xlLml0ggsqLmdvb2dsZS5ubIILKi5nb29nbGUucGyC -CyouZ29vZ2xlLnB0gg8qLmdvb2dsZWFwaXMuY26CESouZ29vZ2xldmlkZW8uY29t -ggwqLmdzdGF0aWMuY26CECouZ3N0YXRpYy1jbi5jb22CD2dvb2dsZWNuYXBwcy5j -boIRKi5nb29nbGVjbmFwcHMuY26CEWdvb2dsZWFwcHMtY24uY29tghMqLmdvb2ds -ZWFwcHMtY24uY29tggxna2VjbmFwcHMuY26CDiouZ2tlY25hcHBzLmNughJnb29n -bGVkb3dubG9hZHMuY26CFCouZ29vZ2xlZG93bmxvYWRzLmNughByZWNhcHRjaGEu -bmV0LmNughIqLnJlY2FwdGNoYS5uZXQuY26CEHJlY2FwdGNoYS1jbi5uZXSCEiou -cmVjYXB0Y2hhLWNuLm5ldIILd2lkZXZpbmUuY26CDSoud2lkZXZpbmUuY26CEWFt -cHByb2plY3Qub3JnLmNughMqLmFtcHByb2plY3Qub3JnLmNughFhbXBwcm9qZWN0 -Lm5ldC5jboITKi5hbXBwcm9qZWN0Lm5ldC5jboIXZ29vZ2xlLWFuYWx5dGljcy1j -bi5jb22CGSouZ29vZ2xlLWFuYWx5dGljcy1jbi5jb22CF2dvb2dsZWFkc2Vydmlj -ZXMtY24uY29tghkqLmdvb2dsZWFkc2VydmljZXMtY24uY29tghFnb29nbGV2YWRz -LWNuLmNvbYITKi5nb29nbGV2YWRzLWNuLmNvbYIRZ29vZ2xlYXBpcy1jbi5jb22C -EyouZ29vZ2xlYXBpcy1jbi5jb22CFWdvb2dsZW9wdGltaXplLWNuLmNvbYIXKi5n -b29nbGVvcHRpbWl6ZS1jbi5jb22CEmRvdWJsZWNsaWNrLWNuLm5ldIIUKi5kb3Vi -bGVjbGljay1jbi5uZXSCGCouZmxzLmRvdWJsZWNsaWNrLWNuLm5ldIIWKi5nLmRv -dWJsZWNsaWNrLWNuLm5ldIIOZG91YmxlY2xpY2suY26CECouZG91YmxlY2xpY2su -Y26CFCouZmxzLmRvdWJsZWNsaWNrLmNughIqLmcuZG91YmxlY2xpY2suY26CEWRh -cnRzZWFyY2gtY24ubmV0ghMqLmRhcnRzZWFyY2gtY24ubmV0gh1nb29nbGV0cmF2 -ZWxhZHNlcnZpY2VzLWNuLmNvbYIfKi5nb29nbGV0cmF2ZWxhZHNlcnZpY2VzLWNu -LmNvbYIYZ29vZ2xldGFnc2VydmljZXMtY24uY29tghoqLmdvb2dsZXRhZ3NlcnZp -Y2VzLWNuLmNvbYIXZ29vZ2xldGFnbWFuYWdlci1jbi5jb22CGSouZ29vZ2xldGFn -bWFuYWdlci1jbi5jb22CGGdvb2dsZXN5bmRpY2F0aW9uLWNuLmNvbYIaKi5nb29n -bGVzeW5kaWNhdGlvbi1jbi5jb22CJCouc2FmZWZyYW1lLmdvb2dsZXN5bmRpY2F0 -aW9uLWNuLmNvbYIWYXBwLW1lYXN1cmVtZW50LWNuLmNvbYIYKi5hcHAtbWVhc3Vy -ZW1lbnQtY24uY29tggtndnQxLWNuLmNvbYINKi5ndnQxLWNuLmNvbYILZ3Z0Mi1j -bi5jb22CDSouZ3Z0Mi1jbi5jb22CCzJtZG4tY24ubmV0gg0qLjJtZG4tY24ubmV0 -ghRnb29nbGVmbGlnaHRzLWNuLm5ldIIWKi5nb29nbGVmbGlnaHRzLWNuLm5ldIIM -YWRtb2ItY24uY29tgg4qLmFkbW9iLWNuLmNvbYIUZ29vZ2xlc2FuZGJveC1jbi5j -b22CFiouZ29vZ2xlc2FuZGJveC1jbi5jb22CHiouc2FmZW51cC5nb29nbGVzYW5k -Ym94LWNuLmNvbYINKi5nc3RhdGljLmNvbYIUKi5tZXRyaWMuZ3N0YXRpYy5jb22C -CiouZ3Z0MS5jb22CESouZ2NwY2RuLmd2dDEuY29tggoqLmd2dDIuY29tgg4qLmdj -cC5ndnQyLmNvbYIQKi51cmwuZ29vZ2xlLmNvbYIWKi55b3V0dWJlLW5vY29va2ll -LmNvbYILKi55dGltZy5jb22CC2FuZHJvaWQuY29tgg0qLmFuZHJvaWQuY29tghMq -LmZsYXNoLmFuZHJvaWQuY29tggRnLmNuggYqLmcuY26CBGcuY2+CBiouZy5jb4IG -Z29vLmdsggp3d3cuZ29vLmdsghRnb29nbGUtYW5hbHl0aWNzLmNvbYIWKi5nb29n -bGUtYW5hbHl0aWNzLmNvbYIKZ29vZ2xlLmNvbYISZ29vZ2xlY29tbWVyY2UuY29t -ghQqLmdvb2dsZWNvbW1lcmNlLmNvbYIIZ2dwaHQuY26CCiouZ2dwaHQuY26CCnVy -Y2hpbi5jb22CDCoudXJjaGluLmNvbYIIeW91dHUuYmWCC3lvdXR1YmUuY29tgg0q -LnlvdXR1YmUuY29tghFtdXNpYy55b3V0dWJlLmNvbYITKi5tdXNpYy55b3V0dWJl -LmNvbYIUeW91dHViZWVkdWNhdGlvbi5jb22CFioueW91dHViZWVkdWNhdGlvbi5j -b22CD3lvdXR1YmVraWRzLmNvbYIRKi55b3V0dWJla2lkcy5jb22CBXl0LmJlggcq -Lnl0LmJlghphbmRyb2lkLmNsaWVudHMuZ29vZ2xlLmNvbYITKi5hbmRyb2lkLmdv -b2dsZS5jboISKi5jaHJvbWUuZ29vZ2xlLmNughYqLmRldmVsb3BlcnMuZ29vZ2xl -LmNughUqLmFpc3R1ZGlvLmdvb2dsZS5jb20wEwYDVR0gBAwwCjAIBgZngQwBAgEw -NgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2MucGtpLmdvb2cvd2UyLzY0T1VJVnpw -WlY0LmNybDCCAQMGCisGAQQB1nkCBAIEgfQEgfEA7wB1AM8RVu7VLnyv84db2Wku -m+kacWdKsBfsrAHSW3fOzDsIAAABlUMa3KQAAAQDAEYwRAIgbFT96GaW9xdF/H3T -R9A8aKomiq6jRak+HuHJKeYZKbICIFj0lmIw2MOCmAFoPML8Do+XUopVVJGpvKum -UZ3/H1ZBAHYAfVkeEuF4KnscYWd8Xv340IdcFKBOlZ65Ay/ZDowuebgAAAGVQxrc -mAAABAMARzBFAiA1pA/zxlqWAUktHGVu/3MlUzPsjEcaRHOEqw4qFdXIcgIhALwo -K02gj5Eep6saapUuV9BRJ8S5T4iydYXSoKuINbtcMAoGCCqGSM49BAMCA0kAMEYC -IQCe7kXY4zHS22OUlCThOBy44kLyCaMS20ylMx0JWcjHqQIhAIiNQSfvChn4LD5B -TtlK9da3ocqcq85/6pDQ4Cx7a2Ej ------END CERTIFICATE----- - ------BEGIN CERTIFICATE----- -MIIFSzCCBDOgAwIBAgISA+oZlVmojyzdwsUR47BXXUkOMA0GCSqGSIb3DQEBCwUA -MDMxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQwwCgYDVQQD -EwNSMTAwHhcNMjUwMzA2MDUxNDM2WhcNMjUwNjA0MDUxNDM1WjAuMSwwKgYDVQQD -EyNjbi1wcm9kMzAxLXVzLWVhc3QtNC5pbmZsdXhkYXRhLmNvbTCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBANufjJuDVC5JX7FkgtJTsTY4BgXKhJ2CNr7S -Y0JRZWEMGiPE1LIusHYTIgSMR7DqkQubXTIst+GQCd1I0TaPq0JOgUcElPJ/Hroc -UeDXUmkwPB9oyUqAEZE7N1QhZPfrzKtizvt3y+lcMLSrD2npFnSQXDotUonnCgnV -/wviPowV3rEBqUkEmfeNaPqWwNhS5vGAS9nHq+VhJl63i4MV6VVUhsmXKNJpwj+S -6pferlhLRkPFO7T+IOLMOoM50lrZZk2D359+JVG2UVQknlWzPljteikY2GRahIam -mbQwAtdCX0dcz5x5EXtN4/Au4SFzHZAWuhIm0i3VMcvs36RcW18CAwEAAaOCAlww -ggJYMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUH -AwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUi2nfPdxKxh481jUurQRTJ01g8JQw -HwYDVR0jBBgwFoAUu7zDR6XkvKnGw6RyDBCNojXhyOgwVwYIKwYBBQUHAQEESzBJ -MCIGCCsGAQUFBzABhhZodHRwOi8vcjEwLm8ubGVuY3Iub3JnMCMGCCsGAQUFBzAC -hhdodHRwOi8vcjEwLmkubGVuY3Iub3JnLzBkBgNVHREEXTBbghVjbG91ZDIuaW5m -bHV4ZGF0YS5jb22CI2NuLXByb2QzMDEtdXMtZWFzdC00LmluZmx1eGRhdGEuY29t -gh1zdGFnaW5nLmNsb3VkMi5pbmZsdXhkYXRhLmNvbTATBgNVHSAEDDAKMAgGBmeB -DAECATCCAQMGCisGAQQB1nkCBAIEgfQEgfEA7wB1AKLjCuRF772tm3447Udnd1PX -gluElNcrXhssxLlQpEfnAAABlWoWE1IAAAQDAEYwRAIgQNybPpI1UMVzFtTaaZAz -7m/XcSglDuT/mvEv6nrdt3YCIGfx58c5llPJGjWNUSPbbEpL22sKFPbXuLEO78nB -rHPTAHYAE0rfGrWYQgl4DG/vTHqRpBa3I0nOWFdq367ap8Kr4CIAAAGVahYUxwAA -BAMARzBFAiBHSneDjE19jyyftoe1V5J1XQBVcm7ftufbswguI4qB/QIhAOegRql3 -XPu0n8tq7/dfFeI1ChN7WhqqZxXZinDcr9rCMA0GCSqGSIb3DQEBCwUAA4IBAQAC -dgqfe0okFZ1g08EI4c8VMwYE8ii9z5VtM9bDf+2ukubahIlOBQ61glKuFkwr6yqU -yS5x/FUooq7yWYqMb/7zo/Xgb5/vpDfJblGi2oeuI3NBW1vu8Zkxa4rO1D8ypAPM -4JgsgtjYA4XOtTRoRmltlet3KvILPwFh0pTn9iDuLv0G8qf4eqezXpVj9QeZJknp -cr+tx8H7/0Kesy8coOzhkTXx3rjYbGce6JYlXHkyhMtppNcgHP8ly7CQCJjr4784 -+mVdGOYN+rswgsnwMDwGEjbQfvErSqKS1DZNxIpy8CJLwfWJUNU3pqHqKM9lp4dY -ZWSUzpxgWgtYEdvcvDIi ------END CERTIFICATE----- \ No newline at end of file From 44a0a834ba648cdf9e1c6c7f93bc144cab79be68 Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Thu, 20 Mar 2025 15:04:22 +0700 Subject: [PATCH 34/52] fix: linter --- src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java b/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java index 7c325b1b..c54a41c6 100644 --- a/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java +++ b/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java @@ -30,6 +30,7 @@ import java.util.Properties; import java.util.UUID; import java.util.stream.Stream; +import javax.annotation.Nonnull; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; @@ -281,7 +282,7 @@ public void testQuery() throws Exception { } } - private void assertGetdataSuccess(InfluxDBClient influxDBClient) throws Exception { + private void assertGetdataSuccess(@Nonnull final InfluxDBClient influxDBClient) throws Exception { influxDBClient.writePoint( Point.measurement("test1") .setField("field", "field1") From 24c16d5a9bb923f7cf0badab7baeeec86be4cfd3 Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Thu, 20 Mar 2025 16:02:49 +0700 Subject: [PATCH 35/52] refactor: change proxyUrl to proxyAddress --- .../java/com/influxdb/v3/ProxyExample.java | 6 +-- .../v3/client/config/ClientConfig.java | 37 ++++++++++--------- .../v3/client/internal/FlightSqlClient.java | 11 +++--- .../v3/client/internal/RestClient.java | 7 +--- .../v3/client/InfluxDBClientTest.java | 17 +++++---- .../client/internal/FlightSqlClientTest.java | 4 +- .../v3/client/internal/RestClientTest.java | 6 +-- 7 files changed, 44 insertions(+), 44 deletions(-) diff --git a/examples/src/main/java/com/influxdb/v3/ProxyExample.java b/examples/src/main/java/com/influxdb/v3/ProxyExample.java index dd43333b..4a910c9f 100644 --- a/examples/src/main/java/com/influxdb/v3/ProxyExample.java +++ b/examples/src/main/java/com/influxdb/v3/ProxyExample.java @@ -35,13 +35,13 @@ private ProxyExample() { } public static void main(final String[] args) throws Exception { // Run docker-compose.yml file to start Envoy proxy - String proxyUrl = "http://127.0.0.1:10000"; - String certificateFilePath = "src/test/java/com/influxdb/v3/client/testdata/valid-certificates.pem"; + String proxyAddress = new InetSocketAddress("localhost", 10000); + String certificateFilePath = "src/test/java/com/influxdb/v3/client/testdata/influxdb-certificate.pem"; ClientConfig clientConfig = new ClientConfig.Builder() .host(System.getenv("TESTING_INFLUXDB_URL")) .token(System.getenv("TESTING_INFLUXDB_TOKEN").toCharArray()) .database(System.getenv("TESTING_INFLUXDB_DATABASE")) - .proxyUrl(proxyUrl) + .proxyAddress(proxyAddress) .certificateFilePath(certificateFilePath) .build(); diff --git a/src/main/java/com/influxdb/v3/client/config/ClientConfig.java b/src/main/java/com/influxdb/v3/client/config/ClientConfig.java index e9d5f4ad..4cf2b138 100644 --- a/src/main/java/com/influxdb/v3/client/config/ClientConfig.java +++ b/src/main/java/com/influxdb/v3/client/config/ClientConfig.java @@ -22,6 +22,7 @@ package com.influxdb.v3.client.config; import java.net.Authenticator; +import java.net.InetSocketAddress; import java.net.MalformedURLException; import java.net.ProxySelector; import java.net.URL; @@ -58,7 +59,7 @@ * disable server certificate validation for HTTPS connections * *
  • proxy - HTTP proxy selector
  • - *
  • proxyUrl - Proxy url for query api and write api
  • + *
  • proxyAddress - Proxy address for query api and write api
  • *
  • queryApiProxy - HTTP query detector
  • *
  • authenticator - HTTP proxy authenticator
  • *
  • headers - headers to be added to requests
  • @@ -100,13 +101,13 @@ public final class ClientConfig { private final Duration timeout; private final Boolean allowHttpRedirects; private final Boolean disableServerCertificateValidation; - private final String proxyUrl; + private final InetSocketAddress proxyAddress; private final Authenticator authenticator; private final Map headers; private final String certificateFilePath; /** - * Deprecated use {@link #proxyUrl}. + * Deprecated use {@link #proxyAddress}. */ @Deprecated private final ProxySelector proxy; @@ -224,7 +225,7 @@ public Boolean getDisableServerCertificateValidation() { * Gets the proxy. * * @return the proxy, may be null - * Deprecated use {@link #proxyUrl} + * Deprecated use {@link #proxyAddress} */ @Nullable @Deprecated @@ -233,13 +234,13 @@ public ProxySelector getProxy() { } /** - * Gets the proxy url. + * Gets the proxy address. * - * @return the proxy url, may be null + * @return the proxy address, may be null */ @Nullable - public String getProxyUrl() { - return proxyUrl; + public InetSocketAddress getProxyAddress() { + return proxyAddress; } /** @@ -302,7 +303,7 @@ public boolean equals(final Object o) { && Objects.equals(allowHttpRedirects, that.allowHttpRedirects) && Objects.equals(disableServerCertificateValidation, that.disableServerCertificateValidation) && Objects.equals(proxy, that.proxy) - && Objects.equals(proxyUrl, that.proxyUrl) + && Objects.equals(proxyAddress, that.proxyAddress) && Objects.equals(authenticator, that.authenticator) && Objects.equals(headers, that.headers) && Objects.equals(certificateFilePath, that.certificateFilePath); @@ -313,7 +314,7 @@ public int hashCode() { return Objects.hash(host, Arrays.hashCode(token), authScheme, organization, database, writePrecision, gzipThreshold, timeout, allowHttpRedirects, disableServerCertificateValidation, - proxy, proxyUrl, authenticator, headers, + proxy, proxyAddress, authenticator, headers, defaultTags, certificateFilePath); } @@ -329,7 +330,7 @@ public String toString() { .add("allowHttpRedirects=" + allowHttpRedirects) .add("disableServerCertificateValidation=" + disableServerCertificateValidation) .add("proxy=" + proxy) - .add("proxyUrl=" + proxyUrl) + .add("proxyAddress=" + proxyAddress) .add("authenticator=" + authenticator) .add("headers=" + headers) .add("defaultTags=" + defaultTags) @@ -355,7 +356,7 @@ public static final class Builder { private Boolean allowHttpRedirects; private Boolean disableServerCertificateValidation; private ProxySelector proxy; - private String proxyUrl; + private InetSocketAddress proxyAddress; private Authenticator authenticator; private Map headers; private String certificateFilePath; @@ -511,7 +512,7 @@ public Builder disableServerCertificateValidation(@Nullable final Boolean disabl * * @param proxy Proxy selector. * @return this - * Deprecated use {@link #proxyUrl} + * Deprecated use {@link #proxyAddress} */ @Nonnull public Builder proxy(@Nullable final ProxySelector proxy) { @@ -521,15 +522,15 @@ public Builder proxy(@Nullable final ProxySelector proxy) { } /** - * Sets the proxy url. Default is 'null'. + * Sets the proxyAddress. Default is 'null'. * - * @param proxyUrl Proxy url. + * @param proxyAddress Proxy address. * @return this */ @Nonnull - public Builder proxyUrl(@Nullable final String proxyUrl) { + public Builder proxyAddress(@Nullable final InetSocketAddress proxyAddress) { - this.proxyUrl = proxyUrl; + this.proxyAddress = proxyAddress; return this; } @@ -726,7 +727,7 @@ private ClientConfig(@Nonnull final Builder builder) { disableServerCertificateValidation = builder.disableServerCertificateValidation != null ? builder.disableServerCertificateValidation : false; proxy = builder.proxy; - proxyUrl = builder.proxyUrl; + proxyAddress = builder.proxyAddress; authenticator = builder.authenticator; headers = builder.headers; certificateFilePath = builder.certificateFilePath; diff --git a/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java b/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java index 3b666236..1601a3dc 100644 --- a/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java +++ b/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java @@ -171,13 +171,13 @@ FlightClient createFlightClient(@Nonnull final ClientConfig config) { nettyChannelBuilder.usePlaintext(); } - if (config.getProxyUrl() != null) { - ProxyDetector proxyDetector = createProxyDetector(config.getHost(), config.getProxyUrl()); + if (config.getProxyAddress() != null) { + ProxyDetector proxyDetector = createProxyDetector(config.getHost(), config.getProxyAddress()); nettyChannelBuilder.proxyDetector(proxyDetector); } if (config.getProxy() != null) { - LOG.warn("proxy property will not work in query api, use proxyUrl property instead"); + LOG.warn("proxy property in ClientConfig will not work in query api, use proxyAddress property instead"); } nettyChannelBuilder.maxTraceEvents(0) @@ -272,14 +272,13 @@ private void setChannelTypeAndEventLoop(@Nonnull final NettyChannelBuilder netty } } - ProxyDetector createProxyDetector(@Nonnull final String hostUrl, @Nonnull final String proxyUrl) { - URI proxyUri = URI.create(proxyUrl); + ProxyDetector createProxyDetector(@Nonnull final String hostUrl, @Nonnull final InetSocketAddress proxyAddress) { URI hostUri = URI.create(hostUrl); return (targetServerAddress) -> { InetSocketAddress targetAddress = (InetSocketAddress) targetServerAddress; if (hostUri.getHost().equals(targetAddress.getHostString())) { return HttpConnectProxiedSocketAddress.newBuilder() - .setProxyAddress(new InetSocketAddress(proxyUri.getHost(), proxyUri.getPort())) + .setProxyAddress(proxyAddress) .setTargetAddress(targetAddress) .build(); } diff --git a/src/main/java/com/influxdb/v3/client/internal/RestClient.java b/src/main/java/com/influxdb/v3/client/internal/RestClient.java index 3474ae7f..d75299a9 100644 --- a/src/main/java/com/influxdb/v3/client/internal/RestClient.java +++ b/src/main/java/com/influxdb/v3/client/internal/RestClient.java @@ -22,9 +22,7 @@ package com.influxdb.v3.client.internal; import java.io.FileInputStream; -import java.net.InetSocketAddress; import java.net.ProxySelector; -import java.net.URI; import java.net.URISyntaxException; import java.net.http.HttpClient; import java.net.http.HttpRequest; @@ -106,9 +104,8 @@ public void checkServerTrusted( // default headers this.defaultHeaders = config.getHeaders() != null ? Map.copyOf(config.getHeaders()) : null; - if (config.getProxyUrl() != null) { - URI uri = URI.create(config.getProxyUrl()); - ProxySelector proxy = ProxySelector.of(new InetSocketAddress(uri.getHost(), uri.getPort())); + if (config.getProxyAddress() != null) { + ProxySelector proxy = ProxySelector.of(config.getProxyAddress()); builder.proxy(proxy); if (config.getAuthenticator() != null) { builder.authenticator(config.getAuthenticator()); diff --git a/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java b/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java index c54a41c6..f62e6175 100644 --- a/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java +++ b/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java @@ -23,6 +23,7 @@ import java.io.IOException; import java.math.BigInteger; +import java.net.InetSocketAddress; import java.net.URL; import java.net.URLConnection; import java.time.Instant; @@ -47,10 +48,12 @@ public class InfluxDBClientTest { @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_DATABASE", matches = ".*") @Test void testQueryWithProxy() { - String proxyUrl = "http://127.0.0.1:10000"; + InetSocketAddress proxyAddress = new InetSocketAddress("localhost", 10000); + try { // Continue to run this test only if Envoy proxy is running in this address http://127.0.0.1:10000 - URLConnection hpCon = new URL(proxyUrl).openConnection(); + String url = String.format("http://%s:%d/", proxyAddress.getHostName(), proxyAddress.getPort()); + URLConnection hpCon = new URL(url).openConnection(); hpCon.connect(); } catch (IOException e) { return; @@ -60,7 +63,7 @@ void testQueryWithProxy() { .host(System.getenv("TESTING_INFLUXDB_URL")) .token(System.getenv("TESTING_INFLUXDB_TOKEN").toCharArray()) .database(System.getenv("TESTING_INFLUXDB_DATABASE")) - .proxyUrl(proxyUrl) + .proxyAddress(proxyAddress) .build(); InfluxDBClient influxDBClient = InfluxDBClient.getInstance(clientConfig); @@ -128,12 +131,12 @@ void disableServerCertificateValidation() throws Exception { } @Test - void withProxyUrl() { - String proxyUrl = "http://127.0.0.1:10000"; + void withProxyAddress() { + InetSocketAddress proxyAddress = new InetSocketAddress("127.0.0.1", 10000); ClientConfig.Builder builder = new ClientConfig.Builder(); - builder.proxyUrl(proxyUrl); + builder.proxyAddress(proxyAddress); ClientConfig clientConfig = builder.build(); - Assertions.assertThat(clientConfig.getProxyUrl()).isEqualTo(proxyUrl); + Assertions.assertThat(clientConfig.getProxyAddress()).isEqualTo(proxyAddress); } @Test diff --git a/src/test/java/com/influxdb/v3/client/internal/FlightSqlClientTest.java b/src/test/java/com/influxdb/v3/client/internal/FlightSqlClientTest.java index bba68e79..f7c84cef 100644 --- a/src/test/java/com/influxdb/v3/client/internal/FlightSqlClientTest.java +++ b/src/test/java/com/influxdb/v3/client/internal/FlightSqlClientTest.java @@ -281,8 +281,8 @@ void createProxyDetector() { .build(); try (FlightSqlClient flightSqlClient = new FlightSqlClient(clientConfig)) { String hostUrl = "https://youtube.com"; - String proxyUrl = "https://facebook.com"; - ProxyDetector proxyDetector = flightSqlClient.createProxyDetector(hostUrl, proxyUrl); + InetSocketAddress proxyAddress = new InetSocketAddress("localhost", 10000); + ProxyDetector proxyDetector = flightSqlClient.createProxyDetector(hostUrl, proxyAddress); Assertions.assertThat(proxyDetector.proxyFor( new InetSocketAddress("142.250.198.142", 80) )).isNull(); diff --git a/src/test/java/com/influxdb/v3/client/internal/RestClientTest.java b/src/test/java/com/influxdb/v3/client/internal/RestClientTest.java index 6ec792ad..d76c98c8 100644 --- a/src/test/java/com/influxdb/v3/client/internal/RestClientTest.java +++ b/src/test/java/com/influxdb/v3/client/internal/RestClientTest.java @@ -292,12 +292,12 @@ public void proxy() throws InterruptedException { } @Test - public void proxyUrl() throws InterruptedException { + public void proxyAddress() throws InterruptedException { mockServer.enqueue(createResponse(200)); restClient = new RestClient(new ClientConfig.Builder() .host("http://foo.com:8086") - .proxyUrl(String.format("http://%s:%s", mockServer.getHostName(), mockServer.getPort())) + .proxyAddress(new InetSocketAddress(mockServer.getHostName(), mockServer.getPort())) .build()); restClient.request("ping", HttpMethod.GET, null, null, null); @@ -316,7 +316,7 @@ public void proxyWithAuthentication() throws InterruptedException { restClient = new RestClient(new ClientConfig.Builder() .host("http://foo.com:8086") - .proxyUrl(String.format("http://%s:%s", mockServer.getHostName(), mockServer.getPort())) + .proxyAddress(new InetSocketAddress(mockServer.getHostName(), mockServer.getPort())) .authenticator(new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { From 630edf7ee4c70b7bc14b473dbae40d8184cbdbff Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Thu, 20 Mar 2025 16:27:30 +0700 Subject: [PATCH 36/52] feat: add more test cases --- .../v3/client/internal/FlightSqlClientTest.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/test/java/com/influxdb/v3/client/internal/FlightSqlClientTest.java b/src/test/java/com/influxdb/v3/client/internal/FlightSqlClientTest.java index f7c84cef..6e819aee 100644 --- a/src/test/java/com/influxdb/v3/client/internal/FlightSqlClientTest.java +++ b/src/test/java/com/influxdb/v3/client/internal/FlightSqlClientTest.java @@ -25,6 +25,7 @@ import java.net.URISyntaxException; import java.util.Map; +import io.grpc.HttpConnectProxiedSocketAddress; import io.grpc.ProxyDetector; import io.grpc.internal.GrpcUtil; import org.apache.arrow.flight.CallHeaders; @@ -276,15 +277,23 @@ public void useParamsFromQueryConfig() throws Exception { @Test void createProxyDetector() { + String hostUrl = "https://localhost:80"; ClientConfig clientConfig = new ClientConfig.Builder() - .host("https://localhost:80") + .host(hostUrl) .build(); try (FlightSqlClient flightSqlClient = new FlightSqlClient(clientConfig)) { - String hostUrl = "https://youtube.com"; InetSocketAddress proxyAddress = new InetSocketAddress("localhost", 10000); ProxyDetector proxyDetector = flightSqlClient.createProxyDetector(hostUrl, proxyAddress); Assertions.assertThat(proxyDetector.proxyFor( - new InetSocketAddress("142.250.198.142", 80) + new InetSocketAddress("localhost", 80) + )).isEqualTo(HttpConnectProxiedSocketAddress.newBuilder() + .setProxyAddress(proxyAddress) + .setTargetAddress(new InetSocketAddress("localhost", 80)) + .build()); + + // Return null case + Assertions.assertThat(proxyDetector.proxyFor( + new InetSocketAddress("123.2.3.1", 80) )).isNull(); } catch (Exception e) { throw new RuntimeException(e); From cb02b24e5bd2a0007e5b63afffea8460b14432d6 Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Mon, 24 Mar 2025 11:25:48 +0700 Subject: [PATCH 37/52] refacor: client config --- .../java/com/influxdb/v3/ProxyExample.java | 35 ++-- .../v3/client/config/ClientConfig.java | 65 +++--- .../v3/client/internal/FlightSqlClient.java | 35 ++-- .../v3/client/internal/RestClient.java | 15 +- .../v3/client/InfluxDBClientTest.java | 174 +--------------- .../v3/client/integration/E2ETest.java | 186 ++++++++++++++++++ .../client/internal/FlightSqlClientTest.java | 10 +- .../v3/client/internal/RestClientTest.java | 6 +- 8 files changed, 276 insertions(+), 250 deletions(-) create mode 100644 src/test/java/com/influxdb/v3/client/integration/E2ETest.java diff --git a/examples/src/main/java/com/influxdb/v3/ProxyExample.java b/examples/src/main/java/com/influxdb/v3/ProxyExample.java index 4a910c9f..f65c0ba0 100644 --- a/examples/src/main/java/com/influxdb/v3/ProxyExample.java +++ b/examples/src/main/java/com/influxdb/v3/ProxyExample.java @@ -30,32 +30,31 @@ public final class ProxyExample { - private ProxyExample() { } + private ProxyExample() { + } public static void main(final String[] args) throws Exception { // Run docker-compose.yml file to start Envoy proxy - String proxyAddress = new InetSocketAddress("localhost", 10000); - String certificateFilePath = "src/test/java/com/influxdb/v3/client/testdata/influxdb-certificate.pem"; + String proxyUrl = "http://localhost:10000"; + String sslRootsFilePath = "src/test/java/com/influxdb/v3/client/testdata/influxdb-certificate.pem"; ClientConfig clientConfig = new ClientConfig.Builder() - .host(System.getenv("TESTING_INFLUXDB_URL")) - .token(System.getenv("TESTING_INFLUXDB_TOKEN").toCharArray()) - .database(System.getenv("TESTING_INFLUXDB_DATABASE")) - .proxyAddress(proxyAddress) - .certificateFilePath(certificateFilePath) + .host(System.getenv("INFLUXDB_URL")) + .token(System.getenv("INFLUXDB_TOKEN").toCharArray()) + .database(System.getenv("INFLUXDB_DATABASE")) + .proxyUrl(proxyUrl) + .sslRootsFilePath(sslRootsFilePath) .build(); InfluxDBClient influxDBClient = InfluxDBClient.getInstance(clientConfig); - influxDBClient.writePoint( - Point.measurement("test1") - .setField("field", "field1") - ); - - try (Stream stream = influxDBClient.queryPoints("SELECT * FROM test1")) { - stream.findFirst() - .ifPresent(pointValues -> { - Assertions.assertThat(pointValues.getField("field")).isEqualTo("field1"); - }); + Point point = Point.measurement("Home") + .setTag("room", "Kitchen") + .setField("temp", 12.7) + .setField("hum", 37); + influxDBClient.writePoint(point); + + try (Stream stream = influxDBClient.queryPoints("SELECT * FROM home")) { + stream.findFirst().ifPresent(System.out::println); } } } diff --git a/src/main/java/com/influxdb/v3/client/config/ClientConfig.java b/src/main/java/com/influxdb/v3/client/config/ClientConfig.java index 4cf2b138..fc248e30 100644 --- a/src/main/java/com/influxdb/v3/client/config/ClientConfig.java +++ b/src/main/java/com/influxdb/v3/client/config/ClientConfig.java @@ -22,7 +22,6 @@ package com.influxdb.v3.client.config; import java.net.Authenticator; -import java.net.InetSocketAddress; import java.net.MalformedURLException; import java.net.ProxySelector; import java.net.URL; @@ -58,12 +57,10 @@ *
  • disableServerCertificateValidation - * disable server certificate validation for HTTPS connections *
  • - *
  • proxy - HTTP proxy selector
  • - *
  • proxyAddress - Proxy address for query api and write api
  • - *
  • queryApiProxy - HTTP query detector
  • + *
  • proxyUrl - Proxy url for query api and write api
  • *
  • authenticator - HTTP proxy authenticator
  • *
  • headers - headers to be added to requests
  • - *
  • certificateFilePath - Path to the stored certificates file
  • + *
  • sslRootsFilePath - Path to the stored certificates file in PEM format
  • * *

    * If you want to create a client with custom configuration, you can use following code: @@ -76,7 +73,7 @@ * .database("my-database") * .writePrecision(WritePrecision.S) * .gzipThreshold(4096) - * .proxy(ProxySelector.of(new InetSocketAddress("proxy.local", 8888))) + * .proxyUrl("http://localhost:10000") * .build(); * * try (InfluxDBClient client = InfluxDBClient.getInstance(config)) { @@ -101,13 +98,13 @@ public final class ClientConfig { private final Duration timeout; private final Boolean allowHttpRedirects; private final Boolean disableServerCertificateValidation; - private final InetSocketAddress proxyAddress; + private final String proxyUrl; private final Authenticator authenticator; private final Map headers; - private final String certificateFilePath; + private final String sslRootsFilePath; /** - * Deprecated use {@link #proxyAddress}. + * Deprecated use {@link #proxyUrl}. */ @Deprecated private final ProxySelector proxy; @@ -225,7 +222,7 @@ public Boolean getDisableServerCertificateValidation() { * Gets the proxy. * * @return the proxy, may be null - * Deprecated use {@link #proxyAddress} + * Deprecated use {@link #proxyUrl} */ @Nullable @Deprecated @@ -234,13 +231,13 @@ public ProxySelector getProxy() { } /** - * Gets the proxy address. + * Gets the proxy url. * - * @return the proxy address, may be null + * @return the proxy url, may be null */ @Nullable - public InetSocketAddress getProxyAddress() { - return proxyAddress; + public String getProxyUrl() { + return proxyUrl; } /** @@ -249,8 +246,8 @@ public InetSocketAddress getProxyAddress() { * @return the certificates file path, may be null */ @Nullable - public String certificateFilePath() { - return certificateFilePath; + public String sslRootsFilePath() { + return sslRootsFilePath; } /** @@ -303,10 +300,10 @@ public boolean equals(final Object o) { && Objects.equals(allowHttpRedirects, that.allowHttpRedirects) && Objects.equals(disableServerCertificateValidation, that.disableServerCertificateValidation) && Objects.equals(proxy, that.proxy) - && Objects.equals(proxyAddress, that.proxyAddress) + && Objects.equals(proxyUrl, that.proxyUrl) && Objects.equals(authenticator, that.authenticator) && Objects.equals(headers, that.headers) - && Objects.equals(certificateFilePath, that.certificateFilePath); + && Objects.equals(sslRootsFilePath, that.sslRootsFilePath); } @Override @@ -314,8 +311,8 @@ public int hashCode() { return Objects.hash(host, Arrays.hashCode(token), authScheme, organization, database, writePrecision, gzipThreshold, timeout, allowHttpRedirects, disableServerCertificateValidation, - proxy, proxyAddress, authenticator, headers, - defaultTags, certificateFilePath); + proxy, proxyUrl, authenticator, headers, + defaultTags, sslRootsFilePath); } @Override @@ -330,11 +327,11 @@ public String toString() { .add("allowHttpRedirects=" + allowHttpRedirects) .add("disableServerCertificateValidation=" + disableServerCertificateValidation) .add("proxy=" + proxy) - .add("proxyAddress=" + proxyAddress) + .add("proxyUrl=" + proxyUrl) .add("authenticator=" + authenticator) .add("headers=" + headers) .add("defaultTags=" + defaultTags) - .add("certificateFilePath=" + certificateFilePath) + .add("sslRootsFilePath=" + sslRootsFilePath) .toString(); } @@ -356,10 +353,10 @@ public static final class Builder { private Boolean allowHttpRedirects; private Boolean disableServerCertificateValidation; private ProxySelector proxy; - private InetSocketAddress proxyAddress; + private String proxyUrl; private Authenticator authenticator; private Map headers; - private String certificateFilePath; + private String sslRootsFilePath; /** * Sets the URL of the InfluxDB server. @@ -512,7 +509,7 @@ public Builder disableServerCertificateValidation(@Nullable final Boolean disabl * * @param proxy Proxy selector. * @return this - * Deprecated use {@link #proxyAddress} + * Deprecated use {@link #proxyUrl} */ @Nonnull public Builder proxy(@Nullable final ProxySelector proxy) { @@ -522,15 +519,15 @@ public Builder proxy(@Nullable final ProxySelector proxy) { } /** - * Sets the proxyAddress. Default is 'null'. + * Sets the proxy url. Default is 'null'. * - * @param proxyAddress Proxy address. + * @param proxyUrl Proxy url. * @return this */ @Nonnull - public Builder proxyAddress(@Nullable final InetSocketAddress proxyAddress) { + public Builder proxyUrl(@Nullable final String proxyUrl) { - this.proxyAddress = proxyAddress; + this.proxyUrl = proxyUrl; return this; } @@ -582,13 +579,13 @@ public Builder headers(@Nullable final Map headers) { /** * Sets certificate file path. Default is 'null'. * - * @param certificateFilePath The certificate file path + * @param sslRootsFilePath The certificate file path * @return this */ @Nonnull - public Builder certificateFilePath(@Nullable final String certificateFilePath) { + public Builder sslRootsFilePath(@Nullable final String sslRootsFilePath) { - this.certificateFilePath = certificateFilePath; + this.sslRootsFilePath = sslRootsFilePath; return this; } @@ -727,9 +724,9 @@ private ClientConfig(@Nonnull final Builder builder) { disableServerCertificateValidation = builder.disableServerCertificateValidation != null ? builder.disableServerCertificateValidation : false; proxy = builder.proxy; - proxyAddress = builder.proxyAddress; + proxyUrl = builder.proxyUrl; authenticator = builder.authenticator; headers = builder.headers; - certificateFilePath = builder.certificateFilePath; + sslRootsFilePath = builder.sslRootsFilePath; } } diff --git a/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java b/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java index 1601a3dc..ef0d7f70 100644 --- a/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java +++ b/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java @@ -77,6 +77,12 @@ final class FlightSqlClient implements AutoCloseable { private final Map defaultHeaders = new HashMap<>(); private final ObjectMapper objectMapper = new ObjectMapper(); + private final List VALID_SCHEMAS = List.of( + LocationSchemes.GRPC, + LocationSchemes.GRPC_INSECURE, + LocationSchemes.GRPC_TLS, + LocationSchemes.GRPC_DOMAIN_SOCKET + ); FlightSqlClient(@Nonnull final ClientConfig config) { this(config, null); @@ -143,17 +149,11 @@ public void close() throws Exception { } @Nonnull - FlightClient createFlightClient(@Nonnull final ClientConfig config) { + private FlightClient createFlightClient(@Nonnull final ClientConfig config) { Location location = createLocation(config); final NettyChannelBuilder nettyChannelBuilder = NettyChannelBuilder.forTarget(location.getUri().getHost()); - var validSchemas = List.of( - LocationSchemes.GRPC, - LocationSchemes.GRPC_INSECURE, - LocationSchemes.GRPC_TLS, - LocationSchemes.GRPC_DOMAIN_SOCKET - ); - if (!validSchemas.contains(location.getUri().getScheme())) { + if (!VALID_SCHEMAS.contains(location.getUri().getScheme())) { throw new IllegalArgumentException( "Scheme is not supported: " + location.getUri().getScheme()); } @@ -171,13 +171,13 @@ FlightClient createFlightClient(@Nonnull final ClientConfig config) { nettyChannelBuilder.usePlaintext(); } - if (config.getProxyAddress() != null) { - ProxyDetector proxyDetector = createProxyDetector(config.getHost(), config.getProxyAddress()); + if (config.getProxyUrl() != null) { + ProxyDetector proxyDetector = createProxyDetector(config.getHost(), config.getProxyUrl()); nettyChannelBuilder.proxyDetector(proxyDetector); } if (config.getProxy() != null) { - LOG.warn("proxy property in ClientConfig will not work in query api, use proxyAddress property instead"); + LOG.warn("proxy property in ClientConfig will not work in query api, use proxyUrl property instead"); } nettyChannelBuilder.maxTraceEvents(0) @@ -193,8 +193,8 @@ SslContext createNettySslContext(@Nonnull final ClientConfig config) { SslContextBuilder sslContextBuilder; sslContextBuilder = GrpcSslContexts.forClient(); if (!config.getDisableServerCertificateValidation()) { - if (config.certificateFilePath() != null) { - try (FileInputStream fileInputStream = new FileInputStream(config.certificateFilePath())) { + if (config.sslRootsFilePath() != null) { + try (FileInputStream fileInputStream = new FileInputStream(config.sslRootsFilePath())) { sslContextBuilder.trustManager(fileInputStream); } } @@ -272,13 +272,14 @@ private void setChannelTypeAndEventLoop(@Nonnull final NettyChannelBuilder netty } } - ProxyDetector createProxyDetector(@Nonnull final String hostUrl, @Nonnull final InetSocketAddress proxyAddress) { - URI hostUri = URI.create(hostUrl); + ProxyDetector createProxyDetector(@Nonnull final String targetUrl, @Nonnull final String proxyUrl) { + URI targetUri = URI.create(targetUrl); + URI proxyUri = URI.create(proxyUrl); return (targetServerAddress) -> { InetSocketAddress targetAddress = (InetSocketAddress) targetServerAddress; - if (hostUri.getHost().equals(targetAddress.getHostString())) { + if (targetUri.getHost().equals(targetAddress.getHostString()) && targetUri.getPort() == targetAddress.getPort()) { return HttpConnectProxiedSocketAddress.newBuilder() - .setProxyAddress(proxyAddress) + .setProxyAddress(new InetSocketAddress(proxyUri.getHost(), proxyUri.getPort())) .setTargetAddress(targetAddress) .build(); } diff --git a/src/main/java/com/influxdb/v3/client/internal/RestClient.java b/src/main/java/com/influxdb/v3/client/internal/RestClient.java index d75299a9..387c68c0 100644 --- a/src/main/java/com/influxdb/v3/client/internal/RestClient.java +++ b/src/main/java/com/influxdb/v3/client/internal/RestClient.java @@ -22,7 +22,9 @@ package com.influxdb.v3.client.internal; import java.io.FileInputStream; +import java.net.InetSocketAddress; import java.net.ProxySelector; +import java.net.URI; import java.net.URISyntaxException; import java.net.http.HttpClient; import java.net.http.HttpRequest; @@ -104,8 +106,9 @@ public void checkServerTrusted( // default headers this.defaultHeaders = config.getHeaders() != null ? Map.copyOf(config.getHeaders()) : null; - if (config.getProxyAddress() != null) { - ProxySelector proxy = ProxySelector.of(config.getProxyAddress()); + if (config.getProxyUrl() != null) { + URI proxyUri = URI.create(config.getProxyUrl()); + ProxySelector proxy = ProxySelector.of(new InetSocketAddress(proxyUri.getHost(), proxyUri.getPort())); builder.proxy(proxy); if (config.getAuthenticator() != null) { builder.authenticator(config.getAuthenticator()); @@ -120,11 +123,11 @@ public void checkServerTrusted( if (baseUrl.startsWith("https")) { try { SSLContext sslContext = SSLContext.getInstance("TLS"); - sslContext.init(null, TRUST_ALL_CERTS, new SecureRandom()); - - if (config.certificateFilePath() != null && !config.getDisableServerCertificateValidation()) { - X509TrustManager x509TrustManager = getX509TrustManagerFromFile(config.certificateFilePath()); + if (config.sslRootsFilePath() != null && !config.getDisableServerCertificateValidation()) { + X509TrustManager x509TrustManager = getX509TrustManagerFromFile(config.sslRootsFilePath()); sslContext.init(null, new X509TrustManager[]{x509TrustManager}, new SecureRandom()); + } else { + sslContext.init(null, TRUST_ALL_CERTS, new SecureRandom()); } builder.sslContext(sslContext); } catch (Exception e) { diff --git a/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java b/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java index f62e6175..e1f1667f 100644 --- a/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java +++ b/src/test/java/com/influxdb/v3/client/InfluxDBClientTest.java @@ -21,131 +21,32 @@ */ package com.influxdb.v3.client; -import java.io.IOException; -import java.math.BigInteger; -import java.net.InetSocketAddress; -import java.net.URL; -import java.net.URLConnection; -import java.time.Instant; import java.util.Map; import java.util.Properties; -import java.util.UUID; -import java.util.stream.Stream; -import javax.annotation.Nonnull; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; import com.influxdb.v3.client.config.ClientConfig; -import com.influxdb.v3.client.write.WriteOptions; -import com.influxdb.v3.client.write.WritePrecision; public class InfluxDBClientTest { - @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_URL", matches = ".*") - @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_TOKEN", matches = ".*") - @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_DATABASE", matches = ".*") @Test - void testQueryWithProxy() { - InetSocketAddress proxyAddress = new InetSocketAddress("localhost", 10000); - - try { - // Continue to run this test only if Envoy proxy is running in this address http://127.0.0.1:10000 - String url = String.format("http://%s:%d/", proxyAddress.getHostName(), proxyAddress.getPort()); - URLConnection hpCon = new URL(url).openConnection(); - hpCon.connect(); - } catch (IOException e) { - return; - } - - ClientConfig clientConfig = new ClientConfig.Builder() - .host(System.getenv("TESTING_INFLUXDB_URL")) - .token(System.getenv("TESTING_INFLUXDB_TOKEN").toCharArray()) - .database(System.getenv("TESTING_INFLUXDB_DATABASE")) - .proxyAddress(proxyAddress) - .build(); - - InfluxDBClient influxDBClient = InfluxDBClient.getInstance(clientConfig); - influxDBClient.writePoint( - Point.measurement("test1") - .setField("field", "field1") - ); - - try (Stream stream = influxDBClient.queryPoints("SELECT * FROM test1")) { - stream.findFirst() - .ifPresent(pointValues -> { - Assertions.assertThat(pointValues.getField("field")).isEqualTo("field1"); - }); - } - } - - @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_URL", matches = ".*") - @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_TOKEN", matches = ".*") - @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_DATABASE", matches = ".*") - @Test - void correctSslCertificates() throws Exception { - // This is real certificate downloaded from https://cloud2.influxdata.com - String influxDBcertificateFile = "src/test/java/com/influxdb/v3/client/testdata/influxdb-certificate.pem"; - - ClientConfig clientConfig = new ClientConfig.Builder() - .host(System.getenv("TESTING_INFLUXDB_URL")) - .token(System.getenv("TESTING_INFLUXDB_TOKEN").toCharArray()) - .database(System.getenv("TESTING_INFLUXDB_DATABASE")) - .certificateFilePath(influxDBcertificateFile) - .build(); - InfluxDBClient influxDBClient = InfluxDBClient.getInstance(clientConfig); - assertGetdataSuccess(influxDBClient); - } - - @Test - void wrongSslCertificate() { - String certificateFile = "src/test/java/com/influxdb/v3/client/testdata/docker.com.pem"; - - ClientConfig clientConfig = new ClientConfig.Builder() - .host(System.getenv("TESTING_INFLUXDB_URL")) - .token(System.getenv("TESTING_INFLUXDB_TOKEN").toCharArray()) - .database(System.getenv("TESTING_INFLUXDB_DATABASE")) - .certificateFilePath(certificateFile) - .build(); - InfluxDBClient influxDBClient = InfluxDBClient.getInstance(clientConfig); - Assertions.assertThatThrownBy(() -> assertGetdataSuccess(influxDBClient)) - .hasMessageContaining("PKIX path building failed"); - } - - @Test - void disableServerCertificateValidation() throws Exception { - String wrongCertificateFile = "src/test/java/com/influxdb/v3/client/testdata/docker.com.pem"; - - ClientConfig clientConfig = new ClientConfig.Builder() - .host(System.getenv("TESTING_INFLUXDB_URL")) - .token(System.getenv("TESTING_INFLUXDB_TOKEN").toCharArray()) - .database(System.getenv("TESTING_INFLUXDB_DATABASE")) - .disableServerCertificateValidation(true) - .certificateFilePath(wrongCertificateFile) - .build(); - - // Test succeeded with wrong certificate file because disableServerCertificateValidation is true - InfluxDBClient influxDBClient = InfluxDBClient.getInstance(clientConfig); - assertGetdataSuccess(influxDBClient); - } - - @Test - void withProxyAddress() { - InetSocketAddress proxyAddress = new InetSocketAddress("127.0.0.1", 10000); + void withProxyUrl() { + String proxyUrl = "http://localhost:10000"; ClientConfig.Builder builder = new ClientConfig.Builder(); - builder.proxyAddress(proxyAddress); + builder.proxyUrl(proxyUrl); ClientConfig clientConfig = builder.build(); - Assertions.assertThat(clientConfig.getProxyAddress()).isEqualTo(proxyAddress); + Assertions.assertThat(clientConfig.getProxyUrl()).isEqualTo(proxyUrl); } @Test - void withCertificateFilePath() { + void withSslRootsFilePath() { String path = "/path/to/cert"; ClientConfig.Builder builder = new ClientConfig.Builder(); - builder.certificateFilePath(path); + builder.sslRootsFilePath(path); ClientConfig clientConfig = builder.build(); - Assertions.assertThat(clientConfig.certificateFilePath()).isEqualTo(path); + Assertions.assertThat(clientConfig.sslRootsFilePath()).isEqualTo(path); } @Test @@ -236,65 +137,4 @@ public void unsupportedQueryParams() throws Exception { } } - @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_URL", matches = ".*") - @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_TOKEN", matches = ".*") - @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_DATABASE", matches = ".*") - @Test - public void testQuery() throws Exception { - try (InfluxDBClient client = InfluxDBClient.getInstance( - System.getenv("TESTING_INFLUXDB_URL"), - System.getenv("TESTING_INFLUXDB_TOKEN").toCharArray(), - System.getenv("TESTING_INFLUXDB_DATABASE"), - null)) { - String uuid = UUID.randomUUID().toString(); - long timestamp = Instant.now().getEpochSecond(); - String record = String.format( - "host10,tag=empty " - + "name=\"intel\"," - + "mem_total=2048," - + "disk_free=100i," - + "temperature=100.86," - + "isActive=true," - + "testId=\"%s\" %d", - uuid, - timestamp - ); - client.writeRecord(record, new WriteOptions(null, WritePrecision.S, null)); - - Map parameters = Map.of("testId", uuid); - String sql = "Select * from host10 where \"testId\"=$testId"; - try (Stream stream = client.query(sql, parameters)) { - stream.findFirst() - .ifPresent(objects -> { - Assertions.assertThat(objects[0].getClass()).isEqualTo(Long.class); - Assertions.assertThat(objects[0]).isEqualTo(100L); - - Assertions.assertThat(objects[1].getClass()).isEqualTo(Boolean.class); - Assertions.assertThat(objects[1]).isEqualTo(true); - - Assertions.assertThat(objects[2].getClass()).isEqualTo(Double.class); - Assertions.assertThat(objects[2]).isEqualTo(2048.0); - - Assertions.assertThat(objects[3].getClass()).isEqualTo(String.class); - Assertions.assertThat(objects[3]).isEqualTo("intel"); - - Assertions.assertThat(objects[7].getClass()).isEqualTo(BigInteger.class); - Assertions.assertThat(objects[7]).isEqualTo(BigInteger.valueOf(timestamp * 1_000_000_000)); - }); - } - } - } - - private void assertGetdataSuccess(@Nonnull final InfluxDBClient influxDBClient) throws Exception { - influxDBClient.writePoint( - Point.measurement("test1") - .setField("field", "field1") - ); - try (Stream stream = influxDBClient.queryPoints("SELECT * FROM test1")) { - stream.findFirst() - .ifPresent(pointValues -> { - Assertions.assertThat(pointValues.getField("field")).isEqualTo("field1"); - }); - } - } } diff --git a/src/test/java/com/influxdb/v3/client/integration/E2ETest.java b/src/test/java/com/influxdb/v3/client/integration/E2ETest.java new file mode 100644 index 00000000..5d3188cc --- /dev/null +++ b/src/test/java/com/influxdb/v3/client/integration/E2ETest.java @@ -0,0 +1,186 @@ +package com.influxdb.v3.client.integration; + +import java.math.BigInteger; +import java.net.ConnectException; +import java.net.URL; +import java.net.URLConnection; +import java.time.Instant; +import java.util.Map; +import java.util.UUID; +import java.util.logging.Logger; +import java.util.stream.Stream; +import javax.annotation.Nonnull; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; + +import com.influxdb.v3.client.InfluxDBClient; +import com.influxdb.v3.client.Point; +import com.influxdb.v3.client.PointValues; +import com.influxdb.v3.client.config.ClientConfig; +import com.influxdb.v3.client.write.WriteOptions; +import com.influxdb.v3.client.write.WritePrecision; + +public class E2ETest { + + private static final java.util.logging.Logger LOG = Logger.getLogger(E2ETest.class.getName()); + + @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_URL", matches = ".*") + @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_TOKEN", matches = ".*") + @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_DATABASE", matches = ".*") + @Test + void testQueryWithProxy() { + String proxyUrl = "http://localhost:10000"; + + try { + // Continue to run this test only if Envoy proxy is running on this address http://localhost:10000 + String url = String.format("http://%s:%d/", "localhost", 10000); + URLConnection hpCon = new URL(url).openConnection(); + hpCon.connect(); + } catch (Exception e) { + if (e instanceof ConnectException && e.getMessage().equals("Connection refused")) { + LOG.warning("Tests with proxy have been skipped because no proxy is running on " + proxyUrl); + return; + } + } + + ClientConfig clientConfig = new ClientConfig.Builder() + .host(System.getenv("TESTING_INFLUXDB_URL")) + .token(System.getenv("TESTING_INFLUXDB_TOKEN").toCharArray()) + .database(System.getenv("TESTING_INFLUXDB_DATABASE")) + .proxyUrl(proxyUrl) + .build(); + + InfluxDBClient influxDBClient = InfluxDBClient.getInstance(clientConfig); + influxDBClient.writePoint( + Point.measurement("test1") + .setField("field", "field1") + ); + + try (Stream stream = influxDBClient.queryPoints("SELECT * FROM test1")) { + stream.findFirst() + .ifPresent(pointValues -> { + Assertions.assertThat(pointValues.getField("field")).isEqualTo("field1"); + }); + } + } + + @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_URL", matches = ".*") + @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_TOKEN", matches = ".*") + @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_DATABASE", matches = ".*") + @Test + void correctSslCertificates() throws Exception { + // This is real certificate downloaded from https://cloud2.influxdata.com + String influxDBcertificateFile = "src/test/java/com/influxdb/v3/client/testdata/influxdb-certificate.pem"; + + ClientConfig clientConfig = new ClientConfig.Builder() + .host(System.getenv("TESTING_INFLUXDB_URL")) + .token(System.getenv("TESTING_INFLUXDB_TOKEN").toCharArray()) + .database(System.getenv("TESTING_INFLUXDB_DATABASE")) + .sslRootsFilePath(influxDBcertificateFile) + .build(); + InfluxDBClient influxDBClient = InfluxDBClient.getInstance(clientConfig); + assertGetDataSuccess(influxDBClient); + } + + @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_URL", matches = ".*") + @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_TOKEN", matches = ".*") + @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_DATABASE", matches = ".*") + @Test + void wrongSslCertificate() { + String certificateFile = "src/test/java/com/influxdb/v3/client/testdata/docker.com.pem"; + + ClientConfig clientConfig = new ClientConfig.Builder() + .host(System.getenv("TESTING_INFLUXDB_URL")) + .token(System.getenv("TESTING_INFLUXDB_TOKEN").toCharArray()) + .database(System.getenv("TESTING_INFLUXDB_DATABASE")) + .sslRootsFilePath(certificateFile) + .build(); + InfluxDBClient influxDBClient = InfluxDBClient.getInstance(clientConfig); + Assertions.assertThatThrownBy(() -> assertGetDataSuccess(influxDBClient)) + .hasMessageContaining("PKIX path building failed"); + } + + @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_URL", matches = ".*") + @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_TOKEN", matches = ".*") + @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_DATABASE", matches = ".*") + @Test + void disableServerCertificateValidation() { + String wrongCertificateFile = "src/test/java/com/influxdb/v3/client/testdata/docker.com.pem"; + + ClientConfig clientConfig = new ClientConfig.Builder() + .host(System.getenv("TESTING_INFLUXDB_URL")) + .token(System.getenv("TESTING_INFLUXDB_TOKEN").toCharArray()) + .database(System.getenv("TESTING_INFLUXDB_DATABASE")) + .disableServerCertificateValidation(true) + .sslRootsFilePath(wrongCertificateFile) + .build(); + + // Test succeeded with wrong certificate file because disableServerCertificateValidation is true + InfluxDBClient influxDBClient = InfluxDBClient.getInstance(clientConfig); + assertGetDataSuccess(influxDBClient); + } + + @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_URL", matches = ".*") + @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_TOKEN", matches = ".*") + @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_DATABASE", matches = ".*") + @Test + public void testQuery() throws Exception { + try (InfluxDBClient client = InfluxDBClient.getInstance( + System.getenv("TESTING_INFLUXDB_URL"), + System.getenv("TESTING_INFLUXDB_TOKEN").toCharArray(), + System.getenv("TESTING_INFLUXDB_DATABASE"), + null)) { + String uuid = UUID.randomUUID().toString(); + long timestamp = Instant.now().getEpochSecond(); + String record = String.format( + "host10,tag=empty " + + "name=\"intel\"," + + "mem_total=2048," + + "disk_free=100i," + + "temperature=100.86," + + "isActive=true," + + "testId=\"%s\" %d", + uuid, + timestamp + ); + client.writeRecord(record, new WriteOptions(null, WritePrecision.S, null)); + + Map parameters = Map.of("testId", uuid); + String sql = "Select * from host10 where \"testId\"=$testId"; + try (Stream stream = client.query(sql, parameters)) { + stream.findFirst() + .ifPresent(objects -> { + Assertions.assertThat(objects[0].getClass()).isEqualTo(Long.class); + Assertions.assertThat(objects[0]).isEqualTo(100L); + + Assertions.assertThat(objects[1].getClass()).isEqualTo(Boolean.class); + Assertions.assertThat(objects[1]).isEqualTo(true); + + Assertions.assertThat(objects[2].getClass()).isEqualTo(Double.class); + Assertions.assertThat(objects[2]).isEqualTo(2048.0); + + Assertions.assertThat(objects[3].getClass()).isEqualTo(String.class); + Assertions.assertThat(objects[3]).isEqualTo("intel"); + + Assertions.assertThat(objects[7].getClass()).isEqualTo(BigInteger.class); + Assertions.assertThat(objects[7]).isEqualTo(BigInteger.valueOf(timestamp * 1_000_000_000)); + }); + } + } + } + + private void assertGetDataSuccess(@Nonnull final InfluxDBClient influxDBClient) { + influxDBClient.writePoint( + Point.measurement("test1") + .setField("field", "field1") + ); + try (Stream stream = influxDBClient.queryPoints("SELECT * FROM test1")) { + stream.findFirst() + .ifPresent(pointValues -> { + Assertions.assertThat(pointValues.getField("field")).isEqualTo("field1"); + }); + } + } +} diff --git a/src/test/java/com/influxdb/v3/client/internal/FlightSqlClientTest.java b/src/test/java/com/influxdb/v3/client/internal/FlightSqlClientTest.java index 6e819aee..0cd7ffeb 100644 --- a/src/test/java/com/influxdb/v3/client/internal/FlightSqlClientTest.java +++ b/src/test/java/com/influxdb/v3/client/internal/FlightSqlClientTest.java @@ -277,17 +277,17 @@ public void useParamsFromQueryConfig() throws Exception { @Test void createProxyDetector() { - String hostUrl = "https://localhost:80"; + String targetUrl = "https://localhost:80"; ClientConfig clientConfig = new ClientConfig.Builder() - .host(hostUrl) + .host(targetUrl) .build(); try (FlightSqlClient flightSqlClient = new FlightSqlClient(clientConfig)) { - InetSocketAddress proxyAddress = new InetSocketAddress("localhost", 10000); - ProxyDetector proxyDetector = flightSqlClient.createProxyDetector(hostUrl, proxyAddress); + String proxyUrl = "http://localhost:10000"; + ProxyDetector proxyDetector = flightSqlClient.createProxyDetector(targetUrl, proxyUrl); Assertions.assertThat(proxyDetector.proxyFor( new InetSocketAddress("localhost", 80) )).isEqualTo(HttpConnectProxiedSocketAddress.newBuilder() - .setProxyAddress(proxyAddress) + .setProxyAddress(new InetSocketAddress("localhost", 10000)) .setTargetAddress(new InetSocketAddress("localhost", 80)) .build()); diff --git a/src/test/java/com/influxdb/v3/client/internal/RestClientTest.java b/src/test/java/com/influxdb/v3/client/internal/RestClientTest.java index d76c98c8..47f30acc 100644 --- a/src/test/java/com/influxdb/v3/client/internal/RestClientTest.java +++ b/src/test/java/com/influxdb/v3/client/internal/RestClientTest.java @@ -292,12 +292,12 @@ public void proxy() throws InterruptedException { } @Test - public void proxyAddress() throws InterruptedException { + public void proxyUrl() throws InterruptedException { mockServer.enqueue(createResponse(200)); restClient = new RestClient(new ClientConfig.Builder() .host("http://foo.com:8086") - .proxyAddress(new InetSocketAddress(mockServer.getHostName(), mockServer.getPort())) + .proxyUrl(String.format("http://%s:%d", mockServer.getHostName(), mockServer.getPort())) .build()); restClient.request("ping", HttpMethod.GET, null, null, null); @@ -316,7 +316,7 @@ public void proxyWithAuthentication() throws InterruptedException { restClient = new RestClient(new ClientConfig.Builder() .host("http://foo.com:8086") - .proxyAddress(new InetSocketAddress(mockServer.getHostName(), mockServer.getPort())) + .proxyUrl(String.format("http://%s:%d", mockServer.getHostName(), mockServer.getPort())) .authenticator(new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { From 1a0c3c6bcd9529c396aabdb105193ec57a4a3ddc Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Mon, 24 Mar 2025 11:27:37 +0700 Subject: [PATCH 38/52] fix: linter --- .../v3/client/integration/E2ETest.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/test/java/com/influxdb/v3/client/integration/E2ETest.java b/src/test/java/com/influxdb/v3/client/integration/E2ETest.java index 5d3188cc..738b89d8 100644 --- a/src/test/java/com/influxdb/v3/client/integration/E2ETest.java +++ b/src/test/java/com/influxdb/v3/client/integration/E2ETest.java @@ -1,3 +1,24 @@ +/* + * The MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package com.influxdb.v3.client.integration; import java.math.BigInteger; From 1db21939ecab7a62676752be2586b489aea4146c Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Mon, 24 Mar 2025 13:37:55 +0700 Subject: [PATCH 39/52] fix: formater --- .../com/influxdb/v3/client/internal/FlightSqlClient.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java b/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java index ef0d7f70..584c7018 100644 --- a/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java +++ b/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java @@ -77,7 +77,7 @@ final class FlightSqlClient implements AutoCloseable { private final Map defaultHeaders = new HashMap<>(); private final ObjectMapper objectMapper = new ObjectMapper(); - private final List VALID_SCHEMAS = List.of( + private final List validSchemas = List.of( LocationSchemes.GRPC, LocationSchemes.GRPC_INSECURE, LocationSchemes.GRPC_TLS, @@ -153,7 +153,7 @@ private FlightClient createFlightClient(@Nonnull final ClientConfig config) { Location location = createLocation(config); final NettyChannelBuilder nettyChannelBuilder = NettyChannelBuilder.forTarget(location.getUri().getHost()); - if (!VALID_SCHEMAS.contains(location.getUri().getScheme())) { + if (!validSchemas.contains(location.getUri().getScheme())) { throw new IllegalArgumentException( "Scheme is not supported: " + location.getUri().getScheme()); } @@ -277,7 +277,8 @@ ProxyDetector createProxyDetector(@Nonnull final String targetUrl, @Nonnull fina URI proxyUri = URI.create(proxyUrl); return (targetServerAddress) -> { InetSocketAddress targetAddress = (InetSocketAddress) targetServerAddress; - if (targetUri.getHost().equals(targetAddress.getHostString()) && targetUri.getPort() == targetAddress.getPort()) { + if (targetUri.getHost().equals(targetAddress.getHostString()) + && targetUri.getPort() == targetAddress.getPort()) { return HttpConnectProxiedSocketAddress.newBuilder() .setProxyAddress(new InetSocketAddress(proxyUri.getHost(), proxyUri.getPort())) .setTargetAddress(targetAddress) From a68b9b1edc592b5e80c948e8d105745b7c59a17f Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Mon, 24 Mar 2025 14:16:31 +0700 Subject: [PATCH 40/52] fix: formater --- src/test/java/com/influxdb/v3/client/integration/E2ETest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/influxdb/v3/client/integration/E2ETest.java b/src/test/java/com/influxdb/v3/client/integration/E2ETest.java index 738b89d8..ca1d4236 100644 --- a/src/test/java/com/influxdb/v3/client/integration/E2ETest.java +++ b/src/test/java/com/influxdb/v3/client/integration/E2ETest.java @@ -56,7 +56,7 @@ void testQueryWithProxy() { try { // Continue to run this test only if Envoy proxy is running on this address http://localhost:10000 - String url = String.format("http://%s:%d/", "localhost", 10000); + String url = String.format("http://%s:%d", "localhost", 10000); URLConnection hpCon = new URL(url).openConnection(); hpCon.connect(); } catch (Exception e) { From 89604b5db1203c3d4c720d93247371b608036fac Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Mon, 24 Mar 2025 14:21:28 +0700 Subject: [PATCH 41/52] refactor: check proxy --- .../java/com/influxdb/v3/client/integration/E2ETest.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/test/java/com/influxdb/v3/client/integration/E2ETest.java b/src/test/java/com/influxdb/v3/client/integration/E2ETest.java index ca1d4236..7f6ee778 100644 --- a/src/test/java/com/influxdb/v3/client/integration/E2ETest.java +++ b/src/test/java/com/influxdb/v3/client/integration/E2ETest.java @@ -22,7 +22,6 @@ package com.influxdb.v3.client.integration; import java.math.BigInteger; -import java.net.ConnectException; import java.net.URL; import java.net.URLConnection; import java.time.Instant; @@ -60,10 +59,8 @@ void testQueryWithProxy() { URLConnection hpCon = new URL(url).openConnection(); hpCon.connect(); } catch (Exception e) { - if (e instanceof ConnectException && e.getMessage().equals("Connection refused")) { - LOG.warning("Tests with proxy have been skipped because no proxy is running on " + proxyUrl); - return; - } + LOG.warning("Tests with proxy have been skipped because no proxy is running on " + proxyUrl); + return; } ClientConfig clientConfig = new ClientConfig.Builder() From 0b2eca6750b574be9b484e7ae32360cc0b4fa824 Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Mon, 24 Mar 2025 14:29:14 +0700 Subject: [PATCH 42/52] refactor: check proxy --- .../java/com/influxdb/v3/client/integration/E2ETest.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/influxdb/v3/client/integration/E2ETest.java b/src/test/java/com/influxdb/v3/client/integration/E2ETest.java index 7f6ee778..4e21dff9 100644 --- a/src/test/java/com/influxdb/v3/client/integration/E2ETest.java +++ b/src/test/java/com/influxdb/v3/client/integration/E2ETest.java @@ -22,6 +22,7 @@ package com.influxdb.v3.client.integration; import java.math.BigInteger; +import java.net.ConnectException; import java.net.URL; import java.net.URLConnection; import java.time.Instant; @@ -59,8 +60,10 @@ void testQueryWithProxy() { URLConnection hpCon = new URL(url).openConnection(); hpCon.connect(); } catch (Exception e) { - LOG.warning("Tests with proxy have been skipped because no proxy is running on " + proxyUrl); - return; + if (e instanceof ConnectException && e.getMessage().contains("Connection refused")) { + LOG.warning("Tests with proxy have been skipped because no proxy is running on " + proxyUrl); + return; + } } ClientConfig clientConfig = new ClientConfig.Builder() From 203e39d260d26177cf8840d675af83a97c611e23 Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Mon, 24 Mar 2025 17:22:09 +0700 Subject: [PATCH 43/52] chore: CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 48ed94b0..8972ec3c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ### Features -1. [#229](https://github.com/InfluxCommunity/influxdb3-java/pull/229): Support proxy and ssl +1. [#229](https://github.com/InfluxCommunity/influxdb3-java/pull/229): Support proxy and custom ssl root certificates ## 1.0.0 [2024-12-11] From 80ce464e14ef90b6a945d37766083a5900bf96f7 Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Mon, 24 Mar 2025 17:42:12 +0700 Subject: [PATCH 44/52] refactor: ssl sslContextBuilder condition --- .../influxdb/v3/client/internal/FlightSqlClient.java | 12 +++++------- .../com/influxdb/v3/client/internal/RestClient.java | 7 ++++--- .../com/influxdb/v3/client/integration/E2ETest.java | 2 +- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java b/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java index 584c7018..62e4b28d 100644 --- a/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java +++ b/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java @@ -192,14 +192,12 @@ SslContext createNettySslContext(@Nonnull final ClientConfig config) { try { SslContextBuilder sslContextBuilder; sslContextBuilder = GrpcSslContexts.forClient(); - if (!config.getDisableServerCertificateValidation()) { - if (config.sslRootsFilePath() != null) { - try (FileInputStream fileInputStream = new FileInputStream(config.sslRootsFilePath())) { - sslContextBuilder.trustManager(fileInputStream); - } - } - } else { + if (config.getDisableServerCertificateValidation()) { sslContextBuilder.trustManager(InsecureTrustManagerFactory.INSTANCE); + } else if (config.sslRootsFilePath() != null) { + try (FileInputStream fileInputStream = new FileInputStream(config.sslRootsFilePath())) { + sslContextBuilder.trustManager(fileInputStream); + } } return sslContextBuilder.build(); } catch (Exception e) { diff --git a/src/main/java/com/influxdb/v3/client/internal/RestClient.java b/src/main/java/com/influxdb/v3/client/internal/RestClient.java index 387c68c0..3142abf5 100644 --- a/src/main/java/com/influxdb/v3/client/internal/RestClient.java +++ b/src/main/java/com/influxdb/v3/client/internal/RestClient.java @@ -123,12 +123,13 @@ public void checkServerTrusted( if (baseUrl.startsWith("https")) { try { SSLContext sslContext = SSLContext.getInstance("TLS"); - if (config.sslRootsFilePath() != null && !config.getDisableServerCertificateValidation()) { + if (config.getDisableServerCertificateValidation()) { + sslContext.init(null, TRUST_ALL_CERTS, new SecureRandom()); + } else if (config.sslRootsFilePath() != null) { X509TrustManager x509TrustManager = getX509TrustManagerFromFile(config.sslRootsFilePath()); sslContext.init(null, new X509TrustManager[]{x509TrustManager}, new SecureRandom()); - } else { - sslContext.init(null, TRUST_ALL_CERTS, new SecureRandom()); } + sslContext.init(null, null, new SecureRandom()); builder.sslContext(sslContext); } catch (Exception e) { throw new RuntimeException(e); diff --git a/src/test/java/com/influxdb/v3/client/integration/E2ETest.java b/src/test/java/com/influxdb/v3/client/integration/E2ETest.java index 4e21dff9..ae41ced4 100644 --- a/src/test/java/com/influxdb/v3/client/integration/E2ETest.java +++ b/src/test/java/com/influxdb/v3/client/integration/E2ETest.java @@ -120,7 +120,7 @@ void wrongSslCertificate() { .build(); InfluxDBClient influxDBClient = InfluxDBClient.getInstance(clientConfig); Assertions.assertThatThrownBy(() -> assertGetDataSuccess(influxDBClient)) - .hasMessageContaining("PKIX path building failed"); + .isInstanceOf(Exception.class); } @EnabledIfEnvironmentVariable(named = "TESTING_INFLUXDB_URL", matches = ".*") From 0f3ffcdd44c525647c14dce38b725269f38428a0 Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Mon, 24 Mar 2025 19:00:15 +0700 Subject: [PATCH 45/52] refactor: ssl sslContextBuilder condition --- src/main/java/com/influxdb/v3/client/internal/RestClient.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/influxdb/v3/client/internal/RestClient.java b/src/main/java/com/influxdb/v3/client/internal/RestClient.java index 3142abf5..971abd24 100644 --- a/src/main/java/com/influxdb/v3/client/internal/RestClient.java +++ b/src/main/java/com/influxdb/v3/client/internal/RestClient.java @@ -128,8 +128,9 @@ public void checkServerTrusted( } else if (config.sslRootsFilePath() != null) { X509TrustManager x509TrustManager = getX509TrustManagerFromFile(config.sslRootsFilePath()); sslContext.init(null, new X509TrustManager[]{x509TrustManager}, new SecureRandom()); + } else { + sslContext.init(null, null, new SecureRandom()); } - sslContext.init(null, null, new SecureRandom()); builder.sslContext(sslContext); } catch (Exception e) { throw new RuntimeException(e); From 766d68d3b6123035e6ac20289c700deb761008ce Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Tue, 25 Mar 2025 08:44:35 +0700 Subject: [PATCH 46/52] feat: add test case --- .../v3/client/internal/FlightSqlClientTest.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/test/java/com/influxdb/v3/client/internal/FlightSqlClientTest.java b/src/test/java/com/influxdb/v3/client/internal/FlightSqlClientTest.java index 0cd7ffeb..e478ee63 100644 --- a/src/test/java/com/influxdb/v3/client/internal/FlightSqlClientTest.java +++ b/src/test/java/com/influxdb/v3/client/internal/FlightSqlClientTest.java @@ -86,6 +86,23 @@ void tearDown() throws Exception { } } + @Test + void flightSqlClient() throws Exception { + ClientConfig clientConfig = new ClientConfig.Builder() + .host("grpc+unix://tmp/dummy.sock") + .token("Token".toCharArray()) + .build(); + try (FlightSqlClient flightSqlClient = new FlightSqlClient(clientConfig)) { + Assertions.assertThat(flightSqlClient).isNotNull(); + } + + FlightClient.Builder builder = FlightClient.builder(allocator, server.getLocation()); + try (FlightClient flightClient = builder.build()) { + FlightSqlClient flightSqlClient = new FlightSqlClient(clientConfig, flightClient); + Assertions.assertThat(flightSqlClient).isNotNull(); + } + } + @Test public void invalidHost() { ClientConfig clientConfig = new ClientConfig.Builder() From 70b3d7d9cb6c881425d2d227a091ed749c666718 Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Tue, 25 Mar 2025 09:03:21 +0700 Subject: [PATCH 47/52] feat: add test case --- .../v3/client/internal/FlightSqlClientTest.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/influxdb/v3/client/internal/FlightSqlClientTest.java b/src/test/java/com/influxdb/v3/client/internal/FlightSqlClientTest.java index e478ee63..84a609ad 100644 --- a/src/test/java/com/influxdb/v3/client/internal/FlightSqlClientTest.java +++ b/src/test/java/com/influxdb/v3/client/internal/FlightSqlClientTest.java @@ -88,8 +88,9 @@ void tearDown() throws Exception { @Test void flightSqlClient() throws Exception { + String correctHost = "grpc+unix://tmp/dummy.sock"; ClientConfig clientConfig = new ClientConfig.Builder() - .host("grpc+unix://tmp/dummy.sock") + .host(correctHost) .token("Token".toCharArray()) .build(); try (FlightSqlClient flightSqlClient = new FlightSqlClient(clientConfig)) { @@ -101,6 +102,13 @@ void flightSqlClient() throws Exception { FlightSqlClient flightSqlClient = new FlightSqlClient(clientConfig, flightClient); Assertions.assertThat(flightSqlClient).isNotNull(); } + + var inCorrectHost = "grpc+unix://///tmp/dummy.sock"; + ClientConfig clientConfig1 = new ClientConfig.Builder() + .host(inCorrectHost) + .token("Token".toCharArray()) + .build(); + Assertions.assertThatThrownBy(() -> new FlightSqlClient(clientConfig1)); } @Test From 884410a11b954d8f70bc8b3ae59b706913276f2c Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Tue, 25 Mar 2025 15:03:05 +0700 Subject: [PATCH 48/52] refactor: remove setChannelTypeAndEventLoop() --- .../v3/client/internal/FlightSqlClient.java | 53 ------------------- 1 file changed, 53 deletions(-) diff --git a/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java b/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java index 62e4b28d..e1b37298 100644 --- a/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java +++ b/src/main/java/com/influxdb/v3/client/internal/FlightSqlClient.java @@ -22,7 +22,6 @@ package com.influxdb.v3.client.internal; import java.io.FileInputStream; -import java.lang.reflect.InvocationTargetException; import java.net.InetSocketAddress; import java.net.URI; import java.net.URISyntaxException; @@ -47,8 +46,6 @@ import io.grpc.ProxyDetector; import io.grpc.netty.GrpcSslContexts; import io.grpc.netty.NettyChannelBuilder; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.ServerChannel; import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.SslContextBuilder; import io.netty.handler.ssl.util.InsecureTrustManagerFactory; @@ -77,12 +74,6 @@ final class FlightSqlClient implements AutoCloseable { private final Map defaultHeaders = new HashMap<>(); private final ObjectMapper objectMapper = new ObjectMapper(); - private final List validSchemas = List.of( - LocationSchemes.GRPC, - LocationSchemes.GRPC_INSECURE, - LocationSchemes.GRPC_TLS, - LocationSchemes.GRPC_DOMAIN_SOCKET - ); FlightSqlClient(@Nonnull final ClientConfig config) { this(config, null); @@ -153,14 +144,6 @@ private FlightClient createFlightClient(@Nonnull final ClientConfig config) { Location location = createLocation(config); final NettyChannelBuilder nettyChannelBuilder = NettyChannelBuilder.forTarget(location.getUri().getHost()); - if (!validSchemas.contains(location.getUri().getScheme())) { - throw new IllegalArgumentException( - "Scheme is not supported: " + location.getUri().getScheme()); - } - - if (location.getUri().getScheme().equals(LocationSchemes.GRPC_DOMAIN_SOCKET)) { - setChannelTypeAndEventLoop(nettyChannelBuilder); - } if (LocationSchemes.GRPC_TLS.equals(location.getUri().getScheme())) { nettyChannelBuilder.useTransportSecurity(); @@ -234,42 +217,6 @@ private HeaderCallOption metadataHeader(@Nonnull final Map reque return new HeaderCallOption(metadata); } - private void setChannelTypeAndEventLoop(@Nonnull final NettyChannelBuilder nettyChannelBuilder) { - // The implementation is platform-specific, so we have to find the classes at runtime - try { - try { - // Linux - nettyChannelBuilder.channelType( - Class.forName("io.netty.channel.epoll.EpollDomainSocketChannel") - .asSubclass(ServerChannel.class)); - final EventLoopGroup elg = - Class.forName("io.netty.channel.epoll.EpollEventLoopGroup") - .asSubclass(EventLoopGroup.class) - .getDeclaredConstructor() - .newInstance(); - nettyChannelBuilder.eventLoopGroup(elg); - } catch (ClassNotFoundException e) { - // BSD - nettyChannelBuilder.channelType( - Class.forName("io.netty.channel.kqueue.KQueueDomainSocketChannel") - .asSubclass(ServerChannel.class)); - final EventLoopGroup elg = - Class.forName("io.netty.channel.kqueue.KQueueEventLoopGroup") - .asSubclass(EventLoopGroup.class) - .getDeclaredConstructor() - .newInstance(); - nettyChannelBuilder.eventLoopGroup(elg); - } - } catch (ClassNotFoundException - | InstantiationException - | IllegalAccessException - | NoSuchMethodException - | InvocationTargetException e) { - throw new UnsupportedOperationException( - "Could not find suitable Netty native transport implementation for domain socket address."); - } - } - ProxyDetector createProxyDetector(@Nonnull final String targetUrl, @Nonnull final String proxyUrl) { URI targetUri = URI.create(targetUrl); URI proxyUri = URI.create(proxyUrl); From f9af61345af83d0917710da2afbe0526c3d87a5b Mon Sep 17 00:00:00 2001 From: karel rehor Date: Tue, 25 Mar 2025 14:05:36 +0100 Subject: [PATCH 49/52] test: add assume to proxy test - so it gets marked as skipped by junit. --- src/test/java/com/influxdb/v3/client/integration/E2ETest.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/test/java/com/influxdb/v3/client/integration/E2ETest.java b/src/test/java/com/influxdb/v3/client/integration/E2ETest.java index ae41ced4..0eff6cdc 100644 --- a/src/test/java/com/influxdb/v3/client/integration/E2ETest.java +++ b/src/test/java/com/influxdb/v3/client/integration/E2ETest.java @@ -43,6 +43,8 @@ import com.influxdb.v3.client.write.WriteOptions; import com.influxdb.v3.client.write.WritePrecision; +import static org.junit.jupiter.api.Assumptions.assumeFalse; + public class E2ETest { private static final java.util.logging.Logger LOG = Logger.getLogger(E2ETest.class.getName()); @@ -62,6 +64,7 @@ void testQueryWithProxy() { } catch (Exception e) { if (e instanceof ConnectException && e.getMessage().contains("Connection refused")) { LOG.warning("Tests with proxy have been skipped because no proxy is running on " + proxyUrl); + assumeFalse(e.getMessage().contains("Connection refused")); return; } } From 45d5fa348fa7ef6dce37b5d7c1258b9bef6b9c05 Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Wed, 26 Mar 2025 13:49:07 +0700 Subject: [PATCH 50/52] chore: update example --- examples/src/main/java/com/influxdb/v3/ProxyExample.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/src/main/java/com/influxdb/v3/ProxyExample.java b/examples/src/main/java/com/influxdb/v3/ProxyExample.java index f65c0ba0..6b97ae81 100644 --- a/examples/src/main/java/com/influxdb/v3/ProxyExample.java +++ b/examples/src/main/java/com/influxdb/v3/ProxyExample.java @@ -53,7 +53,7 @@ public static void main(final String[] args) throws Exception { .setField("hum", 37); influxDBClient.writePoint(point); - try (Stream stream = influxDBClient.queryPoints("SELECT * FROM home")) { + try (Stream stream = influxDBClient.queryPoints("SELECT * FROM Home")) { stream.findFirst().ifPresent(System.out::println); } } From 01a83a201036c6df41693710c03f435694b400a2 Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Wed, 26 Mar 2025 13:52:46 +0700 Subject: [PATCH 51/52] [EMPTY] trigger CI From 9008c68be049f13950a7fda24dbc690ff2ac7845 Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Thu, 27 Mar 2025 08:06:29 +0700 Subject: [PATCH 52/52] feat: update example --- .../java/com/influxdb/v3/ProxyExample.java | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/examples/src/main/java/com/influxdb/v3/ProxyExample.java b/examples/src/main/java/com/influxdb/v3/ProxyExample.java index 6b97ae81..76a3204d 100644 --- a/examples/src/main/java/com/influxdb/v3/ProxyExample.java +++ b/examples/src/main/java/com/influxdb/v3/ProxyExample.java @@ -21,6 +21,7 @@ */ package com.influxdb.v3; +import java.util.UUID; import java.util.stream.Stream; import com.influxdb.v3.client.InfluxDBClient; @@ -47,14 +48,24 @@ public static void main(final String[] args) throws Exception { .build(); InfluxDBClient influxDBClient = InfluxDBClient.getInstance(clientConfig); - Point point = Point.measurement("Home") + String testId = UUID.randomUUID().toString(); + Point point = Point.measurement("My_Home") .setTag("room", "Kitchen") .setField("temp", 12.7) - .setField("hum", 37); + .setField("hum", 37) + .setField("testId", testId); influxDBClient.writePoint(point); - try (Stream stream = influxDBClient.queryPoints("SELECT * FROM Home")) { - stream.findFirst().ifPresent(System.out::println); + String query = String.format("SELECT * FROM \"My_Home\" WHERE \"testId\" = '%s'", testId); + try (Stream stream = influxDBClient.queryPoints(query)) { + stream.findFirst().ifPresent(values -> { + assert values.getTimestamp() != null; + System.out.printf("room[%s]: %s, temp: %3.2f, hum: %d", + new java.util.Date(values.getTimestamp().longValue() / 1000000), + values.getTag("room"), + (Double) values.getField("temp"), + (Long) values.getField("hum")); + }); } } }