Skip to content

Commit 54fd41c

Browse files
authored
Merge pull request #512 from splitio/kerberos-okhttp
Changed Kerberos client to use okhttp lib
2 parents e388362 + d484a21 commit 54fd41c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+2028
-666
lines changed

CHANGES.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
4.13.0 (Sep 13, 2024)
2+
- Added support for Kerberos Proxy authentication.
3+
14
4.12.1 (Jun 10, 2024)
25
- Fixed deadlock for virtual thread in Push Manager and SSE Client.
36

client/pom.xml

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<parent>
66
<groupId>io.split.client</groupId>
77
<artifactId>java-client-parent</artifactId>
8-
<version>4.13.0-rc1</version>
8+
<version>4.13.0</version>
99
</parent>
1010
<artifactId>java-client</artifactId>
1111
<packaging>jar</packaging>
@@ -64,6 +64,7 @@
6464
<include>io.split.schemas:*</include>
6565
<include>io.codigo.grammar:*</include>
6666
<include>org.apache.httpcomponents.*</include>
67+
<include>org.apache.hc.*</include>
6768
<include>com.google.*</include>
6869
<include>org.yaml:snakeyaml:*</include>
6970

@@ -238,5 +239,17 @@
238239
<version>4.0.3</version>
239240
<scope>test</scope>
240241
</dependency>
242+
<dependency>
243+
<groupId>org.powermock</groupId>
244+
<artifactId>powermock-module-junit4</artifactId>
245+
<version>1.7.4</version>
246+
<scope>test</scope>
247+
</dependency>
248+
<dependency>
249+
<groupId>org.powermock</groupId>
250+
<artifactId>powermock-api-mockito</artifactId>
251+
<version>1.7.4</version>
252+
<scope>test</scope>
253+
</dependency>
241254
</dependencies>
242255
</project>

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

Lines changed: 7 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,12 @@
22

33
import io.split.client.dtos.RequestContext;
44

5-
import org.apache.hc.core5.http.HttpRequest;
6-
import org.apache.hc.core5.http.Header;
75

86
import java.util.HashSet;
9-
import java.util.HashMap;
107
import java.util.Map;
118
import java.util.Arrays;
12-
import java.util.ArrayList;
139
import java.util.Set;
14-
import java.util.List;
10+
import java.util.stream.Collectors;
1511

1612
public final class RequestDecorator {
1713
CustomHeaderDecorator _headerDecorator;
@@ -36,42 +32,16 @@ public RequestDecorator(CustomHeaderDecorator headerDecorator) {
3632
: headerDecorator;
3733
}
3834

39-
public HttpRequest decorateHeaders(HttpRequest request) {
35+
public RequestContext decorateHeaders(RequestContext request) {
4036
try {
41-
Map<String, List<String>> headers = _headerDecorator
42-
.getHeaderOverrides(new RequestContext(convertToMap(request.getHeaders())));
43-
for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
44-
if (isHeaderAllowed(entry.getKey())) {
45-
List<String> values = entry.getValue();
46-
for (int i = 0; i < values.size(); i++) {
47-
if (i == 0) {
48-
request.setHeader(entry.getKey(), values.get(i));
49-
} else {
50-
request.addHeader(entry.getKey(), values.get(i));
51-
}
52-
}
53-
}
54-
}
37+
return new RequestContext(_headerDecorator.getHeaderOverrides(request)
38+
.entrySet()
39+
.stream()
40+
.filter(e -> !forbiddenHeaders.contains(e.getKey().toLowerCase()))
41+
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)));
5542
} catch (Exception e) {
5643
throw new IllegalArgumentException(
5744
String.format("Problem adding custom headers to request decorator: %s", e), e);
5845
}
59-
60-
return request;
61-
}
62-
63-
private boolean isHeaderAllowed(String headerName) {
64-
return !forbiddenHeaders.contains(headerName.toLowerCase());
65-
}
66-
67-
private Map<String, List<String>> convertToMap(Header[] to_convert) {
68-
Map<String, List<String>> to_return = new HashMap<String, List<String>>();
69-
for (Integer i = 0; i < to_convert.length; i++) {
70-
if (!to_return.containsKey(to_convert[i].getName())) {
71-
to_return.put(to_convert[i].getName(), new ArrayList<String>());
72-
}
73-
to_return.get(to_convert[i].getName()).add(to_convert[i].getValue());
74-
}
75-
return to_return;
7646
}
7747
}

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

Lines changed: 78 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
import io.split.client.impressions.ImpressionsManager;
55
import io.split.client.utils.FileTypeEnum;
66
import io.split.integrations.IntegrationsConfig;
7+
import io.split.service.CustomHttpModule;
78
import io.split.storages.enums.OperationMode;
89
import io.split.storages.enums.StorageMode;
9-
import io.split.service.HttpAuthScheme;
1010
import org.apache.hc.core5.http.HttpHost;
1111
import pluggable.CustomStorageWrapper;
1212

@@ -92,8 +92,7 @@ public class SplitClientConfig {
9292
private final HashSet<String> _flagSetsFilter;
9393
private final int _invalidSets;
9494
private final CustomHeaderDecorator _customHeaderDecorator;
95-
private final HttpAuthScheme _authScheme;
96-
95+
private final CustomHttpModule _alternativeHTTPModule;
9796

9897
public static Builder builder() {
9998
return new Builder();
@@ -151,7 +150,7 @@ private SplitClientConfig(String endpoint,
151150
HashSet<String> flagSetsFilter,
152151
int invalidSets,
153152
CustomHeaderDecorator customHeaderDecorator,
154-
HttpAuthScheme authScheme) {
153+
CustomHttpModule alternativeHTTPModule) {
155154
_endpoint = endpoint;
156155
_eventsEndpoint = eventsEndpoint;
157156
_featuresRefreshRate = pollForFeatureChangesEveryNSeconds;
@@ -204,7 +203,7 @@ private SplitClientConfig(String endpoint,
204203
_flagSetsFilter = flagSetsFilter;
205204
_invalidSets = invalidSets;
206205
_customHeaderDecorator = customHeaderDecorator;
207-
_authScheme = authScheme;
206+
_alternativeHTTPModule = alternativeHTTPModule;
208207

209208
Properties props = new Properties();
210209
try {
@@ -412,10 +411,8 @@ public int getInvalidSets() {
412411
public CustomHeaderDecorator customHeaderDecorator() {
413412
return _customHeaderDecorator;
414413
}
415-
public HttpAuthScheme authScheme() {
416-
return _authScheme;
417-
}
418414

415+
public CustomHttpModule alternativeHTTPModule() { return _alternativeHTTPModule; }
419416
public static final class Builder {
420417

421418
private String _endpoint = SDK_ENDPOINT;
@@ -473,7 +470,7 @@ public static final class Builder {
473470
private HashSet<String> _flagSetsFilter = new HashSet<>();
474471
private int _invalidSetsCount = 0;
475472
private CustomHeaderDecorator _customHeaderDecorator = null;
476-
private HttpAuthScheme _authScheme = null;
473+
private CustomHttpModule _alternativeHTTPModule = null;
477474

478475
public Builder() {
479476
}
@@ -969,13 +966,13 @@ public Builder customHeaderDecorator(CustomHeaderDecorator customHeaderDecorator
969966
}
970967

971968
/**
972-
* Authentication Scheme
969+
* Alternative Http Client
973970
*
974-
* @param authScheme
971+
* @param alternativeHTTPModule
975972
* @return this builder
976973
*/
977-
public Builder authScheme(HttpAuthScheme authScheme) {
978-
_authScheme = authScheme;
974+
public Builder alternativeHTTPModule(CustomHttpModule alternativeHTTPModule) {
975+
_alternativeHTTPModule = alternativeHTTPModule;
979976
return this;
980977
}
981978

@@ -990,7 +987,7 @@ public Builder threadFactory(ThreadFactory threadFactory) {
990987
return this;
991988
}
992989

993-
public SplitClientConfig build() {
990+
private void verifyRates() {
994991
if (_featuresRefreshRate < 5 ) {
995992
throw new IllegalArgumentException("featuresRefreshRate must be >= 5: " + _featuresRefreshRate);
996993
}
@@ -999,35 +996,19 @@ public SplitClientConfig build() {
999996
throw new IllegalArgumentException("segmentsRefreshRate must be >= 30: " + _segmentsRefreshRate);
1000997
}
1001998

1002-
switch (_impressionsMode) {
1003-
case OPTIMIZED:
1004-
_impressionsRefreshRate = (_impressionsRefreshRate <= 0) ? 300 : Math.max(60, _impressionsRefreshRate);
1005-
break;
1006-
case DEBUG:
1007-
_impressionsRefreshRate = (_impressionsRefreshRate <= 0) ? 60 : _impressionsRefreshRate;
1008-
break;
1009-
}
1010-
1011999
if (_eventSendIntervalInMillis < 1000) {
10121000
throw new IllegalArgumentException("_eventSendIntervalInMillis must be >= 1000: " + _eventSendIntervalInMillis);
10131001
}
10141002

10151003
if (_metricsRefreshRate < 30) {
10161004
throw new IllegalArgumentException("metricsRefreshRate must be >= 30: " + _metricsRefreshRate);
10171005
}
1018-
1019-
if (_impressionsQueueSize <=0 ) {
1020-
throw new IllegalArgumentException("impressionsQueueSize must be > 0: " + _impressionsQueueSize);
1021-
}
1022-
1023-
if (_connectionTimeout <= 0) {
1024-
throw new IllegalArgumentException("connectionTimeOutInMs must be > 0: " + _connectionTimeout);
1025-
}
1026-
1027-
if (_readTimeout <= 0) {
1028-
throw new IllegalArgumentException("readTimeout must be > 0: " + _readTimeout);
1006+
if(_telemetryRefreshRate < 60) {
1007+
throw new IllegalStateException("_telemetryRefreshRate must be >= 60");
10291008
}
1009+
}
10301010

1011+
private void verifyEndPoints() {
10311012
if (_endpoint == null) {
10321013
throw new IllegalArgumentException("endpoint must not be null");
10331014
}
@@ -1040,18 +1021,6 @@ public SplitClientConfig build() {
10401021
throw new IllegalArgumentException("If endpoint is set, you must also set the events endpoint");
10411022
}
10421023

1043-
if (_numThreadsForSegmentFetch <= 0) {
1044-
throw new IllegalArgumentException("Number of threads for fetching segments MUST be greater than zero");
1045-
}
1046-
1047-
if (_authRetryBackoffBase <= 0) {
1048-
throw new IllegalArgumentException("authRetryBackoffBase: must be >= 1");
1049-
}
1050-
1051-
if (_streamingReconnectBackoffBase <= 0) {
1052-
throw new IllegalArgumentException("streamingReconnectBackoffBase: must be >= 1");
1053-
}
1054-
10551024
if (_authServiceURL == null) {
10561025
throw new IllegalArgumentException("authServiceURL must not be null");
10571026
}
@@ -1063,31 +1032,83 @@ public SplitClientConfig build() {
10631032
if (_telemetryURl == null) {
10641033
throw new IllegalArgumentException("telemetryURl must not be null");
10651034
}
1035+
}
10661036

1067-
if (_onDemandFetchRetryDelayMs <= 0) {
1068-
throw new IllegalStateException("streamingRetryDelay must be > 0");
1037+
private void verifyAllModes() {
1038+
switch (_impressionsMode) {
1039+
case OPTIMIZED:
1040+
_impressionsRefreshRate = (_impressionsRefreshRate <= 0) ? 300 : Math.max(60, _impressionsRefreshRate);
1041+
break;
1042+
case DEBUG:
1043+
_impressionsRefreshRate = (_impressionsRefreshRate <= 0) ? 60 : _impressionsRefreshRate;
1044+
break;
1045+
case NONE:
1046+
break;
10691047
}
10701048

1071-
if(_onDemandFetchMaxRetries <= 0) {
1072-
throw new IllegalStateException("_onDemandFetchMaxRetries must be > 0");
1049+
if (_impressionsQueueSize <=0 ) {
1050+
throw new IllegalArgumentException("impressionsQueueSize must be > 0: " + _impressionsQueueSize);
10731051
}
1074-
10751052
if(_storageMode == null) {
10761053
_storageMode = StorageMode.MEMORY;
10771054
}
1078-
1079-
if(_telemetryRefreshRate < 60) {
1080-
throw new IllegalStateException("_telemetryRefreshRate must be >= 60");
1081-
}
10821055

10831056
if(OperationMode.CONSUMER.equals(_operationMode)){
10841057
if(_customStorageWrapper == null) {
10851058
throw new IllegalStateException("Custom Storage must not be null on Consumer mode.");
10861059
}
10871060
_storageMode = StorageMode.PLUGGABLE;
10881061
}
1062+
}
1063+
1064+
private void verifyNetworkParams() {
1065+
if (_connectionTimeout <= 0) {
1066+
throw new IllegalArgumentException("connectionTimeOutInMs must be > 0: " + _connectionTimeout);
1067+
}
1068+
1069+
if (_readTimeout <= 0) {
1070+
throw new IllegalArgumentException("readTimeout must be > 0: " + _readTimeout);
1071+
}
1072+
if (_authRetryBackoffBase <= 0) {
1073+
throw new IllegalArgumentException("authRetryBackoffBase: must be >= 1");
1074+
}
1075+
1076+
if (_streamingReconnectBackoffBase <= 0) {
1077+
throw new IllegalArgumentException("streamingReconnectBackoffBase: must be >= 1");
1078+
}
1079+
1080+
if (_onDemandFetchRetryDelayMs <= 0) {
1081+
throw new IllegalStateException("streamingRetryDelay must be > 0");
1082+
}
1083+
1084+
if(_onDemandFetchMaxRetries <= 0) {
1085+
throw new IllegalStateException("_onDemandFetchMaxRetries must be > 0");
1086+
}
1087+
}
1088+
1089+
private void verifyAlternativeClient() {
1090+
if (_alternativeHTTPModule != null && _streamingEnabled) {
1091+
throw new IllegalArgumentException("Streaming feature is not supported with Alternative HTTP Client");
1092+
}
1093+
}
1094+
1095+
public SplitClientConfig build() {
1096+
1097+
verifyRates();
1098+
1099+
verifyAllModes();
1100+
1101+
verifyEndPoints();
1102+
1103+
verifyNetworkParams();
1104+
1105+
verifyAlternativeClient();
1106+
1107+
if (_numThreadsForSegmentFetch <= 0) {
1108+
throw new IllegalArgumentException("Number of threads for fetching segments MUST be greater than zero");
1109+
}
10891110

1090-
return new SplitClientConfig(
1111+
return new SplitClientConfig(
10911112
_endpoint,
10921113
_eventsEndpoint,
10931114
_featuresRefreshRate,
@@ -1140,7 +1161,7 @@ public SplitClientConfig build() {
11401161
_flagSetsFilter,
11411162
_invalidSetsCount,
11421163
_customHeaderDecorator,
1143-
_authScheme);
1164+
_alternativeHTTPModule);
11441165
}
11451166
}
11461167
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import io.split.inputValidation.ApiKeyValidator;
44
import io.split.grammar.Treatments;
5+
import io.split.service.SplitHttpClient;
56
import io.split.storages.enums.StorageMode;
67
import org.slf4j.Logger;
78
import org.slf4j.LoggerFactory;

0 commit comments

Comments
 (0)