55import com .launchdarkly .sdk .internal .http .HttpHelpers ;
66import com .launchdarkly .sdk .internal .http .HttpProperties ;
77
8+ import java .io .ByteArrayOutputStream ;
89import java .io .IOException ;
910import java .net .URI ;
1011import java .nio .charset .Charset ;
1314import java .util .Date ;
1415import java .util .Locale ;
1516import java .util .UUID ;
17+ import java .util .zip .GZIPOutputStream ;
1618
1719import static com .launchdarkly .sdk .internal .http .HttpErrors .checkIfErrorIsRecoverableAndLog ;
1820import static com .launchdarkly .sdk .internal .http .HttpErrors .httpErrorDescription ;
@@ -55,13 +57,24 @@ public final class DefaultEventSender implements EventSender {
5557 Locale .US ); // server dates as defined by RFC-822/RFC-1123 use English day/month names
5658 private static final Object HTTP_DATE_FORMAT_LOCK = new Object (); // synchronize on this because DateFormat isn't thread-safe
5759
60+ private static class CompressionResult <T > {
61+ final T data ;
62+ final boolean wasCompressed ;
63+
64+ CompressionResult (T data , boolean wasCompressed ) {
65+ this .data = data ;
66+ this .wasCompressed = wasCompressed ;
67+ }
68+ }
69+
5870 private final OkHttpClient httpClient ;
5971 private final boolean shouldCloseHttpClient ;
6072 private final Headers baseHeaders ;
6173 private final String analyticsRequestPath ;
6274 private final String diagnosticRequestPath ;
6375 final long retryDelayMillis ; // visible for testing
6476 private final LDLogger logger ;
77+ private final boolean enableGzipCompression ;
6578
6679 /**
6780 * Creates an instance.
@@ -70,13 +83,15 @@ public final class DefaultEventSender implements EventSender {
7083 * @param analyticsRequestPath the request path for posting analytics events
7184 * @param diagnosticRequestPath the request path for posting diagnostic events
7285 * @param retryDelayMillis retry delay, or zero to use the default
86+ * @param enableGzipCompression whether to enable gzip compression
7387 * @param logger the logger
7488 */
7589 public DefaultEventSender (
7690 HttpProperties httpProperties ,
7791 String analyticsRequestPath ,
7892 String diagnosticRequestPath ,
7993 long retryDelayMillis ,
94+ boolean enableGzipCompression ,
8095 LDLogger logger
8196 ) {
8297 if (httpProperties .getSharedHttpClient () == null ) {
@@ -87,6 +102,7 @@ public DefaultEventSender(
87102 shouldCloseHttpClient = false ;
88103 }
89104 this .logger = logger ;
105+ this .enableGzipCompression = enableGzipCompression ;
90106
91107 this .baseHeaders = httpProperties .toHeadersBuilder ()
92108 .add ("Content-Type" , "application/json" )
@@ -115,6 +131,24 @@ public Result sendDiagnosticEvent(byte[] data, URI eventsBaseUri) {
115131 return sendEventData (true , data , 1 , eventsBaseUri );
116132 }
117133
134+ private CompressionResult <byte []> compressData (byte [] data ) {
135+ if (!enableGzipCompression ) {
136+ return new CompressionResult <>(data , false );
137+ }
138+
139+ try {
140+ ByteArrayOutputStream byteStream = new ByteArrayOutputStream ();
141+ try (GZIPOutputStream gzipStream = new GZIPOutputStream (byteStream )) {
142+ gzipStream .write (data );
143+ }
144+ byte [] compressedData = byteStream .toByteArray ();
145+ return new CompressionResult <>(compressedData , true );
146+ } catch (IOException e ) {
147+ logger .warn ("Failed to compress event data, falling back to uncompressed: {}" , e .toString ());
148+ return new CompressionResult <>(data , false );
149+ }
150+ }
151+
118152 private Result sendEventData (boolean isDiagnostic , byte [] data , int eventCount , URI eventsBaseUri ) {
119153 if (data == null || data .length == 0 ) {
120154 // DefaultEventProcessor won't normally pass us an empty payload, but if it does, don't bother sending
@@ -137,10 +171,15 @@ private Result sendEventData(boolean isDiagnostic, byte[] data, int eventCount,
137171 }
138172
139173 URI uri = HttpHelpers .concatenateUriPath (eventsBaseUri , path );
140- Headers headers = headersBuilder . build ( );
141- RequestBody body = RequestBody .create (data , JSON_CONTENT_TYPE );
174+ CompressionResult < byte []> compressionResult = compressData ( data );
175+ RequestBody body = RequestBody .create (compressionResult . data , JSON_CONTENT_TYPE );
142176 boolean mustShutDown = false ;
143177
178+ if (compressionResult .wasCompressed ) {
179+ headersBuilder .add ("Content-Encoding" , "gzip" );
180+ }
181+
182+ Headers headers = headersBuilder .build ();
144183 logger .debug ("Posting {} to {} with payload: {}" , description , uri ,
145184 LogValues .defer (new LazilyPrintedUtf8Data (data )));
146185
0 commit comments