5
5
import com .launchdarkly .sdk .internal .http .HttpHelpers ;
6
6
import com .launchdarkly .sdk .internal .http .HttpProperties ;
7
7
8
+ import java .io .ByteArrayOutputStream ;
8
9
import java .io .IOException ;
9
10
import java .net .URI ;
10
11
import java .nio .charset .Charset ;
13
14
import java .util .Date ;
14
15
import java .util .Locale ;
15
16
import java .util .UUID ;
17
+ import java .util .zip .GZIPOutputStream ;
16
18
17
19
import static com .launchdarkly .sdk .internal .http .HttpErrors .checkIfErrorIsRecoverableAndLog ;
18
20
import static com .launchdarkly .sdk .internal .http .HttpErrors .httpErrorDescription ;
@@ -55,13 +57,24 @@ public final class DefaultEventSender implements EventSender {
55
57
Locale .US ); // server dates as defined by RFC-822/RFC-1123 use English day/month names
56
58
private static final Object HTTP_DATE_FORMAT_LOCK = new Object (); // synchronize on this because DateFormat isn't thread-safe
57
59
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
+
58
70
private final OkHttpClient httpClient ;
59
71
private final boolean shouldCloseHttpClient ;
60
72
private final Headers baseHeaders ;
61
73
private final String analyticsRequestPath ;
62
74
private final String diagnosticRequestPath ;
63
75
final long retryDelayMillis ; // visible for testing
64
76
private final LDLogger logger ;
77
+ private final boolean enableGzipCompression ;
65
78
66
79
/**
67
80
* Creates an instance.
@@ -70,13 +83,15 @@ public final class DefaultEventSender implements EventSender {
70
83
* @param analyticsRequestPath the request path for posting analytics events
71
84
* @param diagnosticRequestPath the request path for posting diagnostic events
72
85
* @param retryDelayMillis retry delay, or zero to use the default
86
+ * @param enableGzipCompression whether to enable gzip compression
73
87
* @param logger the logger
74
88
*/
75
89
public DefaultEventSender (
76
90
HttpProperties httpProperties ,
77
91
String analyticsRequestPath ,
78
92
String diagnosticRequestPath ,
79
93
long retryDelayMillis ,
94
+ boolean enableGzipCompression ,
80
95
LDLogger logger
81
96
) {
82
97
if (httpProperties .getSharedHttpClient () == null ) {
@@ -87,6 +102,7 @@ public DefaultEventSender(
87
102
shouldCloseHttpClient = false ;
88
103
}
89
104
this .logger = logger ;
105
+ this .enableGzipCompression = enableGzipCompression ;
90
106
91
107
this .baseHeaders = httpProperties .toHeadersBuilder ()
92
108
.add ("Content-Type" , "application/json" )
@@ -115,6 +131,24 @@ public Result sendDiagnosticEvent(byte[] data, URI eventsBaseUri) {
115
131
return sendEventData (true , data , 1 , eventsBaseUri );
116
132
}
117
133
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
+
118
152
private Result sendEventData (boolean isDiagnostic , byte [] data , int eventCount , URI eventsBaseUri ) {
119
153
if (data == null || data .length == 0 ) {
120
154
// 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,
137
171
}
138
172
139
173
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 );
142
176
boolean mustShutDown = false ;
143
177
178
+ if (compressionResult .wasCompressed ) {
179
+ headersBuilder .add ("Content-Encoding" , "gzip" );
180
+ }
181
+
182
+ Headers headers = headersBuilder .build ();
144
183
logger .debug ("Posting {} to {} with payload: {}" , description , uri ,
145
184
LogValues .defer (new LazilyPrintedUtf8Data (data )));
146
185
0 commit comments