diff --git a/pom.xml b/pom.xml
index ef2976d94..6399b55d5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -115,20 +115,20 @@
org.assertj
assertj-core
- 3.26.3
+ 3.27.6
test
org.mockito
mockito-core
- 4.8.1
+ 5.20.0
test
com.github.tomakehurst
wiremock-jre8
- 2.35.2
+ 3.0.1
test
@@ -177,6 +177,13 @@
org.apache.maven.plugins
maven-dependency-plugin
3.8.1
+
+
+
+ properties
+
+
+
org.apache.maven.plugins
@@ -219,7 +226,7 @@
org.jacoco
jacoco-maven-plugin
- 0.8.12
+ 0.8.13
prepare-agent
@@ -410,6 +417,9 @@
org.apache.maven.plugins
maven-surefire-plugin
3.5.2
+
+ @{argLine} -javaagent:${org.mockito:mockito-core:jar}
+
diff --git a/src/main/java/io/getunleash/repository/HttpFeatureFetcher.java b/src/main/java/io/getunleash/repository/HttpFeatureFetcher.java
index 53f2ab22b..a8863bb10 100644
--- a/src/main/java/io/getunleash/repository/HttpFeatureFetcher.java
+++ b/src/main/java/io/getunleash/repository/HttpFeatureFetcher.java
@@ -5,15 +5,13 @@
import io.getunleash.UnleashException;
import io.getunleash.event.ClientFeaturesResponse;
import io.getunleash.util.UnleashConfig;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
+import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Optional;
import java.util.stream.Collectors;
+import java.util.zip.GZIPInputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -59,15 +57,30 @@ private ClientFeaturesResponse getFeatureResponse(
if (responseCode < 300) {
etag = Optional.ofNullable(request.getHeaderField("ETag"));
-
- try (BufferedReader reader =
- new BufferedReader(
- new InputStreamReader(
- (InputStream) request.getContent(), StandardCharsets.UTF_8))) {
-
- String clientFeatures = reader.lines().collect(Collectors.joining("\n"));
-
- return ClientFeaturesResponse.updated(clientFeatures);
+ String contentEncoding = request.getHeaderField("Content-Encoding");
+ if ("gzip".equalsIgnoreCase(contentEncoding)) {
+ try (GZIPInputStream stream = new GZIPInputStream(request.getInputStream())) {
+ try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
+ byte[] buffer = new byte[1024];
+ int len;
+ while ((len = stream.read(buffer)) != -1) {
+ outputStream.write(buffer, 0, len);
+ }
+ String clientFeatures = outputStream.toString(StandardCharsets.UTF_8);
+ return ClientFeaturesResponse.updated(clientFeatures);
+ }
+ }
+ } else {
+ try (BufferedReader reader =
+ new BufferedReader(
+ new InputStreamReader(
+ (InputStream) request.getContent(),
+ StandardCharsets.UTF_8))) {
+
+ String clientFeatures = reader.lines().collect(Collectors.joining("\n"));
+
+ return ClientFeaturesResponse.updated(clientFeatures);
+ }
}
} else if (followRedirect
&& (responseCode == HttpURLConnection.HTTP_MOVED_TEMP
@@ -114,6 +127,7 @@ private HttpURLConnection openConnection(URL url) throws IOException {
connection.setReadTimeout((int) this.config.getFetchTogglesReadTimeout().toMillis());
connection.setRequestProperty("Accept", "application/json");
connection.setRequestProperty("Content-Type", "application/json");
+ connection.setRequestProperty("Accept-Encoding", "gzip,deflate");
UnleashConfig.setRequestProperties(connection, this.config);
etag.ifPresent(val -> connection.setRequestProperty("If-None-Match", val));
diff --git a/src/test/java/io/getunleash/HotReloadSchedulerReuseTest.java b/src/test/java/io/getunleash/HotReloadSchedulerReuseTest.java
index 530ca4cbc..f93e772d0 100644
--- a/src/test/java/io/getunleash/HotReloadSchedulerReuseTest.java
+++ b/src/test/java/io/getunleash/HotReloadSchedulerReuseTest.java
@@ -1,25 +1,23 @@
package io.getunleash;
-import io.getunleash.util.UnleashConfig;
-import org.junit.jupiter.api.*;
+import static org.assertj.core.api.Assertions.assertThat;
+import io.getunleash.util.UnleashConfig;
import java.lang.reflect.Field;
import java.util.concurrent.ScheduledThreadPoolExecutor;
-
-import static org.assertj.core.api.Assertions.assertThat;
+import org.junit.jupiter.api.*;
class HotReloadSchedulerReuseTest {
-
private UnleashConfig baseConfig() {
return UnleashConfig.builder()
- .appName("hot-reload-test-app")
- .instanceId("A")
- .unleashAPI("http://localhost") // never hit
- .synchronousFetchOnInitialisation(false)
- .fetchTogglesInterval(100)
- .sendMetricsInterval(100)
- .build();
+ .appName("hot-reload-test-app")
+ .instanceId("A")
+ .unleashAPI("http://localhost") // never hit
+ .synchronousFetchOnInitialisation(false)
+ .fetchTogglesInterval(100)
+ .sendMetricsInterval(100)
+ .build();
}
private ScheduledThreadPoolExecutor currentGlobalExecutor() throws Exception {
@@ -37,9 +35,7 @@ private ScheduledThreadPoolExecutor currentGlobalExecutor() throws Exception {
@Test
void secondClientDoesNotReuseSchedulerExecutor() throws Exception {
// 1) Create first client; let it schedule background tasks
- DefaultUnleash first = new DefaultUnleash(
- baseConfig()
- );
+ DefaultUnleash first = new DefaultUnleash(baseConfig());
// Let it initialize/schedule
Thread.sleep(150);
@@ -57,11 +53,10 @@ void secondClientDoesNotReuseSchedulerExecutor() throws Exception {
assertThat(execAfterShutdown).isNull();
// 3) "Reloaded app": create a second client in the same JVM (statics still around)
- DefaultUnleash second = new DefaultUnleash(
- baseConfig()
- );
+ DefaultUnleash second = new DefaultUnleash(baseConfig());
- // 4) Assert that the second client creates a fresh executor (not reusing the terminated one)
+ // 4) Assert that the second client creates a fresh executor (not reusing the terminated
+ // one)
ScheduledThreadPoolExecutor execUsedBySecond = currentGlobalExecutor();
assertThat(execUsedBySecond).isNotNull();
assertThat(execUsedBySecond.isShutdown()).isFalse(); // it's a new one