Skip to content

Commit 1b4741d

Browse files
authored
Update Handling of Loading Proxies from the Environment (Azure#23151)
Update Handling of Loading Proxies from the Environment
1 parent 787aeb6 commit 1b4741d

File tree

4 files changed

+110
-75
lines changed

4 files changed

+110
-75
lines changed

sdk/core/azure-core-http-netty/src/test/java/com/azure/core/http/netty/NettyAsyncHttpClientBuilderTests.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public class NettyAsyncHttpClientBuilderTests {
5959
private static final String COOKIE_NAME = "test";
6060
private static final String COOKIE_VALUE = "success";
6161

62-
private static final String JAVA_PROXY_PREREQUISITE = "java.net.useSystemProxies";
62+
private static final String JAVA_SYSTEM_PROXY_PREREQUISITE = "java.net.useSystemProxies";
6363
private static final String JAVA_NON_PROXY_HOSTS = "http.nonProxyHosts";
6464

6565
private static final String JAVA_HTTP_PROXY_HOST = "http.proxyHost";
@@ -256,7 +256,6 @@ public void buildWithConfigurationProxy(boolean shouldHaveProxy, boolean usesAzu
256256

257257
private static Stream<Arguments> buildWithConfigurationProxySupplier() {
258258
Supplier<Configuration> baseJavaProxyConfigurationSupplier = () -> new Configuration()
259-
.put(JAVA_PROXY_PREREQUISITE, "true")
260259
.put(JAVA_HTTP_PROXY_HOST, "localhost")
261260
.put(JAVA_HTTP_PROXY_PORT, "12345");
262261

@@ -268,7 +267,8 @@ private static Stream<Arguments> buildWithConfigurationProxySupplier() {
268267
arguments.add(Arguments.of(true, false, baseJavaProxyConfigurationSupplier.get(), defaultUrl));
269268

270269
Configuration simpleEnvProxy = new Configuration()
271-
.put(Configuration.PROPERTY_HTTP_PROXY, "http://localhost:12345");
270+
.put(Configuration.PROPERTY_HTTP_PROXY, "http://localhost:12345")
271+
.put(JAVA_SYSTEM_PROXY_PREREQUISITE, "true");
272272
arguments.add(Arguments.of(true, false, simpleEnvProxy, defaultUrl));
273273

274274
/*
@@ -280,7 +280,8 @@ private static Stream<Arguments> buildWithConfigurationProxySupplier() {
280280
arguments.add(Arguments.of(true, true, javaProxyWithAuthentication, defaultUrl));
281281

282282
Configuration envProxyWithAuthentication = new Configuration()
283-
.put(Configuration.PROPERTY_HTTP_PROXY, "http://1:1@localhost:12345");
283+
.put(Configuration.PROPERTY_HTTP_PROXY, "http://1:1@localhost:12345")
284+
.put(JAVA_SYSTEM_PROXY_PREREQUISITE, "true");
284285
arguments.add(Arguments.of(true, true, envProxyWithAuthentication, defaultUrl));
285286

286287
/*
@@ -304,7 +305,8 @@ private static Stream<Arguments> buildWithConfigurationProxySupplier() {
304305
.put(JAVA_NON_PROXY_HOSTS, rawJavaNonProxyHosts);
305306
Supplier<Configuration> envNonProxyHostsSupplier = () -> new Configuration()
306307
.put(Configuration.PROPERTY_HTTP_PROXY, "http://localhost:12345")
307-
.put(Configuration.PROPERTY_NO_PROXY, rawEnvNonProxyHosts);
308+
.put(Configuration.PROPERTY_NO_PROXY, rawEnvNonProxyHosts)
309+
.put(JAVA_SYSTEM_PROXY_PREREQUISITE, "true");
308310

309311
List<Supplier<Configuration>> nonProxyHostsSuppliers = Arrays.asList(javaNonProxyHostsSupplier,
310312
envNonProxyHostsSupplier);
@@ -327,7 +329,8 @@ private static Stream<Arguments> buildWithConfigurationProxySupplier() {
327329
.put(JAVA_HTTP_PROXY_PASSWORD, "1");
328330
Supplier<Configuration> authenticatedEnvNonProxyHostsSupplier = () -> new Configuration()
329331
.put(Configuration.PROPERTY_HTTP_PROXY, "http://1:1@localhost:12345")
330-
.put(Configuration.PROPERTY_NO_PROXY, rawEnvNonProxyHosts);
332+
.put(Configuration.PROPERTY_NO_PROXY, rawEnvNonProxyHosts)
333+
.put(JAVA_SYSTEM_PROXY_PREREQUISITE, "true");
331334

332335
List<Supplier<Configuration>> authenticatedNonProxyHostsSuppliers = Arrays.asList(
333336
authenticatedJavaNonProxyHostsSupplier, authenticatedEnvNonProxyHostsSupplier);

sdk/core/azure-core-http-okhttp/src/test/java/com/azure/core/http/okhttp/OkHttpAsyncHttpClientBuilderTests.java

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public class OkHttpAsyncHttpClientBuilderTests {
5050
private static final String DEFAULT_PATH = "/default";
5151
private static final String DISPATCHER_PATH = "/dispatcher";
5252

53-
private static final String JAVA_PROXY_PREREQUISITE = "java.net.useSystemProxies";
53+
private static final String JAVA_SYSTEM_PROXY_PREREQUISITE = "java.net.useSystemProxies";
5454
private static final String JAVA_NON_PROXY_HOSTS = "http.nonProxyHosts";
5555

5656
private static final String JAVA_HTTP_PROXY_HOST = "http.proxyHost";
@@ -394,7 +394,6 @@ public void buildWithConfigurationProxy(boolean shouldHaveProxy, Configuration c
394394

395395
private static Stream<Arguments> buildWithConfigurationProxySupplier() {
396396
Supplier<Configuration> baseJavaProxyConfigurationSupplier = () -> new Configuration()
397-
.put(JAVA_PROXY_PREREQUISITE, "true")
398397
.put(JAVA_HTTP_PROXY_HOST, "localhost")
399398
.put(JAVA_HTTP_PROXY_PORT, "12345");
400399

@@ -406,7 +405,8 @@ private static Stream<Arguments> buildWithConfigurationProxySupplier() {
406405
arguments.add(Arguments.of(true, baseJavaProxyConfigurationSupplier.get(), defaultUrl));
407406

408407
Configuration simpleEnvProxy = new Configuration()
409-
.put(Configuration.PROPERTY_HTTP_PROXY, "http://localhost:12345");
408+
.put(Configuration.PROPERTY_HTTP_PROXY, "http://localhost:12345")
409+
.put(JAVA_SYSTEM_PROXY_PREREQUISITE, "true");
410410
arguments.add(Arguments.of(true, simpleEnvProxy, defaultUrl));
411411

412412
/*
@@ -418,7 +418,8 @@ private static Stream<Arguments> buildWithConfigurationProxySupplier() {
418418
arguments.add(Arguments.of(true, javaProxyWithAuthentication, defaultUrl));
419419

420420
Configuration envProxyWithAuthentication = new Configuration()
421-
.put(Configuration.PROPERTY_HTTP_PROXY, "http://1:1@localhost:12345");
421+
.put(Configuration.PROPERTY_HTTP_PROXY, "http://1:1@localhost:12345")
422+
.put(JAVA_SYSTEM_PROXY_PREREQUISITE, "true");
422423
arguments.add(Arguments.of(true, envProxyWithAuthentication, defaultUrl));
423424

424425
/*
@@ -442,7 +443,8 @@ private static Stream<Arguments> buildWithConfigurationProxySupplier() {
442443
.put(JAVA_NON_PROXY_HOSTS, rawJavaNonProxyHosts);
443444
Supplier<Configuration> envNonProxyHostsSupplier = () -> new Configuration()
444445
.put(Configuration.PROPERTY_HTTP_PROXY, "http://localhost:12345")
445-
.put(Configuration.PROPERTY_NO_PROXY, rawEnvNonProxyHosts);
446+
.put(Configuration.PROPERTY_NO_PROXY, rawEnvNonProxyHosts)
447+
.put(JAVA_SYSTEM_PROXY_PREREQUISITE, "true");
446448

447449
List<Supplier<Configuration>> nonProxyHostsSuppliers = Arrays.asList(javaNonProxyHostsSupplier,
448450
envNonProxyHostsSupplier);
@@ -465,7 +467,8 @@ private static Stream<Arguments> buildWithConfigurationProxySupplier() {
465467
.put(JAVA_HTTP_PROXY_PASSWORD, "1");
466468
Supplier<Configuration> authenticatedEnvNonProxyHostsSupplier = () -> new Configuration()
467469
.put(Configuration.PROPERTY_HTTP_PROXY, "http://1:1@localhost:12345")
468-
.put(Configuration.PROPERTY_NO_PROXY, rawEnvNonProxyHosts);
470+
.put(Configuration.PROPERTY_NO_PROXY, rawEnvNonProxyHosts)
471+
.put(JAVA_SYSTEM_PROXY_PREREQUISITE, "true");
469472

470473
List<Supplier<Configuration>> authenticatedNonProxyHostsSuppliers = Arrays.asList(
471474
authenticatedJavaNonProxyHostsSupplier, authenticatedEnvNonProxyHostsSupplier);
@@ -486,6 +489,18 @@ private static Stream<Arguments> buildWithConfigurationProxySupplier() {
486489
private static OkHttpClient okHttpClientWithProxyValidation(boolean shouldHaveProxy, Proxy.Type proxyType) {
487490
return new OkHttpClient.Builder()
488491
.eventListener(new TestEventListenerValidator(shouldHaveProxy, proxyType))
492+
// Use a custom Dispatcher and ExecutorService which overrides the uncaught exception handler.
493+
// This is done to prevent the tests using this from printing their error stack trace.
494+
// The reason this happens is the test throws an exception which goes uncaught in a thread, and this is an
495+
// expected exception, which results in the exception and its stack trace being logged, which is very
496+
// verbose.
497+
.dispatcher(new Dispatcher(Executors.newFixedThreadPool(2, r -> {
498+
Thread thread = new Thread(r);
499+
thread.setUncaughtExceptionHandler((t, e) -> {
500+
});
501+
502+
return thread;
503+
})))
489504
.build();
490505
}
491506

sdk/core/azure-core/src/main/java/com/azure/core/http/ProxyOptions.java

Lines changed: 35 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,7 @@
1414
import java.net.URL;
1515
import java.net.URLDecoder;
1616
import java.nio.charset.StandardCharsets;
17-
import java.util.Arrays;
18-
import java.util.List;
1917
import java.util.Objects;
20-
import java.util.function.BiFunction;
2118
import java.util.regex.Pattern;
2219

2320
/**
@@ -30,9 +27,9 @@ public class ProxyOptions {
3027
private static final String INVALID_AZURE_PROXY_URL = "Configuration {} is an invalid URL and is being ignored.";
3128

3229
/*
33-
* This indicates whether Java environment proxy configurations are allowed to be used.
30+
* This indicates whether system proxy configurations (HTTPS_PROXY, HTTP_PROXY) are allowed to be used.
3431
*/
35-
private static final String JAVA_PROXY_PREREQUISITE = "java.net.useSystemProxies";
32+
private static final String JAVA_SYSTEM_PROXY_PREREQUISITE = "java.net.useSystemProxies";
3633

3734
/*
3835
* Java environment variables related to proxies. The protocol is removed since these are the same for 'https' and
@@ -50,17 +47,6 @@ public class ProxyOptions {
5047
private static final String HTTP = "http";
5148
private static final int DEFAULT_HTTP_PORT = 80;
5249

53-
private static final List<BiFunction<Configuration, Boolean, ProxyOptions>> ENVIRONMENT_LOAD_ORDER = Arrays.asList(
54-
(configuration, resolveProxy)
55-
-> attemptToLoadAzureProxy(configuration, resolveProxy, Configuration.PROPERTY_HTTPS_PROXY),
56-
(configuration, resolveProxy)
57-
-> attemptToLoadAzureProxy(configuration, resolveProxy, Configuration.PROPERTY_HTTP_PROXY),
58-
(configuration, resolveProxy)
59-
-> attemptToLoadJavaProxy(configuration, resolveProxy, HTTPS),
60-
(configuration, resolveProxy)
61-
-> attemptToLoadJavaProxy(configuration, resolveProxy, HTTP)
62-
);
63-
6450
private final InetSocketAddress address;
6551
private final Type type;
6652
private String username;
@@ -93,7 +79,6 @@ public ProxyOptions setCredentials(String username, String password) {
9379

9480
/**
9581
* Sets the hosts which bypass the proxy.
96-
*
9782
* <p>
9883
* The expected format of the passed string is a {@code '|'} delimited list of hosts which should bypass the proxy.
9984
* Individual host strings may contain regex characters such as {@code '*'}.
@@ -188,7 +173,6 @@ public static ProxyOptions fromConfiguration(Configuration configuration) {
188173
*
189174
* Azure proxy configurations will be preferred over Java proxy configurations as they are more closely scoped to
190175
* the purpose of the SDK. Additionally, more secure protocols, HTTPS vs HTTP, will be preferred.
191-
*
192176
* <p>
193177
* {@code null} will be returned if no proxy was found in the environment.
194178
*
@@ -209,17 +193,44 @@ public static ProxyOptions fromConfiguration(Configuration configuration, boolea
209193
? Configuration.getGlobalConfiguration()
210194
: configuration;
211195

212-
for (BiFunction<Configuration, Boolean, ProxyOptions> loader : ENVIRONMENT_LOAD_ORDER) {
213-
ProxyOptions proxyOptions = loader.apply(proxyConfiguration, createUnresolved);
196+
return attemptToLoadProxy(proxyConfiguration, createUnresolved);
197+
}
198+
199+
private static ProxyOptions attemptToLoadProxy(Configuration configuration, boolean createUnresolved) {
200+
ProxyOptions proxyOptions;
201+
202+
// Only use system proxies when the prerequisite property is 'true'.
203+
if (Boolean.parseBoolean(configuration.get(JAVA_SYSTEM_PROXY_PREREQUISITE))) {
204+
proxyOptions = attemptToLoadSystemProxy(configuration, createUnresolved,
205+
Configuration.PROPERTY_HTTPS_PROXY);
206+
if (proxyOptions != null) {
207+
LOGGER.verbose("Using proxy created from HTTPS_PROXY environment variable.");
208+
return proxyOptions;
209+
}
210+
211+
proxyOptions = attemptToLoadSystemProxy(configuration, createUnresolved, Configuration.PROPERTY_HTTP_PROXY);
214212
if (proxyOptions != null) {
213+
LOGGER.verbose("Using proxy created from HTTP_PROXY environment variable.");
215214
return proxyOptions;
216215
}
217216
}
218217

218+
proxyOptions = attemptToLoadJavaProxy(configuration, createUnresolved, HTTPS);
219+
if (proxyOptions != null) {
220+
LOGGER.verbose("Using proxy created from JVM HTTPS system properties.");
221+
return proxyOptions;
222+
}
223+
224+
proxyOptions = attemptToLoadJavaProxy(configuration, createUnresolved, HTTP);
225+
if (proxyOptions != null) {
226+
LOGGER.verbose("Using proxy created from JVM HTTP system properties.");
227+
return proxyOptions;
228+
}
229+
219230
return null;
220231
}
221232

222-
private static ProxyOptions attemptToLoadAzureProxy(Configuration configuration, boolean createUnresolved,
233+
private static ProxyOptions attemptToLoadSystemProxy(Configuration configuration, boolean createUnresolved,
223234
String proxyProperty) {
224235
String proxyConfiguration = configuration.get(proxyProperty);
225236

@@ -236,7 +247,7 @@ private static ProxyOptions attemptToLoadAzureProxy(Configuration configuration,
236247
? InetSocketAddress.createUnresolved(proxyUrl.getHost(), port)
237248
: new InetSocketAddress(proxyUrl.getHost(), port);
238249

239-
ProxyOptions proxyOptions = new ProxyOptions(Type.HTTP, socketAddress);
250+
ProxyOptions proxyOptions = new ProxyOptions(ProxyOptions.Type.HTTP, socketAddress);
240251

241252
String nonProxyHostsString = configuration.get(Configuration.PROPERTY_NO_PROXY);
242253
if (!CoreUtils.isNullOrEmpty(nonProxyHostsString)) {
@@ -325,11 +336,6 @@ private static String sanitizeNoProxy(String noProxyString) {
325336

326337
private static ProxyOptions attemptToLoadJavaProxy(Configuration configuration, boolean createUnresolved,
327338
String type) {
328-
// Not allowed to use Java proxies
329-
if (!Boolean.parseBoolean(configuration.get(JAVA_PROXY_PREREQUISITE))) {
330-
return null;
331-
}
332-
333339
String host = configuration.get(type + "." + JAVA_PROXY_HOST);
334340

335341
// No proxy configuration setup.
@@ -348,11 +354,11 @@ private static ProxyOptions attemptToLoadJavaProxy(Configuration configuration,
348354
? InetSocketAddress.createUnresolved(host, port)
349355
: new InetSocketAddress(host, port);
350356

351-
ProxyOptions proxyOptions = new ProxyOptions(Type.HTTP, socketAddress);
357+
ProxyOptions proxyOptions = new ProxyOptions(ProxyOptions.Type.HTTP, socketAddress);
352358

353359
String nonProxyHostsString = configuration.get(JAVA_NON_PROXY_HOSTS);
354360
if (!CoreUtils.isNullOrEmpty(nonProxyHostsString)) {
355-
proxyOptions.nonProxyHosts = sanitizeJavaHttpNonProxyHosts(nonProxyHostsString);
361+
proxyOptions.setNonProxyHosts(nonProxyHostsString);
356362
}
357363

358364
String username = configuration.get(type + "." + JAVA_PROXY_USER);

0 commit comments

Comments
 (0)