Skip to content

Commit bb87766

Browse files
author
Bilal Al
committed
separated httpclient from module
1 parent 1e9482d commit bb87766

File tree

7 files changed

+248
-261
lines changed

7 files changed

+248
-261
lines changed

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
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.SplitHttpClient;
7+
import io.split.service.CustomHttpModule;
88
import io.split.storages.enums.OperationMode;
99
import io.split.storages.enums.StorageMode;
1010
import org.apache.hc.core5.http.HttpHost;
@@ -92,7 +92,7 @@ public class SplitClientConfig {
9292
private final HashSet<String> _flagSetsFilter;
9393
private final int _invalidSets;
9494
private final CustomHeaderDecorator _customHeaderDecorator;
95-
private final SplitHttpClient _alternativeHTTPModule;
95+
private final CustomHttpModule _alternativeHTTPModule;
9696

9797
public static Builder builder() {
9898
return new Builder();
@@ -150,7 +150,7 @@ private SplitClientConfig(String endpoint,
150150
HashSet<String> flagSetsFilter,
151151
int invalidSets,
152152
CustomHeaderDecorator customHeaderDecorator,
153-
SplitHttpClient alternativeHTTPModule) {
153+
CustomHttpModule alternativeHTTPModule) {
154154
_endpoint = endpoint;
155155
_eventsEndpoint = eventsEndpoint;
156156
_featuresRefreshRate = pollForFeatureChangesEveryNSeconds;
@@ -412,7 +412,7 @@ public CustomHeaderDecorator customHeaderDecorator() {
412412
return _customHeaderDecorator;
413413
}
414414

415-
public SplitHttpClient alternativeHTTPModule() { return _alternativeHTTPModule; }
415+
public CustomHttpModule alternativeHTTPModule() { return _alternativeHTTPModule; }
416416
public static final class Builder {
417417

418418
private String _endpoint = SDK_ENDPOINT;
@@ -470,7 +470,7 @@ public static final class Builder {
470470
private HashSet<String> _flagSetsFilter = new HashSet<>();
471471
private int _invalidSetsCount = 0;
472472
private CustomHeaderDecorator _customHeaderDecorator = null;
473-
private SplitHttpClient _alternativeHTTPModule = null;
473+
private CustomHttpModule _alternativeHTTPModule = null;
474474

475475
public Builder() {
476476
}
@@ -971,7 +971,7 @@ public Builder customHeaderDecorator(CustomHeaderDecorator customHeaderDecorator
971971
* @param alternativeHTTPModule
972972
* @return this builder
973973
*/
974-
public Builder alternativeHTTPModule(SplitHttpClient alternativeHTTPModule) {
974+
public Builder alternativeHTTPModule(CustomHttpModule alternativeHTTPModule) {
975975
_alternativeHTTPModule = alternativeHTTPModule;
976976
return this;
977977
}

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

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ public class SplitFactoryImpl implements SplitFactory {
165165
private RequestDecorator _requestDecorator;
166166

167167
// Constructor for standalone mode
168-
public SplitFactoryImpl(String apiToken, SplitClientConfig config) throws URISyntaxException {
168+
public SplitFactoryImpl(String apiToken, SplitClientConfig config) throws URISyntaxException, IOException {
169169
_userStorageWrapper = null;
170170
_operationMode = config.operationMode();
171171
_startTime = System.currentTimeMillis();
@@ -193,10 +193,7 @@ public SplitFactoryImpl(String apiToken, SplitClientConfig config) throws URISyn
193193
if (config.alternativeHTTPModule() == null) {
194194
_splitHttpClient = buildSplitHttpClient(apiToken, config, _sdkMetadata, _requestDecorator);
195195
} else {
196-
_splitHttpClient = config.alternativeHTTPModule();
197-
_splitHttpClient.setMetaData(_sdkMetadata);
198-
_splitHttpClient.setRequestDecorator(_requestDecorator);
199-
_splitHttpClient.setApiKey(apiToken);
196+
_splitHttpClient = config.alternativeHTTPModule().createClient(apiToken, _sdkMetadata, _requestDecorator);
200197
}
201198

202199
// Roots
@@ -284,14 +281,6 @@ public SplitFactoryImpl(String apiToken, SplitClientConfig config) throws URISyn
284281
}
285282
}
286283

287-
public RequestDecorator getRequestDecorator() {
288-
return _requestDecorator;
289-
}
290-
291-
public SDKMetadata getSDKMetaData() {
292-
return _sdkMetadata;
293-
}
294-
295284
// Constructor for consumer mode
296285
protected SplitFactoryImpl(String apiToken, SplitClientConfig config, CustomStorageWrapper customStorageWrapper)
297286
throws URISyntaxException {
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package io.split.service;
2+
3+
import io.split.client.RequestDecorator;
4+
import io.split.client.utils.SDKMetadata;
5+
import io.split.service.SplitHttpClient;
6+
7+
import java.io.IOException;
8+
9+
public interface CustomHttpModule {
10+
public SplitHttpClient createClient(String apiToken, SDKMetadata sdkMetadata, RequestDecorator requestDecorator) throws IOException;
11+
12+
13+
}

client/src/main/java/io/split/service/SplitHttpClient.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package io.split.service;
22

3-
import io.split.client.RequestDecorator;
4-
import io.split.client.utils.SDKMetadata;
53
import io.split.engine.common.FetchOptions;
64
import io.split.client.dtos.SplitHttpResponse;
75

@@ -34,10 +32,4 @@ public interface SplitHttpClient extends Closeable {
3432
public SplitHttpResponse post(URI uri,
3533
HttpEntity entity,
3634
Map<String, List<String>> additionalHeaders) throws IOException;
37-
38-
public void setMetaData(SDKMetadata metadata);
39-
40-
public void setRequestDecorator(RequestDecorator requestDecorator);
41-
42-
public void setApiKey(String apiKey);
4335
}

client/src/main/java/io/split/service/SplitHttpClientImpl.java

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -145,19 +145,4 @@ private void setBasicHeaders(HttpRequest request) {
145145
public void close() throws IOException {
146146
_client.close();
147147
}
148-
149-
@Override
150-
public void setMetaData(SDKMetadata metadata) {
151-
// only implemented for Kerberos client
152-
}
153-
154-
@Override
155-
public void setRequestDecorator(RequestDecorator requestDecorator) {
156-
// only implemented for Kerberos client
157-
}
158-
@Override
159-
public void setApiKey(String apiKey) {
160-
// only implemented for Kerberos client
161-
}
162-
163148
}
Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
package io.split.httpmodules.okhttp;
2+
3+
import io.split.client.RequestDecorator;
4+
import io.split.client.dtos.SplitHttpResponse;
5+
import io.split.client.utils.SDKMetadata;
6+
import io.split.engine.common.FetchOptions;
7+
import io.split.service.SplitHttpClient;
8+
9+
import okhttp3.*;
10+
import okhttp3.OkHttpClient.Builder;
11+
import okhttp3.Request.*;
12+
import okhttp3.logging.HttpLoggingInterceptor;
13+
import org.slf4j.Logger;
14+
import org.slf4j.LoggerFactory;
15+
16+
import split.org.apache.hc.client5.http.classic.methods.HttpGet;
17+
import split.org.apache.hc.core5.http.Header;
18+
import split.org.apache.hc.core5.http.HttpEntity;
19+
import split.org.apache.hc.core5.http.HttpRequest;
20+
import split.org.apache.hc.core5.http.io.entity.EntityUtils;
21+
import split.org.apache.hc.core5.http.message.BasicHeader;
22+
23+
import java.io.IOException;
24+
import java.net.HttpURLConnection;
25+
import java.net.Proxy;
26+
import java.net.URI;
27+
import java.util.ArrayList;
28+
import java.util.HashMap;
29+
import java.util.List;
30+
import java.util.Map;
31+
import java.util.concurrent.TimeUnit;
32+
33+
public class OkHttpClientImpl implements SplitHttpClient {
34+
public final OkHttpClient httpClient;
35+
private static final Logger _log = LoggerFactory.getLogger(OkHttpClientImpl.class);
36+
private static final String HEADER_CACHE_CONTROL_NAME = "Cache-Control";
37+
private static final String HEADER_CACHE_CONTROL_VALUE = "no-cache";
38+
private static final String HEADER_API_KEY = "Authorization";
39+
private static final String HEADER_CLIENT_KEY = "SplitSDKClientKey";
40+
private static final String HEADER_CLIENT_MACHINE_NAME = "SplitSDKMachineName";
41+
private static final String HEADER_CLIENT_MACHINE_IP = "SplitSDKMachineIP";
42+
private static final String HEADER_CLIENT_VERSION = "SplitSDKVersion";
43+
private RequestDecorator _requestDecorator;
44+
private String _apikey;
45+
private SDKMetadata _metadata;
46+
47+
public OkHttpClientImpl(String apiToken, SDKMetadata sdkMetadata, RequestDecorator requestDecorator,
48+
Proxy proxy, String proxyAuthKerberosPrincipalName, boolean debugEnabled,
49+
int readTimeout, int connectionTimeout) throws IOException {
50+
_apikey = apiToken;
51+
_metadata = sdkMetadata;
52+
_requestDecorator = requestDecorator;
53+
54+
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
55+
if (debugEnabled) {
56+
logging.setLevel(HttpLoggingInterceptor.Level.HEADERS);
57+
} else {
58+
logging.setLevel(HttpLoggingInterceptor.Level.NONE);
59+
}
60+
61+
Map<String, String> kerberosOptions = new HashMap<>();
62+
kerberosOptions.put("com.sun.security.auth.module.Krb5LoginModule", "required");
63+
kerberosOptions.put("refreshKrb5Config", "false");
64+
kerberosOptions.put("doNotPrompt", "false");
65+
kerberosOptions.put("useTicketCache", "true");
66+
67+
Authenticator proxyAuthenticator = getProxyAuthenticator(proxyAuthKerberosPrincipalName, kerberosOptions);
68+
69+
httpClient = new okhttp3.OkHttpClient.Builder()
70+
.proxy(proxy)
71+
.readTimeout(readTimeout, TimeUnit.MILLISECONDS)
72+
.connectTimeout(connectionTimeout, TimeUnit.MILLISECONDS)
73+
.addInterceptor(logging)
74+
.proxyAuthenticator(proxyAuthenticator)
75+
.build();
76+
}
77+
78+
public HTTPKerberosAuthInterceptor getProxyAuthenticator(String proxyKerberosPrincipalName,
79+
Map<String, String> kerberosOptions) throws IOException {
80+
return new HTTPKerberosAuthInterceptor(proxyKerberosPrincipalName, kerberosOptions);
81+
}
82+
83+
@Override
84+
public SplitHttpResponse get(URI uri, FetchOptions options, Map<String, List<String>> additionalHeaders) {
85+
try {
86+
okhttp3.Request.Builder requestBuilder = new okhttp3.Request.Builder();
87+
requestBuilder.url(uri.toString());
88+
setBasicHeaders(requestBuilder);
89+
setAdditionalAndDecoratedHeaders(requestBuilder, additionalHeaders);
90+
if (options.cacheControlHeadersEnabled()) {
91+
requestBuilder.addHeader(HEADER_CACHE_CONTROL_NAME, HEADER_CACHE_CONTROL_VALUE);
92+
}
93+
94+
Request request = requestBuilder.build();
95+
_log.debug(String.format("Request Headers: %s", request.headers()));
96+
97+
Response response = httpClient.newCall(request).execute();
98+
99+
int responseCode = response.code();
100+
101+
_log.debug(String.format("[GET] %s. Status code: %s",
102+
request.url().toString(),
103+
responseCode));
104+
105+
String statusMessage = "";
106+
if (responseCode < HttpURLConnection.HTTP_OK || responseCode >= HttpURLConnection.HTTP_MULT_CHOICE) {
107+
_log.warn(String.format("Response status was: %s. Reason: %s", responseCode,
108+
response.message()));
109+
statusMessage = response.message();
110+
}
111+
112+
String responseBody = response.body().string();
113+
response.close();
114+
115+
return new SplitHttpResponse(responseCode,
116+
statusMessage,
117+
responseBody,
118+
getResponseHeaders(response));
119+
} catch (Exception e) {
120+
throw new IllegalStateException(String.format("Problem in http get operation: %s", e), e);
121+
}
122+
}
123+
124+
@Override
125+
public SplitHttpResponse post(URI url, HttpEntity entity,
126+
Map<String, List<String>> additionalHeaders) {
127+
try {
128+
okhttp3.Request.Builder requestBuilder = getRequestBuilder();
129+
requestBuilder.url(url.toString());
130+
setBasicHeaders(requestBuilder);
131+
setAdditionalAndDecoratedHeaders(requestBuilder, additionalHeaders);
132+
requestBuilder.addHeader("Accept-Encoding", "gzip");
133+
requestBuilder.addHeader("Content-Type", "application/json");
134+
String post = EntityUtils.toString((HttpEntity) entity);
135+
RequestBody postBody = RequestBody.create(post.getBytes());
136+
requestBuilder.post(postBody);
137+
138+
Request request = getRequest(requestBuilder);
139+
_log.debug(String.format("Request Headers: %s", request.headers()));
140+
141+
Response response = httpClient.newCall(request).execute();
142+
143+
int responseCode = response.code();
144+
145+
_log.debug(String.format("[GET] %s. Status code: %s",
146+
request.url().toString(),
147+
responseCode));
148+
149+
String statusMessage = "";
150+
if (responseCode < HttpURLConnection.HTTP_OK || responseCode >= HttpURLConnection.HTTP_MULT_CHOICE) {
151+
_log.warn(String.format("Response status was: %s. Reason: %s", responseCode,
152+
response.message()));
153+
statusMessage = response.message();
154+
}
155+
response.close();
156+
157+
return new SplitHttpResponse(responseCode, statusMessage, "", getResponseHeaders(response));
158+
} catch (Exception e) {
159+
throw new IllegalStateException(String.format("Problem in http post operation: %s", e), e);
160+
}
161+
}
162+
163+
protected okhttp3.Request.Builder getRequestBuilder() {
164+
return new okhttp3.Request.Builder();
165+
}
166+
167+
protected Request getRequest(okhttp3.Request.Builder requestBuilder) {
168+
return requestBuilder.build();
169+
}
170+
protected void setBasicHeaders(okhttp3.Request.Builder requestBuilder) {
171+
requestBuilder.addHeader(HEADER_API_KEY, "Bearer " + _apikey);
172+
requestBuilder.addHeader(HEADER_CLIENT_VERSION, _metadata.getSdkVersion());
173+
requestBuilder.addHeader(HEADER_CLIENT_MACHINE_IP, _metadata.getMachineIp());
174+
requestBuilder.addHeader(HEADER_CLIENT_MACHINE_NAME, _metadata.getMachineName());
175+
requestBuilder.addHeader(HEADER_CLIENT_KEY, _apikey.length() > 4
176+
? _apikey.substring(_apikey.length() - 4)
177+
: _apikey);
178+
}
179+
180+
protected void setAdditionalAndDecoratedHeaders(okhttp3.Request.Builder requestBuilder, Map<String, List<String>> additionalHeaders) {
181+
if (additionalHeaders != null) {
182+
for (Map.Entry<String, List<String>> entry : additionalHeaders.entrySet()) {
183+
for (String value : entry.getValue()) {
184+
requestBuilder.addHeader(entry.getKey(), value);
185+
}
186+
}
187+
}
188+
HttpRequest request = new HttpGet("");
189+
_requestDecorator.decorateHeaders(request);
190+
for (Header header : request.getHeaders()) {
191+
requestBuilder.addHeader(header.getName(), header.getValue());
192+
}
193+
}
194+
195+
protected Header[] getResponseHeaders(Response response) {
196+
List<BasicHeader> responseHeaders = new ArrayList<>();
197+
Map<String, List<String>> map = response.headers().toMultimap();
198+
for (Map.Entry<String, List<String>> entry : map.entrySet()) {
199+
if (entry.getKey() != null) {
200+
BasicHeader responseHeader = new BasicHeader(entry.getKey(), entry.getValue());
201+
responseHeaders.add(responseHeader);
202+
}
203+
}
204+
return responseHeaders.toArray(new split.org.apache.hc.core5.http.Header[0]);
205+
}
206+
@Override
207+
public void close() throws IOException {
208+
httpClient.dispatcher().executorService().shutdown();
209+
}
210+
211+
}

0 commit comments

Comments
 (0)