diff --git a/CHANGELOG.md b/CHANGELOG.md index 921759e2fd..5ed29ed9a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## 7.3.0 [unreleased] +### Features + +- [#821](https://github.com/influxdata/influxdb-client-java/pull/821): Prevent duplicate interceptors in OkHttpClient builder + ### Dependencies ⚠️ Important Notice: Starting from this release, we won’t be listing every dependency change in our changelog. This helps us maintain the project faster and focus on important features for our InfluxDB client. diff --git a/client/src/main/java/com/influxdb/client/InfluxDBClientOptions.java b/client/src/main/java/com/influxdb/client/InfluxDBClientOptions.java index 528f5418dd..6ae4e0746a 100644 --- a/client/src/main/java/com/influxdb/client/InfluxDBClientOptions.java +++ b/client/src/main/java/com/influxdb/client/InfluxDBClientOptions.java @@ -699,8 +699,8 @@ private ParsedUrl(@Nonnull final String connectionString) { String urlWithoutParams = url.scheme() + "://" + host + ":" + url.port() + url.encodedPath(); this.urlWithoutParams = urlWithoutParams.endsWith("/") - ? urlWithoutParams - : urlWithoutParams + "/"; + ? urlWithoutParams + : urlWithoutParams + "/"; } } } diff --git a/client/src/main/java/com/influxdb/client/internal/AbstractInfluxDBClient.java b/client/src/main/java/com/influxdb/client/internal/AbstractInfluxDBClient.java index def96dd34a..a55f8495d2 100644 --- a/client/src/main/java/com/influxdb/client/internal/AbstractInfluxDBClient.java +++ b/client/src/main/java/com/influxdb/client/internal/AbstractInfluxDBClient.java @@ -24,6 +24,7 @@ import java.io.IOException; import java.util.Collection; import java.util.Collections; +import java.util.List; import java.util.Objects; import java.util.concurrent.CopyOnWriteArrayList; import java.util.logging.Level; @@ -41,6 +42,7 @@ import com.influxdb.internal.UserAgentInterceptor; import com.influxdb.utils.Arguments; +import okhttp3.Interceptor; import okhttp3.OkHttpClient; import okhttp3.logging.HttpLoggingInterceptor; import retrofit2.Call; @@ -94,6 +96,17 @@ public AbstractInfluxDBClient(@Nonnull final InfluxDBClientOptions options, this.authenticateInterceptor = new AuthenticateInterceptor(options); this.gzipInterceptor = new GzipInterceptor(); + // These Interceptors are the default for OkHttpClient. It must be unique for every OkHttpClient + List> excludeInterceptorClasses = List.of( + UserAgentInterceptor.class, + AuthenticateInterceptor.class, + HttpLoggingInterceptor.class, + GzipInterceptor.class + ); + options.getOkHttpClient() + .interceptors() + .removeIf(interceptor -> excludeInterceptorClasses.contains(interceptor.getClass())); + String customClientType = options.getClientType() != null ? options.getClientType() : clientType; this.okHttpClient = options.getOkHttpClient() // diff --git a/client/src/test/java/com/influxdb/client/InfluxDBClientTest.java b/client/src/test/java/com/influxdb/client/InfluxDBClientTest.java index c3a53bb238..d706e4d9e3 100644 --- a/client/src/test/java/com/influxdb/client/InfluxDBClientTest.java +++ b/client/src/test/java/com/influxdb/client/InfluxDBClientTest.java @@ -21,9 +21,7 @@ */ package com.influxdb.client; -import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.OutputStream; import java.net.InetSocketAddress; import java.net.Proxy; import java.util.List; @@ -33,18 +31,6 @@ import java.util.logging.Logger; import javax.annotation.Nonnull; -import com.influxdb.client.domain.InfluxQLQuery; -import com.influxdb.client.service.InfluxQLQueryService; -import com.sun.net.httpserver.HttpExchange; -import com.sun.net.httpserver.HttpServer; -import com.sun.net.httpserver.HttpHandler; -import com.influxdb.LogLevel; -import com.influxdb.client.domain.Authorization; -import com.influxdb.client.domain.Run; -import com.influxdb.client.domain.WriteConsistency; -import com.influxdb.client.domain.WritePrecision; -import com.influxdb.client.internal.AbstractInfluxDBClientTest; - import okhttp3.HttpUrl; import okhttp3.Interceptor; import okhttp3.OkHttpClient; @@ -59,6 +45,15 @@ import org.junit.jupiter.api.Test; import retrofit2.Call; +import com.influxdb.LogLevel; +import com.influxdb.client.domain.Authorization; +import com.influxdb.client.domain.InfluxQLQuery; +import com.influxdb.client.domain.Run; +import com.influxdb.client.domain.WriteConsistency; +import com.influxdb.client.domain.WritePrecision; +import com.influxdb.client.internal.AbstractInfluxDBClientTest; +import com.influxdb.client.service.InfluxQLQueryService; + /** * @author Jakub Bednar (bednar@github) (05/09/2018 14:00) */ @@ -130,10 +125,10 @@ public void createNotificationRulesApi() { public void serviceHeaderDefault() { InfluxQLQueryService service = influxDBClient.getService(InfluxQLQueryService.class); Call call = service.query("SELECT * FROM cpu", "test_db", - null, - null, - null, - InfluxQLQuery.AcceptHeader.JSON.getVal()); + null, + null, + null, + InfluxQLQuery.AcceptHeader.JSON.getVal()); Assertions.assertThat(call.request().header("Accept")).isEqualTo("application/json"); } @@ -141,10 +136,10 @@ public void serviceHeaderDefault() { public void serviceHeaderChange() { InfluxQLQueryService service = influxDBClient.getService(InfluxQLQueryService.class); Call call = service.query("SELECT * FROM cpu", "test_db", - null, - null, - null, - InfluxQLQuery.AcceptHeader.CSV.getVal()); + null, + null, + null, + InfluxQLQuery.AcceptHeader.CSV.getVal()); Assertions.assertThat(call.request().header("accept")).isEqualTo("application/csv"); } @@ -221,7 +216,8 @@ void parseUnknownEnumAsNull() { @Test void parseDateTime() { - mockServer.enqueue(new MockResponse().setBody("{\"id\":\"runID\",\"taskID\":\"taskID\",\"startedAt\":\"2019-03-11T11:57:30.830995162Z\"}")); + mockServer.enqueue(new MockResponse().setBody( + "{\"id\":\"runID\",\"taskID\":\"taskID\",\"startedAt\":\"2019-03-11T11:57:30.830995162Z\"}")); Run run = influxDBClient.getTasksApi().getRun("taskID", "runID"); @@ -245,19 +241,23 @@ public void trailingSlashInUrl() throws InterruptedException { InfluxDBClient influxDBClient = InfluxDBClientFactory .create(path, "my-token".toCharArray()); - influxDBClient.getWriteApiBlocking().writeRecord("my-bucket", "my-org", WritePrecision.NS, "record,tag=a value=1"); + influxDBClient.getWriteApiBlocking() + .writeRecord("my-bucket", "my-org", WritePrecision.NS, "record,tag=a value=1"); RecordedRequest request = mockServer.takeRequest(); - Assertions.assertThat(request.getRequestUrl().toString()).isEqualTo(path + "api/v2/write?org=my-org&bucket=my-bucket&precision=ns"); + Assertions.assertThat(request.getRequestUrl().toString()) + .isEqualTo(path + "api/v2/write?org=my-org&bucket=my-bucket&precision=ns"); influxDBClient.close(); influxDBClient = InfluxDBClientFactory .create(path.substring(0, path.length() - 1), "my-token".toCharArray()); - influxDBClient.getWriteApiBlocking().writeRecord("my-bucket", "my-org", WritePrecision.NS, "record,tag=a value=1"); + influxDBClient.getWriteApiBlocking() + .writeRecord("my-bucket", "my-org", WritePrecision.NS, "record,tag=a value=1"); request = mockServer.takeRequest(); - Assertions.assertThat(request.getRequestUrl().toString()).isEqualTo(path + "api/v2/write?org=my-org&bucket=my-bucket&precision=ns"); + Assertions.assertThat(request.getRequestUrl().toString()) + .isEqualTo(path + "api/v2/write?org=my-org&bucket=my-bucket&precision=ns"); influxDBClient.close(); } @@ -277,9 +277,11 @@ void customPath() throws InterruptedException { // http://localhost:8086 -> http://localhost:8086/api/v2/query {serverURL, serverURL + "/api/v2/query"}, // http://localhost:8086?readTimeout=1000&writeTimeout=3000&connectTimeout=2000&logLevel=HEADERS" -> http://localhost:8086/api/v2/query - {serverURL + "?readTimeout=1000&writeTimeout=3000&connectTimeout=2000&logLevel=HEADERS", serverURL + "/api/v2/query"}, + {serverURL + "?readTimeout=1000&writeTimeout=3000&connectTimeout=2000&logLevel=HEADERS", + serverURL + "/api/v2/query"}, // http://localhost:8086/influx?readTimeout=1000&writeTimeout=3000&connectTimeout=2000&logLevel=HEADERS" -> http://localhost:8086/influx/api/v2/query - {serverURL + "/influx?readTimeout=1000&writeTimeout=3000&connectTimeout=2000&logLevel=HEADERS", serverURL + "/influx/api/v2/query"} + {serverURL + "/influx?readTimeout=1000&writeTimeout=3000&connectTimeout=2000&logLevel=HEADERS", + serverURL + "/influx/api/v2/query"} }; for (String[] connectionString : connectionStrings) { @@ -424,14 +426,14 @@ public void connectionStringPrecision() { InfluxDBClientOptions options = InfluxDBClientOptions.builder() .connectionString("https://us-west-2-1.aws.cloud2.influxdata.com?precision=US") .build(); - + Assertions.assertThat(options.getPrecision()).isEqualTo(WritePrecision.US); } @Test public void propertiesPrecision() { InfluxDBClientOptions options = InfluxDBClientOptions.builder().loadProperties().build(); - + Assertions.assertThat(options.getPrecision()).isEqualTo(WritePrecision.US); } @@ -468,7 +470,8 @@ public void customClientType() throws InterruptedException { .writeRecord("my-bucket", "my-org", WritePrecision.NS, "record,tag=a value=1"); RecordedRequest request = mockServer.takeRequest(); - Assertions.assertThat(request.getHeaders().get("User-Agent")).startsWith("influxdb-client-awesome-service/"); + Assertions.assertThat(request.getHeaders().get("User-Agent")) + .startsWith("influxdb-client-awesome-service/"); } } @@ -482,7 +485,8 @@ public void redactedAuthorizationHeader() { final Logger logger = Logger.getLogger("okhttp3.OkHttpClient"); logger.addHandler(handler); - try (InfluxDBClient client = InfluxDBClientFactory.create(mockServer.url("/").toString(), "my-token".toCharArray())) { + try (InfluxDBClient client = InfluxDBClientFactory.create(mockServer.url("/").toString(), + "my-token".toCharArray())) { client.setLogLevel(LogLevel.HEADERS); client .getWriteApiBlocking() @@ -500,6 +504,43 @@ public void redactedAuthorizationHeader() { Assertions.assertThat(authorizationLog.getMessage()).isEqualTo("Authorization: ██"); } + @Test + void testDefaultInterceptors() { + String url = "http://localhost:8086"; + InfluxDBClientOptions options = new InfluxDBClientOptions.Builder() + .url(url) + .build(); + + InfluxDBClient client = InfluxDBClientFactory.create(options); + List interceptors = options.getOkHttpClient().interceptors(); + Assertions.assertThat(interceptors.size()).isEqualTo(4); + client.close(); + + InfluxDBClient client1 = InfluxDBClientFactory.create(options); + interceptors = options.getOkHttpClient().interceptors(); + Assertions.assertThat(interceptors.size()).isEqualTo(4); + client1.close(); + + // okHttpBuilder with additional Interceptors + OkHttpClient.Builder okHttpBuilder = new OkHttpClient.Builder(); + okHttpBuilder.addInterceptor(chain -> chain.proceed(chain.request())); + okHttpBuilder.addInterceptor(chain -> chain.proceed(chain.request())); + + InfluxDBClientOptions options1 = new InfluxDBClientOptions.Builder() + .url(url) + .okHttpClient(okHttpBuilder) + .build(); + client = InfluxDBClientFactory.create(options1); + interceptors = options1.getOkHttpClient().interceptors(); + Assertions.assertThat(interceptors.size()).isEqualTo(6); + client.close(); + + client1 = InfluxDBClientFactory.create(options1); + interceptors = options1.getOkHttpClient().interceptors(); + Assertions.assertThat(interceptors.size()).isEqualTo(6); + client1.close(); + } + private void queryAndTest(final String expected) throws InterruptedException { RecordedRequest request = takeRequest(); Assertions.assertThat(request).isNotNull();