16
16
import com .ibm .cloud .sdk .core .http .HttpConfigOptions .LoggingLevel ;
17
17
import com .ibm .cloud .sdk .core .http .gzip .GzipRequestInterceptor ;
18
18
import com .ibm .cloud .sdk .core .service .security .DelegatingSSLSocketFactory ;
19
+ import com .ibm .cloud .sdk .core .util .EnvironmentUtils ;
20
+
19
21
import okhttp3 .Authenticator ;
20
22
import okhttp3 .ConnectionSpec ;
21
23
import okhttp3 .Interceptor ;
@@ -179,6 +181,7 @@ private OkHttpClient configureHttpClient() {
179
181
final OkHttpClient .Builder builder = new OkHttpClient .Builder ();
180
182
181
183
addCookieJar (builder );
184
+ addRedirectInterceptor (builder );
182
185
183
186
builder .connectTimeout (60 , TimeUnit .SECONDS );
184
187
builder .writeTimeout (60 , TimeUnit .SECONDS );
@@ -197,11 +200,34 @@ private OkHttpClient configureHttpClient() {
197
200
*
198
201
* @param builder the builder
199
202
*/
200
- private void addCookieJar (final OkHttpClient .Builder builder ) {
203
+ private OkHttpClient . Builder addCookieJar (final OkHttpClient .Builder builder ) {
201
204
final CookieManager cookieManager = new CookieManager ();
202
205
cookieManager .setCookiePolicy (CookiePolicy .ACCEPT_ALL );
203
206
204
207
builder .cookieJar (new ServiceCookieJar (cookieManager ));
208
+ return builder ;
209
+ }
210
+
211
+ /**
212
+ * Adds the RedirectInterceptor to the client builder.
213
+ * @param builder
214
+ */
215
+ private OkHttpClient .Builder addRedirectInterceptor (final OkHttpClient .Builder builder ) {
216
+ String envvar = EnvironmentUtils .getenv ("IBMCLOUD_BYPASS_CUSTOM_REDIRECTS" );
217
+ if (!Boolean .valueOf (envvar )) {
218
+ // Disable the built-in "followRedirects" so that okhttp will ignore redirects.
219
+ builder .followRedirects (false ).followSslRedirects (false );
220
+
221
+ // Add our RedirectInterceptor to the client.
222
+ builder .addInterceptor (new RedirectInterceptor ());
223
+ LOG .log (Level .FINE , "Registered the redirect interceptor." );
224
+ } else {
225
+ LOG .log (Level .FINE , "Bypassed redirect interceptor via options." );
226
+
227
+ // Set the defaults for these two options.
228
+ builder .followRedirects (true ).followSslRedirects (true );
229
+ }
230
+ return builder ;
205
231
}
206
232
207
233
/**
@@ -337,30 +363,6 @@ public static void setupTLSProtocol(final OkHttpClient.Builder builder) {
337
363
}
338
364
}
339
365
340
- /**
341
- * Sets a new list of interceptors for the specified {@link OkHttpClient} instance by removing the specified
342
- * interceptor and returns a new instance with the interceptors configured as requested.
343
- *
344
- * @param client the {@link OkHttpClient} instance to remove the interceptors from
345
- * @param interceptorToRemove the class name of the interceptor to remove
346
- * @return the new {@link OkHttpClient} instance with the new list of interceptors
347
- */
348
- private OkHttpClient reconfigureClientInterceptors (OkHttpClient client , String interceptorToRemove ) {
349
- OkHttpClient .Builder builder = client .newBuilder ();
350
-
351
- if (!builder .interceptors ().isEmpty ()) {
352
- for (Iterator <Interceptor > iter = builder .interceptors ().iterator (); iter .hasNext (); ) {
353
- Interceptor element = iter .next ();
354
- if (interceptorToRemove .equals (element .getClass ().getSimpleName ())) {
355
- LOG .log (Level .FINE , "Removing interceptor " + element .getClass ().getName () + " from http client instance." );
356
- iter .remove ();
357
- }
358
- }
359
- }
360
-
361
- return builder .build ();
362
- }
363
-
364
366
/**
365
367
* Sets a new list of interceptors for the specified {@link OkHttpClient} instance by removing any interceptors
366
368
* that implement "interfaceToRemove".
@@ -370,7 +372,7 @@ private OkHttpClient reconfigureClientInterceptors(OkHttpClient client, String i
370
372
* @return the new {@link OkHttpClient} instance with the updated list of interceptors
371
373
*/
372
374
private OkHttpClient reconfigureClientInterceptors (OkHttpClient client ,
373
- Class <? extends Interceptor > interfaceToRemove ) {
375
+ Class <? extends Interceptor > interfaceToRemove ) {
374
376
OkHttpClient .Builder builder = client .newBuilder ();
375
377
376
378
if (!builder .interceptors ().isEmpty ()) {
@@ -395,6 +397,7 @@ private OkHttpClient reconfigureClientInterceptors(OkHttpClient client,
395
397
public OkHttpClient createHttpClient () {
396
398
Builder builder = okHttpClient .newBuilder ();
397
399
addCookieJar (builder );
400
+ addRedirectInterceptor (builder );
398
401
return builder .build ();
399
402
}
400
403
@@ -419,7 +422,10 @@ public OkHttpClient configureClient(HttpConfigOptions options) {
419
422
* @return a new {@link OkHttpClient} instance with the specified options applied
420
423
*/
421
424
public OkHttpClient configureClient (OkHttpClient client , HttpConfigOptions options ) {
425
+ Boolean customRedirects = null ;
422
426
if (options != null ) {
427
+ customRedirects = options .getCustomRedirects ();
428
+
423
429
if (options .shouldDisableSslVerification ()) {
424
430
client = disableSslVerification (client );
425
431
}
@@ -443,6 +449,7 @@ public OkHttpClient configureClient(OkHttpClient client, HttpConfigOptions optio
443
449
options .getAuthenticator ());
444
450
if (retryInterceptor != null ) {
445
451
client = client .newBuilder ().addInterceptor (retryInterceptor ).build ();
452
+ LOG .log (Level .FINE , "Registered the retry interceptor." );
446
453
} else {
447
454
LOG .log (Level .WARNING ,
448
455
"The retry interceptor factory returned a null IRetryInterceptor instance. Retries are disabled." );
@@ -453,14 +460,35 @@ public OkHttpClient configureClient(OkHttpClient client, HttpConfigOptions optio
453
460
// Configure the GZIP interceptor.
454
461
Boolean enableGzip = options .getGzipCompression ();
455
462
if (enableGzip != null ) {
456
- client = reconfigureClientInterceptors (client , " GzipRequestInterceptor" );
463
+ client = reconfigureClientInterceptors (client , GzipRequestInterceptor . class );
457
464
if (enableGzip .booleanValue ()) {
458
465
client = client .newBuilder ()
459
466
.addInterceptor (new GzipRequestInterceptor ())
460
467
.build ();
468
+ LOG .log (Level .FINE , "Registered the gzip interceptor." );
461
469
}
462
470
}
463
471
}
472
+
473
+ // Configure the redirect interceptor.
474
+ // We want "custom redirects" to be enabled by default (including a scenario
475
+ // where "options" is null), hence the need to handle this feature outside the "if" above.
476
+ // We want to register the interceptor if:
477
+ // 1. options == null
478
+ // 2. options != null and "custom redirects" is explicitly set to Boolean.TRUE
479
+ //
480
+ // We also want to allow "custom redirects" to be bypassed by setting an environment variable.
481
+ // This may be only temporary until we are comfortable with this new function, but I'm
482
+ // adding support for this environment variable as a quick fix in case there are "unforeseen
483
+ // consequences" after this feature hits the street.
484
+ // Example:
485
+ // export IBMCLOUD_BYPASS_CUSTOM_REDIRECTS=true
486
+ // Setting this environment variable will revert back to using the okhttp builtin support for redirects.
487
+ client = reconfigureClientInterceptors (client , RedirectInterceptor .class );
488
+ if (customRedirects == null || customRedirects .booleanValue ()) {
489
+ client = addRedirectInterceptor (client .newBuilder ()).build ();
490
+ }
491
+
464
492
return client ;
465
493
}
466
494
}
0 commit comments