2020import io .split .engine .segments .RefreshableSegmentFetcher ;
2121import io .split .engine .segments .SegmentChangeFetcher ;
2222import io .split .integrations .IntegrationsConfig ;
23- import org .apache .http .auth .AuthScope ;
24- import org .apache .http .auth .Credentials ;
25- import org .apache .http .auth .UsernamePasswordCredentials ;
26- import org .apache .http .client . CredentialsProvider ;
27- import org .apache .http . client . config . CookieSpecs ;
28- import org .apache .http .client . config . RequestConfig ;
29- import org .apache .http .config . Registry ;
30- import org .apache .http .config . RegistryBuilder ;
31- import org .apache .http .conn . socket . ConnectionSocketFactory ;
32- import org .apache .http .conn . socket . PlainConnectionSocketFactory ;
33- import org .apache .http .conn . ssl . SSLConnectionSocketFactory ;
34- import org .apache .http .conn . ssl . SSLContexts ;
35- import org .apache .http . impl . client . BasicCredentialsProvider ;
36- import org .apache .http . impl . client . CloseableHttpClient ;
37- import org .apache .http . impl . client . HttpClientBuilder ;
38- import org .apache .http . impl . client . HttpClients ;
39- import org .apache .http . impl . conn . DefaultProxyRoutePlanner ;
40- import org .apache .http . impl . conn . PoolingHttpClientConnectionManager ;
23+ import org .apache .hc . client5 . http .auth .AuthScope ;
24+ import org .apache .hc . client5 . http .auth .Credentials ;
25+ import org .apache .hc . client5 . http .auth .UsernamePasswordCredentials ;
26+ import org .apache .hc . client5 . http .config . RequestConfig ;
27+ import org .apache .hc . client5 . http . cookie . StandardCookieSpec ;
28+ import org .apache .hc . client5 . http .impl . auth . BasicCredentialsProvider ;
29+ import org .apache .hc . client5 . http .impl . classic . CloseableHttpClient ;
30+ import org .apache .hc . client5 . http .impl . classic . HttpClientBuilder ;
31+ import org .apache .hc . client5 . http .impl . classic . HttpClients ;
32+ import org .apache .hc . client5 . http .impl . io . PoolingHttpClientConnectionManager ;
33+ import org .apache .hc . client5 . http .impl . io . PoolingHttpClientConnectionManagerBuilder ;
34+ import org .apache .hc . client5 . http .impl . routing . DefaultProxyRoutePlanner ;
35+ import org .apache .hc . client5 . http . ssl . SSLConnectionSocketFactory ;
36+ import org .apache .hc . client5 . http . ssl . SSLConnectionSocketFactoryBuilder ;
37+ import org .apache .hc . core5 . http . io . SocketConfig ;
38+ import org .apache .hc . core5 . http . ssl . TLS ;
39+ import org .apache .hc . core5 . ssl . SSLContexts ;
40+ import org .apache .hc . core5 . util . Timeout ;
4141import org .slf4j .Logger ;
4242import org .slf4j .LoggerFactory ;
4343
44- import javax .net .ssl .SSLContext ;
4544import java .io .IOException ;
4645import java .net .URI ;
4746import java .net .URISyntaxException ;
48- import java .security .KeyManagementException ;
49- import java .security .NoSuchAlgorithmException ;
5047import java .util .ArrayList ;
5148import java .util .List ;
5249import java .util .Random ;
5552
5653public class SplitFactoryImpl implements SplitFactory {
5754 private static final Logger _log = LoggerFactory .getLogger (SplitFactory .class );
55+ private final static long SSE_CONNECT_TIMEOUT = 30000 ;
56+ private final static long SSE_SOCKET_TIMEOUT = 70000 ;
5857
5958 private static final Multiset <String > USED_API_TOKENS = ConcurrentHashMultiset .create ();
6059 private static Random RANDOM = new Random ();
@@ -65,46 +64,92 @@ public class SplitFactoryImpl implements SplitFactory {
6564 private final String _apiToken ;
6665 private boolean isTerminated = false ;
6766
68- public SplitFactoryImpl (String apiToken , SplitClientConfig config ) throws URISyntaxException {
69- _apiToken = apiToken ;
70- SSLContext sslContext = null ;
71- try {
72- sslContext = SSLContexts .custom ()
73- .useTLS ()
74- .build ();
75- } catch (NoSuchAlgorithmException | KeyManagementException e ) {
76- throw new RuntimeException ("Unable to create support for secure connection." );
77- }
67+ private static CloseableHttpClient buildHttpClient (String apiToken , SplitClientConfig config ) {
7868
79- SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory (
80- sslContext ,
81- new String []{"TLSv1.1" , "TLSv1.2" },
82- null ,
83- SSLConnectionSocketFactory .getDefaultHostnameVerifier ());
84-
85- Registry <ConnectionSocketFactory > registry = RegistryBuilder .<ConnectionSocketFactory >create ()
86- .register ("http" , PlainConnectionSocketFactory .getSocketFactory ())
87- .register ("https" , sslsf )
69+ SSLConnectionSocketFactory sslSocketFactory = SSLConnectionSocketFactoryBuilder .create ()
70+ .setSslContext (SSLContexts .createSystemDefault ())
71+ .setTlsVersions (TLS .V_1_1 , TLS .V_1_2 )
8872 .build ();
8973
9074 RequestConfig requestConfig = RequestConfig .custom ()
91- .setConnectTimeout (config .connectionTimeout ())
92- .setSocketTimeout (config .readTimeout ())
93- .setCookieSpec (CookieSpecs .STANDARD )
75+ .setConnectTimeout (Timeout .ofMilliseconds (config .connectionTimeout ()))
76+ .setCookieSpec (StandardCookieSpec .STRICT )
9477 .build ();
9578
96- PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager (registry );
79+ PoolingHttpClientConnectionManager cm = PoolingHttpClientConnectionManagerBuilder .create ()
80+ .setSSLSocketFactory (sslSocketFactory )
81+ .setDefaultSocketConfig (SocketConfig .custom ()
82+ .setSoTimeout (Timeout .ofMilliseconds (config .readTimeout ()))
83+ .build ())
84+ .build ();
9785 cm .setMaxTotal (20 );
9886 cm .setDefaultMaxPerRoute (20 );
9987
10088 HttpClientBuilder httpClientbuilder = HttpClients .custom ()
10189 .setConnectionManager (cm )
10290 .setDefaultRequestConfig (requestConfig )
103- .setSSLSocketFactory (sslsf )
104- .addInterceptorLast (AddSplitHeadersFilter .instance (apiToken , config .ipAddressEnabled ()))
105- .addInterceptorLast (new GzipEncoderRequestInterceptor ())
106- .addInterceptorLast (new GzipDecoderResponseInterceptor ());
91+ .addRequestInterceptorLast (AddSplitHeadersFilter .instance (apiToken , config .ipAddressEnabled ()))
92+ .addRequestInterceptorLast (new GzipEncoderRequestInterceptor ())
93+ .addResponseInterceptorLast ((new GzipDecoderResponseInterceptor ()));
94+
95+ // Set up proxy is it exists
96+ if (config .proxy () != null ) {
97+ httpClientbuilder = setupProxy (httpClientbuilder , config );
98+ }
99+
100+ return httpClientbuilder .build ();
101+ }
102+
103+ private static CloseableHttpClient buildSSEdHttpClient (SplitClientConfig config ) {
104+ RequestConfig requestConfig = RequestConfig .custom ()
105+ .setConnectTimeout (Timeout .ofMilliseconds (SSE_CONNECT_TIMEOUT ))
106+ .build ();
107+
108+ SSLConnectionSocketFactory sslSocketFactory = SSLConnectionSocketFactoryBuilder .create ()
109+ .setSslContext (SSLContexts .createSystemDefault ())
110+ .setTlsVersions (TLS .V_1_1 , TLS .V_1_2 )
111+ .build ();
112+
113+ PoolingHttpClientConnectionManager cm = PoolingHttpClientConnectionManagerBuilder .create ()
114+ .setSSLSocketFactory (sslSocketFactory )
115+ .setDefaultSocketConfig (SocketConfig .custom ()
116+ .setSoTimeout (Timeout .ofMilliseconds (SSE_SOCKET_TIMEOUT ))
117+ .build ())
118+ .build ();
119+ cm .setMaxTotal (1 );
120+ cm .setDefaultMaxPerRoute (1 );
121+
122+ HttpClientBuilder httpClientbuilder = HttpClients .custom ()
123+ .setConnectionManager (cm )
124+ .setDefaultRequestConfig (requestConfig );
125+
126+ // Set up proxy is it exists
127+ if (config .proxy () != null ) {
128+ httpClientbuilder = setupProxy (httpClientbuilder , config );
129+ }
107130
131+ return httpClientbuilder .build ();
132+ }
133+
134+ private static HttpClientBuilder setupProxy (HttpClientBuilder httpClientbuilder , SplitClientConfig config ) {
135+ _log .info ("Initializing Split SDK with proxy settings" );
136+ DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner (config .proxy ());
137+ httpClientbuilder .setRoutePlanner (routePlanner );
138+
139+ if (config .proxyUsername () != null && config .proxyPassword () != null ) {
140+ _log .debug ("Proxy setup using credentials" );
141+ BasicCredentialsProvider credsProvider = new BasicCredentialsProvider ();
142+ AuthScope siteScope = new AuthScope (config .proxy ().getHostName (), config .proxy ().getPort ());
143+ Credentials siteCreds = new UsernamePasswordCredentials (config .proxyUsername (), config .proxyPassword ().toCharArray ());
144+ credsProvider .setCredentials (siteScope , siteCreds );
145+ httpClientbuilder .setDefaultCredentialsProvider (credsProvider );
146+ }
147+
148+ return httpClientbuilder ;
149+ }
150+
151+ public SplitFactoryImpl (String apiToken , SplitClientConfig config ) throws URISyntaxException {
152+ _apiToken = apiToken ;
108153
109154 if (USED_API_TOKENS .contains (apiToken )) {
110155 String message = String .format ("factory instantiation: You already have %s with this API Key. " +
@@ -126,24 +171,9 @@ public SplitFactoryImpl(String apiToken, SplitClientConfig config) throws URISyn
126171 "if no ready config has been set when building factory" );
127172
128173 }
129- // Set up proxy is it exists
130- if (config .proxy () != null ) {
131- _log .info ("Initializing Split SDK with proxy settings" );
132- DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner (config .proxy ());
133- httpClientbuilder .setRoutePlanner (routePlanner );
134-
135- if (config .proxyUsername () != null && config .proxyPassword () != null ) {
136- _log .debug ("Proxy setup using credentials" );
137- CredentialsProvider credsProvider = new BasicCredentialsProvider ();
138- AuthScope siteScope = new AuthScope (config .proxy ().getHostName (), config .proxy ().getPort ());
139- Credentials siteCreds = new UsernamePasswordCredentials (config .proxyUsername (), config .proxyPassword ());
140- credsProvider .setCredentials (siteScope , siteCreds );
141-
142- httpClientbuilder .setDefaultCredentialsProvider (credsProvider );
143- }
144- }
145174
146- final CloseableHttpClient httpclient = httpClientbuilder .build ();
175+
176+ final CloseableHttpClient httpclient = buildHttpClient (apiToken , config );
147177
148178 URI rootTarget = URI .create (config .endpoint ());
149179 URI eventsRootTarget = URI .create (config .eventsEndpoint ());
@@ -191,7 +221,7 @@ public SplitFactoryImpl(String apiToken, SplitClientConfig config) throws URISyn
191221 final EventClient eventClient = EventClientImpl .create (httpclient , eventsRootTarget , config .eventsQueueSize (), config .eventFlushIntervalInMillis (), config .waitBeforeShutdown ());
192222
193223 // SyncManager
194- final SyncManager syncManager = SyncManagerImp .build (config .streamingEnabled (), splitFetcherProvider , segmentFetcher , config .authServiceURL (), httpclient , config .streamingServiceURL (), config .authRetryBackoffBase ());
224+ final SyncManager syncManager = SyncManagerImp .build (config .streamingEnabled (), splitFetcherProvider , segmentFetcher , config .authServiceURL (), httpclient , config .streamingServiceURL (), config .authRetryBackoffBase (), buildSSEdHttpClient ( config ) );
195225 syncManager .start ();
196226
197227 destroyer = new Runnable () {
0 commit comments