Skip to content

Commit 13bcbd4

Browse files
authored
Merge pull request #491 from splitio/add-response-headers
added headers to httpsplitresponse and polish
2 parents 5541213 + 493c8f6 commit 13bcbd4

17 files changed

+209
-124
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package io.split.client;
2+
3+
import io.split.client.dtos.RequestContext;
4+
5+
import java.util.Map;
6+
import java.util.List;
7+
8+
public interface CustomHeaderDecorator
9+
{
10+
/**
11+
* Get the additional headers needed for all http operations
12+
* @return HashMap of addition headers
13+
*/
14+
Map<String, List<String>> getHeaderOverrides(RequestContext context);
15+
}

client/src/main/java/io/split/client/HttpSegmentChangeFetcher.java

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,6 @@ private HttpSegmentChangeFetcher(SplitHttpClient client, URI uri, TelemetryRunti
5151
public SegmentChange fetch(String segmentName, long since, FetchOptions options) {
5252
long start = System.currentTimeMillis();
5353

54-
SplitHttpResponse response;
55-
5654
try {
5755
String path = _target.getPath() + "/" + segmentName;
5856
URIBuilder uriBuilder = new URIBuilder(_target)
@@ -64,20 +62,20 @@ public SegmentChange fetch(String segmentName, long since, FetchOptions options)
6462

6563
URI uri = uriBuilder.build();
6664

67-
response = _client.get(uri, options);
65+
SplitHttpResponse response = _client.get(uri, options, null);
6866

69-
if (response.statusCode < HttpStatus.SC_OK || response.statusCode >= HttpStatus.SC_MULTIPLE_CHOICES) {
70-
_telemetryRuntimeProducer.recordSyncError(ResourceEnum.SEGMENT_SYNC, response.statusCode);
71-
if (response.statusCode == HttpStatus.SC_FORBIDDEN) {
67+
if (response.statusCode() < HttpStatus.SC_OK || response.statusCode() >= HttpStatus.SC_MULTIPLE_CHOICES) {
68+
_telemetryRuntimeProducer.recordSyncError(ResourceEnum.SEGMENT_SYNC, response.statusCode());
69+
if (response.statusCode() == HttpStatus.SC_FORBIDDEN) {
7270
_log.error("factory instantiation: you passed a client side type sdkKey, " +
7371
"please grab an sdk key from the Split user interface that is of type server side");
7472
}
7573
throw new IllegalStateException(String.format("Could not retrieve segment changes for %s, since %s; http return code %s",
76-
segmentName, since, response.statusCode));
74+
segmentName, since, response.statusCode()));
7775
}
7876
_telemetryRuntimeProducer.recordSuccessfulSync(LastSynchronizationRecordsEnum.SEGMENTS, System.currentTimeMillis());
7977

80-
return Json.fromJson(response.body, SegmentChange.class);
78+
return Json.fromJson(response.body(), SegmentChange.class);
8179
} catch (Exception e) {
8280
throw new IllegalStateException(String.format("Error occurred when trying to sync segment: %s, since: %s. Details: %s",
8381
segmentName, since, e), e);

client/src/main/java/io/split/client/HttpSplitChangeFetcher.java

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,6 @@ public SplitChange fetch(long since, FetchOptions options) {
5757

5858
long start = System.currentTimeMillis();
5959

60-
SplitHttpResponse response = null;
61-
6260
try {
6361
URIBuilder uriBuilder = new URIBuilder(_target).addParameter(SINCE, "" + since);
6462
if (options.hasCustomCN()) {
@@ -68,20 +66,20 @@ public SplitChange fetch(long since, FetchOptions options) {
6866
uriBuilder.addParameter(SETS, "" + options.flagSetsFilter());
6967
}
7068
URI uri = uriBuilder.build();
71-
response = _client.get(uri, options);
69+
SplitHttpResponse response = _client.get(uri, options, null);
7270

73-
if (response.statusCode < HttpStatus.SC_OK || response.statusCode >= HttpStatus.SC_MULTIPLE_CHOICES) {
74-
if (response.statusCode == HttpStatus.SC_REQUEST_URI_TOO_LONG) {
71+
if (response.statusCode() < HttpStatus.SC_OK || response.statusCode() >= HttpStatus.SC_MULTIPLE_CHOICES) {
72+
if (response.statusCode() == HttpStatus.SC_REQUEST_URI_TOO_LONG) {
7573
_log.error("The amount of flag sets provided are big causing uri length error.");
76-
throw new UriTooLongException(String.format("Status code: %s. Message: %s", response.statusCode, response.statusMessage));
74+
throw new UriTooLongException(String.format("Status code: %s. Message: %s", response.statusCode(), response.statusMessage()));
7775
}
78-
_telemetryRuntimeProducer.recordSyncError(ResourceEnum.SPLIT_SYNC, response.statusCode);
76+
_telemetryRuntimeProducer.recordSyncError(ResourceEnum.SPLIT_SYNC, response.statusCode());
7977
throw new IllegalStateException(
80-
String.format("Could not retrieve splitChanges since %s; http return code %s", since, response.statusCode)
78+
String.format("Could not retrieve splitChanges since %s; http return code %s", since, response.statusCode())
8179
);
8280
}
8381

84-
return Json.fromJson(response.body, SplitChange.class);
82+
return Json.fromJson(response.body(), SplitChange.class);
8583
} catch (Exception e) {
8684
throw new IllegalStateException(String.format("Problem fetching splitChanges since %s: %s", since, e), e);
8785
} finally {

client/src/main/java/io/split/client/RequestDecorator.java

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,28 @@
11
package io.split.client;
22

3+
import io.split.client.dtos.RequestContext;
4+
35
import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase;
6+
import org.apache.hc.core5.http.Header;
7+
48
import java.util.HashSet;
59
import java.util.HashMap;
610
import java.util.Map;
711
import java.util.Arrays;
12+
import java.util.ArrayList;
813
import java.util.Set;
14+
import java.util.List;
915

10-
class NoOpHeaderDecorator implements UserCustomHeaderDecorator {
16+
class NoOpHeaderDecorator implements CustomHeaderDecorator {
1117
public NoOpHeaderDecorator() {}
1218
@Override
13-
public Map<String, String> getHeaderOverrides() {
19+
public Map<String, List<String>> getHeaderOverrides(RequestContext context) {
1420
return new HashMap<>();
1521
}
1622
}
1723

1824
public final class RequestDecorator {
19-
UserCustomHeaderDecorator _headerDecorator;
25+
CustomHeaderDecorator _headerDecorator;
2026

2127
private static final Set<String> forbiddenHeaders = new HashSet<>(Arrays.asList(
2228
"splitsdkversion",
@@ -33,18 +39,25 @@ public final class RequestDecorator {
3339
"x-fastly-debug"
3440
));
3541

36-
public RequestDecorator(UserCustomHeaderDecorator headerDecorator) {
42+
public RequestDecorator(CustomHeaderDecorator headerDecorator) {
3743
_headerDecorator = (headerDecorator == null)
3844
? new NoOpHeaderDecorator()
3945
: headerDecorator;
4046
}
4147

4248
public HttpUriRequestBase decorateHeaders(HttpUriRequestBase request) {
4349
try {
44-
Map<String, String> headers = _headerDecorator.getHeaderOverrides();
50+
Map<String, List<String>> headers = _headerDecorator.getHeaderOverrides(new RequestContext(convertToMap(request.getHeaders())));
4551
for (Map.Entry entry : headers.entrySet()) {
4652
if (isHeaderAllowed(entry.getKey().toString())) {
47-
request.addHeader(entry.getKey().toString(), entry.getValue());
53+
List<String> values = (List<String>) entry.getValue();
54+
for (int i = 0; i < values.size(); i++) {
55+
if (i == 0) {
56+
request.setHeader(entry.getKey().toString(), values.get(i));
57+
} else {
58+
request.addHeader(entry.getKey().toString(), values.get(i));
59+
}
60+
}
4861
}
4962
}
5063
} catch (Exception e) {
@@ -57,4 +70,14 @@ public HttpUriRequestBase decorateHeaders(HttpUriRequestBase request) {
5770
private boolean isHeaderAllowed(String headerName) {
5871
return !forbiddenHeaders.contains(headerName.toLowerCase());
5972
}
73+
private Map<String, List<String>> convertToMap(Header[] to_convert) {
74+
Map<String, List<String>> to_return = new HashMap<String, List<String>>();
75+
for (Integer i = 0; i < to_convert.length; i++ ) {
76+
if (!to_return.containsKey(to_convert[i].getName())) {
77+
to_return.put(to_convert[i].getName(), new ArrayList<String>());
78+
}
79+
to_return.get(to_convert[i].getName()).add(to_convert[i].getValue());
80+
}
81+
return to_return;
82+
}
6083
}

client/src/main/java/io/split/client/SplitClientConfig.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ public class SplitClientConfig {
9090
private final long _lastSeenCacheSize;
9191
private final HashSet<String> _flagSetsFilter;
9292
private final int _invalidSets;
93-
private final UserCustomHeaderDecorator _userCustomHeaderDecorator;
93+
private final CustomHeaderDecorator _customHeaderDecorator;
9494

9595

9696
public static Builder builder() {
@@ -148,7 +148,7 @@ private SplitClientConfig(String endpoint,
148148
ThreadFactory threadFactory,
149149
HashSet<String> flagSetsFilter,
150150
int invalidSets,
151-
UserCustomHeaderDecorator userCustomHeaderDecorator) {
151+
CustomHeaderDecorator customHeaderDecorator) {
152152
_endpoint = endpoint;
153153
_eventsEndpoint = eventsEndpoint;
154154
_featuresRefreshRate = pollForFeatureChangesEveryNSeconds;
@@ -200,7 +200,7 @@ private SplitClientConfig(String endpoint,
200200
_threadFactory = threadFactory;
201201
_flagSetsFilter = flagSetsFilter;
202202
_invalidSets = invalidSets;
203-
_userCustomHeaderDecorator = userCustomHeaderDecorator;
203+
_customHeaderDecorator = customHeaderDecorator;
204204

205205
Properties props = new Properties();
206206
try {
@@ -397,8 +397,8 @@ public int getInvalidSets() {
397397
return _invalidSets;
398398
}
399399

400-
public UserCustomHeaderDecorator userCustomHeaderDecorator() {
401-
return _userCustomHeaderDecorator;
400+
public CustomHeaderDecorator customHeaderDecorator() {
401+
return _customHeaderDecorator;
402402
}
403403

404404
public static final class Builder {
@@ -457,7 +457,7 @@ public static final class Builder {
457457
private ThreadFactory _threadFactory;
458458
private HashSet<String> _flagSetsFilter = new HashSet<>();
459459
private int _invalidSetsCount = 0;
460-
private UserCustomHeaderDecorator _userCustomHeaderDecorator = null;
460+
private CustomHeaderDecorator _customHeaderDecorator = null;
461461

462462
public Builder() {
463463
}
@@ -944,11 +944,11 @@ public Builder flagSetsFilter(List<String> flagSetsFilter) {
944944
/**
945945
* User Custom Header Decorator
946946
*
947-
* @param userCustomHeaderDecorator
947+
* @param customHeaderDecorator
948948
* @return this builder
949949
*/
950-
public Builder userCustomHeaderDecorator(UserCustomHeaderDecorator userCustomHeaderDecorator) {
951-
_userCustomHeaderDecorator = userCustomHeaderDecorator;
950+
public Builder customHeaderDecorator(CustomHeaderDecorator customHeaderDecorator) {
951+
_customHeaderDecorator = customHeaderDecorator;
952952
return this;
953953
}
954954

@@ -1112,7 +1112,7 @@ public SplitClientConfig build() {
11121112
_threadFactory,
11131113
_flagSetsFilter,
11141114
_invalidSetsCount,
1115-
_userCustomHeaderDecorator);
1115+
_customHeaderDecorator);
11161116
}
11171117
}
11181118
}

client/src/main/java/io/split/client/SplitFactoryImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -508,7 +508,7 @@ private static SplitHttpClient buildSplitHttpClient(String apiToken, SplitClient
508508
httpClientbuilder = setupProxy(httpClientbuilder, config);
509509
}
510510

511-
return SplitHttpClientImpl.create(httpClientbuilder.build(), new RequestDecorator(config.userCustomHeaderDecorator()));
511+
return SplitHttpClientImpl.create(httpClientbuilder.build(), new RequestDecorator(config.customHeaderDecorator()));
512512
}
513513

514514
private static CloseableHttpClient buildSSEdHttpClient(String apiToken, SplitClientConfig config, SDKMetadata sdkMetadata) {

client/src/main/java/io/split/client/UserCustomHeaderDecorator.java

Lines changed: 0 additions & 12 deletions
This file was deleted.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package io.split.client.dtos;
2+
3+
import java.util.Map;
4+
import java.util.List;
5+
/**
6+
* A structure returning a context for RequestDecorator class
7+
*/
8+
9+
public class RequestContext
10+
{
11+
private final Map<String, List<String>> _headers;
12+
13+
public RequestContext(Map<String, List<String>> headers) {
14+
_headers = headers;
15+
}
16+
17+
public Map<String, List<String>> headers() {
18+
return _headers;
19+
}
20+
}
Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,34 @@
11
package io.split.client.dtos;
22

3+
import java.util.Map;
4+
import org.apache.hc.core5.http.Header;
35
/**
46
* A structure for returning http call results information
57
*/
68
public class SplitHttpResponse {
7-
public Integer statusCode;
8-
public String statusMessage;
9-
public String body;
9+
private final Integer _statusCode;
10+
private final String _statusMessage;
11+
private final String _body;
12+
private final Header[] _responseHeaders;
13+
14+
public SplitHttpResponse(Integer statusCode, String statusMessage, String body, Header[] headers) {
15+
_statusCode = statusCode;
16+
_statusMessage = statusMessage;
17+
_body = body;
18+
_responseHeaders = headers;
19+
}
20+
public Integer statusCode() {
21+
return _statusCode;
22+
}
23+
public String statusMessage() {
24+
return _statusMessage;
25+
}
26+
27+
public String body() {
28+
return _body;
29+
}
30+
31+
public Header[] responseHeaders() {
32+
return _responseHeaders;
33+
}
1034
}

client/src/main/java/io/split/client/impressions/HttpImpressionsSender.java

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,17 +62,15 @@ private HttpImpressionsSender(SplitHttpClient client, URI impressionBulkTarget,
6262

6363
@Override
6464
public void postImpressionsBulk(List<TestImpressions> impressions) {
65-
66-
SplitHttpResponse response;
6765
long initTime = System.currentTimeMillis();
6866
try {
6967
HttpEntity entity = Utils.toJsonEntity(impressions);
7068
Map<String, String> additionalHeader = new HashMap<>();
7169
additionalHeader.put(IMPRESSIONS_MODE_HEADER, _mode.toString());
72-
response = _client.post(_impressionBulkTarget, entity, additionalHeader);
70+
SplitHttpResponse response = _client.post(_impressionBulkTarget, entity, additionalHeader);
7371

74-
if (response.statusCode < HttpStatus.SC_OK || response.statusCode >= HttpStatus.SC_MULTIPLE_CHOICES) {
75-
_telemetryRuntimeProducer.recordSyncError(ResourceEnum.IMPRESSION_SYNC, response.statusCode);
72+
if (response.statusCode() < HttpStatus.SC_OK || response.statusCode() >= HttpStatus.SC_MULTIPLE_CHOICES) {
73+
_telemetryRuntimeProducer.recordSyncError(ResourceEnum.IMPRESSION_SYNC, response.statusCode());
7674
}
7775
_telemetryRuntimeProducer.recordSuccessfulSync(LastSynchronizationRecordsEnum.IMPRESSIONS, System.currentTimeMillis());
7876

@@ -96,8 +94,8 @@ public void postCounters(HashMap<ImpressionCounter.Key, Integer> raw) {
9694
Utils.toJsonEntity(ImpressionCount.fromImpressionCounterData(raw)),
9795
null);
9896

99-
if (response.statusCode < HttpStatus.SC_OK || response.statusCode >= HttpStatus.SC_MULTIPLE_CHOICES) {
100-
_telemetryRuntimeProducer.recordSyncError(ResourceEnum.IMPRESSION_COUNT_SYNC, response.statusCode);
97+
if (response.statusCode() < HttpStatus.SC_OK || response.statusCode() >= HttpStatus.SC_MULTIPLE_CHOICES) {
98+
_telemetryRuntimeProducer.recordSyncError(ResourceEnum.IMPRESSION_COUNT_SYNC, response.statusCode());
10199
}
102100
_telemetryRuntimeProducer.recordSyncLatency(HTTPLatenciesEnum.IMPRESSIONS_COUNT, System.currentTimeMillis() - initTime);
103101
_telemetryRuntimeProducer.recordSuccessfulSync(LastSynchronizationRecordsEnum.IMPRESSIONS_COUNT, System.currentTimeMillis());

0 commit comments

Comments
 (0)