22
33import com .google .common .io .Files ;
44import com .google .gson .Gson ;
5+ import okhttp3 .Authenticator ;
56import okhttp3 .Cache ;
67import okhttp3 .ConnectionPool ;
8+ import okhttp3 .Credentials ;
79import okhttp3 .OkHttpClient ;
810import okhttp3 .Request ;
11+ import okhttp3 .Response ;
12+ import okhttp3 .Route ;
913import org .slf4j .Logger ;
1014import org .slf4j .LoggerFactory ;
1115
1216import java .io .File ;
17+ import java .io .IOException ;
1318import java .net .InetSocketAddress ;
1419import java .net .Proxy ;
1520import java .net .URI ;
@@ -46,6 +51,7 @@ public final class LDConfig {
4651 final int socketTimeoutMillis ;
4752 final int flushInterval ;
4853 final Proxy proxy ;
54+ final Authenticator proxyAuthenticator ;
4955 final OkHttpClient httpClient ;
5056 final boolean stream ;
5157 final FeatureStore featureStore ;
@@ -64,6 +70,7 @@ protected LDConfig(Builder builder) {
6470 this .socketTimeoutMillis = builder .socketTimeoutMillis ;
6571 this .flushInterval = builder .flushIntervalSeconds ;
6672 this .proxy = builder .proxy ();
73+ this .proxyAuthenticator = builder .proxyAuthenticator ();
6774 this .streamURI = builder .streamURI ;
6875 this .stream = builder .stream ;
6976 this .featureStore = builder .featureStore ;
@@ -91,12 +98,24 @@ protected LDConfig(Builder builder) {
9198
9299 if (proxy != null ) {
93100 httpClientBuilder .proxy (proxy );
101+ if (proxyAuthenticator != null ) {
102+ httpClientBuilder .proxyAuthenticator (proxyAuthenticator );
103+ logger .info ("Using proxy: " + proxy + " with authentication." );
104+ } else {
105+ logger .info ("Using proxy: " + proxy + " without authentication." );
106+ }
94107 }
95108
96109 httpClient = httpClientBuilder
97110 .build ();
98111 }
99112
113+ Request .Builder getRequestBuilder (String sdkKey ) {
114+ return new Request .Builder ()
115+ .addHeader ("Authorization" , sdkKey )
116+ .addHeader ("User-Agent" , "JavaClient/" + LDClient .CLIENT_VERSION );
117+ }
118+
100119 /**
101120 * A <a href="http://en.wikipedia.org/wiki/Builder_pattern">builder</a> that helps construct {@link com.launchdarkly.client.LDConfig} objects. Builder
102121 * calls can be chained, enabling the following pattern:
@@ -118,6 +137,8 @@ public static class Builder {
118137 private int flushIntervalSeconds = DEFAULT_FLUSH_INTERVAL_SECONDS ;
119138 private String proxyHost = "localhost" ;
120139 private int proxyPort = -1 ;
140+ private String proxyUsername = null ;
141+ private String proxyPassword = null ;
121142 private boolean stream = true ;
122143 private boolean useLdd = false ;
123144 private boolean offline = false ;
@@ -289,6 +310,30 @@ public Builder proxyPort(int port) {
289310 return this ;
290311 }
291312
313+ /**
314+ * Sets the username for the optional HTTP proxy. Only used when {@link LDConfig.Builder#proxyPassword(String)}
315+ * is also called.
316+ *
317+ * @param username
318+ * @return the builder
319+ */
320+ public Builder proxyUsername (String username ) {
321+ this .proxyUsername = username ;
322+ return this ;
323+ }
324+
325+ /**
326+ * Sets the password for the optional HTTP proxy. Only used when {@link LDConfig.Builder#proxyUsername(String)}
327+ * is also called.
328+ *
329+ * @param password
330+ * @return the builder
331+ */
332+ public Builder proxyPassword (String password ) {
333+ this .proxyPassword = password ;
334+ return this ;
335+ }
336+
292337 /**
293338 * Deprecated. Only HTTP proxies are currently supported.
294339 *
@@ -352,7 +397,7 @@ public Builder startWaitMillis(long startWaitMillis) {
352397 * Enable event sampling. When set to the default of zero, sampling is disabled and all events
353398 * are sent back to LaunchDarkly. When set to greater than zero, there is a 1 in
354399 * <code>samplingInterval</code> chance events will be will be sent.
355- *
400+ * <p>
356401 * <p>Example: if you want 5% sampling rate, set <code>samplingInterval</code> to 20.
357402 *
358403 * @param samplingInterval the sampling interval.
@@ -386,6 +431,24 @@ Proxy proxy() {
386431 }
387432 }
388433
434+ Authenticator proxyAuthenticator () {
435+ if (this .proxyUsername != null && this .proxyPassword != null ) {
436+ final String credential = Credentials .basic (proxyUsername , proxyPassword );
437+ return new Authenticator () {
438+ public Request authenticate (Route route , Response response ) throws IOException {
439+ if (response .request ().header ("Proxy-Authorization" ) != null ) {
440+ return null ; // Give up, we've already failed to authenticate with the proxy.
441+ } else {
442+ return response .request ().newBuilder ()
443+ .header ("Proxy-Authorization" , credential )
444+ .build ();
445+ }
446+ }
447+ };
448+ }
449+ return null ;
450+ }
451+
389452 /**
390453 * Build the configured {@link com.launchdarkly.client.LDConfig} object
391454 *
@@ -394,12 +457,5 @@ Proxy proxy() {
394457 public LDConfig build () {
395458 return new LDConfig (this );
396459 }
397-
398- }
399-
400- Request .Builder getRequestBuilder (String sdkKey ) {
401- return new Request .Builder ()
402- .addHeader ("Authorization" , sdkKey )
403- .addHeader ("User-Agent" , "JavaClient/" + LDClient .CLIENT_VERSION );
404460 }
405461}
0 commit comments