Skip to content

Commit 3f34e5c

Browse files
author
Erin Yang
committed
Use system property proxy settings for netty and crt http client
1 parent a1d0ce3 commit 3f34e5c

File tree

4 files changed

+221
-23
lines changed

4 files changed

+221
-23
lines changed

http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/ProxyConfiguration.java

Lines changed: 57 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import java.util.Objects;
1919
import software.amazon.awssdk.annotations.SdkPreviewApi;
2020
import software.amazon.awssdk.annotations.SdkPublicApi;
21+
import software.amazon.awssdk.utils.ProxySystemSetting;
2122
import software.amazon.awssdk.utils.builder.CopyableBuilder;
2223
import software.amazon.awssdk.utils.builder.ToCopyableBuilder;
2324

@@ -39,11 +40,13 @@ public final class ProxyConfiguration implements ToCopyableBuilder<ProxyConfigur
3940

4041
private final String username;
4142
private final String password;
43+
private final Boolean useSystemPropertyValues;
4244

4345
private ProxyConfiguration(BuilderImpl builder) {
46+
this.useSystemPropertyValues = builder.useSystemPropertyValues;
4447
this.scheme = builder.scheme;
45-
this.host = builder.host;
46-
this.port = builder.port;
48+
this.host = resolveHost(builder.host);
49+
this.port = resolvePort(builder.port);
4750
this.username = builder.username;
4851
this.password = builder.password;
4952
}
@@ -56,31 +59,35 @@ public String scheme() {
5659
}
5760

5861
/**
59-
* @return The proxy host.
62+
* @return The proxy host from the configuration if set, or from the "http.proxyHost" system property if
63+
* {@link Builder#useSystemPropertyValues(Boolean)} is set to true
6064
*/
6165
public String host() {
6266
return host;
6367
}
6468

6569
/**
66-
* @return The proxy port.
70+
* @return The proxy port from the configuration if set, or from the "http.proxyPort" system property if
71+
* {@link Builder#useSystemPropertyValues(Boolean)} is set to true
6772
*/
6873
public int port() {
6974
return port;
7075
}
7176

7277
/**
73-
* @return Basic authentication username
74-
*/
78+
* @return The proxy username from the configuration if set, or from the "http.proxyUser" system property if
79+
* {@link Builder#useSystemPropertyValues(Boolean)} is set to true
80+
* */
7581
public String username() {
76-
return username;
82+
return resolveValue(username, ProxySystemSetting.PROXY_USERNAME);
7783
}
7884

7985
/**
80-
* @return Basic authentication password
81-
*/
86+
* @return The proxy password from the configuration if set, or from the "http.proxyPassword" system property if
87+
* {@link Builder#useSystemPropertyValues(Boolean)} is set to true
88+
* */
8289
public String password() {
83-
return password;
90+
return resolveValue(password, ProxySystemSetting.PROXY_PASSWORD);
8491
}
8592

8693
@Override
@@ -182,6 +189,34 @@ public interface Builder extends CopyableBuilder<Builder, ProxyConfiguration> {
182189
* @return This object for method chaining.
183190
*/
184191
Builder password(String password);
192+
193+
/**
194+
* The option whether to use system property values from {@link ProxySystemSetting} if any of the config options
195+
* are missing. The value is set to "true" by default which means SDK will automatically use system property values if
196+
* options are not provided during building the {@link ProxyConfiguration} object. To disable this behaviour, set this
197+
* value to false.
198+
*
199+
* @param useSystemPropertyValues The option whether to use system proerpty values
200+
* @return This object for method chaining.
201+
*/
202+
Builder useSystemPropertyValues(Boolean useSystemPropertyValues);
203+
}
204+
205+
private String resolveHost(String host) {
206+
return resolveValue(host, ProxySystemSetting.PROXY_HOST);
207+
}
208+
209+
private int resolvePort(int port) {
210+
return useSystemPropertyValues ? ProxySystemSetting.PROXY_PORT.getStringValue().map(Integer::parseInt).orElse(0)
211+
: port;
212+
}
213+
214+
/**
215+
* Uses the configuration options, system setting property and returns the final value of the given member.
216+
*/
217+
private String resolveValue(String value, ProxySystemSetting systemSetting) {
218+
return value == null && useSystemPropertyValues ? systemSetting.getStringValue().orElse(null)
219+
: value;
185220
}
186221

187222
private static final class BuilderImpl implements Builder {
@@ -190,11 +225,13 @@ private static final class BuilderImpl implements Builder {
190225
private int port;
191226
private String username;
192227
private String password;
228+
private Boolean useSystemPropertyValues = Boolean.TRUE;
193229

194230
private BuilderImpl() {
195231
}
196232

197233
private BuilderImpl(ProxyConfiguration proxyConfiguration) {
234+
this.useSystemPropertyValues = proxyConfiguration.useSystemPropertyValues;
198235
this.scheme = proxyConfiguration.scheme;
199236
this.host = proxyConfiguration.host;
200237
this.port = proxyConfiguration.port;
@@ -232,6 +269,16 @@ public Builder password(String password) {
232269
return this;
233270
}
234271

272+
@Override
273+
public Builder useSystemPropertyValues(Boolean useSystemPropertyValues) {
274+
this.useSystemPropertyValues = useSystemPropertyValues;
275+
return this;
276+
}
277+
278+
public void setUseSystemPropertyValues(Boolean useSystemPropertyValues) {
279+
useSystemPropertyValues(useSystemPropertyValues);
280+
}
281+
235282
@Override
236283
public ProxyConfiguration build() {
237284
return new ProxyConfiguration(this);

http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/ProxyConfigurationTest.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,45 @@
2727
*/
2828
public class ProxyConfigurationTest {
2929
private static final Random RNG = new Random();
30+
private static final String TEST_HOST = "foo.com";
31+
private static final int TEST_PORT = 7777;
32+
private static final String TEST_USER = "testuser";
33+
private static final String TEST_PASSWORD = "123";
3034

3135
@Test
3236
public void build_setsAllProperties() {
3337
verifyAllPropertiesSet(allPropertiesSetConfig());
3438
}
3539

40+
@Test
41+
public void build_systemPropertyEnabled() {
42+
setSystemProperty();
43+
ProxyConfiguration config = ProxyConfiguration.builder().useSystemPropertyValues(true).build();
44+
45+
assertThat(config.host()).isEqualTo(TEST_HOST);
46+
assertThat(config.port()).isEqualTo(TEST_PORT);
47+
assertThat(config.username()).isEqualTo(TEST_USER);
48+
assertThat(config.password()).isEqualTo(TEST_PASSWORD);
49+
assertThat(config.scheme()).isNull();
50+
}
51+
52+
@Test
53+
public void build_systemPropertyDisabled() {
54+
setSystemProperty();
55+
ProxyConfiguration config = ProxyConfiguration.builder()
56+
.host("localhost")
57+
.port(8888)
58+
.username("username")
59+
.password("password")
60+
.useSystemPropertyValues(false).build();
61+
62+
assertThat(config.host()).isEqualTo("localhost");
63+
assertThat(config.port()).isEqualTo(8888);
64+
assertThat(config.username()).isEqualTo("username");
65+
assertThat(config.password()).isEqualTo("password");
66+
assertThat(config.scheme()).isNull();
67+
}
68+
3669
@Test
3770
public void toBuilder_roundTrip_producesExactCopy() {
3871
ProxyConfiguration original = allPropertiesSetConfig();
@@ -76,6 +109,8 @@ private void setRandomValue(Object o, Method setter) throws InvocationTargetExce
76109
setter.invoke(o, randomString());
77110
} else if (int.class.equals(paramClass)) {
78111
setter.invoke(o, RNG.nextInt());
112+
} else if (Boolean.class.equals(paramClass)) {
113+
setter.invoke(o, Boolean.FALSE);
79114
} else {
80115
throw new RuntimeException("Don't know how create random value for type " + paramClass);
81116
}
@@ -108,4 +143,11 @@ private String randomString() {
108143

109144
return sb.toString();
110145
}
146+
147+
private void setSystemProperty() {
148+
System.setProperty("http.proxyHost", TEST_HOST);
149+
System.setProperty("http.proxyPort", Integer.toString(TEST_PORT));
150+
System.setProperty("http.proxyUser", TEST_USER);
151+
System.setProperty("http.proxyPassword", TEST_PASSWORD);
152+
}
111153
}

http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/ProxyConfiguration.java

Lines changed: 79 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,14 @@
1515

1616
package software.amazon.awssdk.http.nio.netty;
1717

18+
import java.util.Arrays;
1819
import java.util.Collections;
1920
import java.util.HashSet;
2021
import java.util.Set;
22+
import java.util.stream.Collectors;
2123
import software.amazon.awssdk.annotations.SdkPublicApi;
24+
import software.amazon.awssdk.utils.ProxySystemSetting;
25+
import software.amazon.awssdk.utils.StringUtils;
2226
import software.amazon.awssdk.utils.builder.CopyableBuilder;
2327
import software.amazon.awssdk.utils.builder.ToCopyableBuilder;
2428

@@ -30,6 +34,7 @@
3034
*/
3135
@SdkPublicApi
3236
public final class ProxyConfiguration implements ToCopyableBuilder<ProxyConfiguration.Builder, ProxyConfiguration> {
37+
private final Boolean useSystemPropertyValues;
3338
private final String scheme;
3439
private final String host;
3540
private final int port;
@@ -38,12 +43,13 @@ public final class ProxyConfiguration implements ToCopyableBuilder<ProxyConfigur
3843
private final Set<String> nonProxyHosts;
3944

4045
private ProxyConfiguration(BuilderImpl builder) {
46+
this.useSystemPropertyValues = builder.useSystemPropertyValues;
4147
this.scheme = builder.scheme;
42-
this.host = builder.host;
43-
this.port = builder.port;
48+
this.host = resolveHost(builder.host);
49+
this.port = resolvePort(builder.port);
4450
this.username = builder.username;
4551
this.password = builder.password;
46-
this.nonProxyHosts = Collections.unmodifiableSet(builder.nonProxyHosts);
52+
this.nonProxyHosts = builder.nonProxyHosts;
4753
}
4854

4955
public static Builder builder() {
@@ -58,38 +64,45 @@ public String scheme() {
5864
}
5965

6066
/**
61-
* @return The proxy host.
67+
* @return The proxy host from the configuration if set, or from the "http.proxyHost" system property if
68+
* {@link Builder#useSystemPropertyValues(Boolean)} is set to true
6269
*/
6370
public String host() {
6471
return host;
6572
}
6673

6774
/**
68-
* @return The proxy port.
75+
* @return The proxy port from the configuration if set, or from the "http.proxyPort" system property if
76+
* {@link Builder#useSystemPropertyValues(Boolean)} is set to true
6977
*/
7078
public int port() {
7179
return port;
7280
}
7381

7482
/**
75-
* @return The proxy username.
76-
*/
83+
* @return The proxy username from the configuration if set, or from the "http.proxyUser" system property if
84+
* {@link Builder#useSystemPropertyValues(Boolean)} is set to true
85+
* */
7786
public String username() {
78-
return username;
87+
return resolveValue(username, ProxySystemSetting.PROXY_USERNAME);
7988
}
8089

8190
/**
82-
* @return The proxy password.
83-
*/
91+
* @return The proxy password from the configuration if set, or from the "http.proxyPassword" system property if
92+
* {@link Builder#useSystemPropertyValues(Boolean)} is set to true
93+
* */
8494
public String password() {
85-
return password;
95+
return resolveValue(password, ProxySystemSetting.PROXY_PASSWORD);
8696
}
8797

8898
/**
89-
* @return The set of hosts that should not be proxied.
99+
* @return The set of hosts that should not be proxied. If the value is not set, the value present by "http.nonProxyHost
100+
* system property os returned. If system property is also not set, an unmodifiable empty set is returned.
90101
*/
91102
public Set<String> nonProxyHosts() {
92-
return nonProxyHosts;
103+
Set<String> hosts = nonProxyHosts == null && useSystemPropertyValues ? parseNonProxyHostProperty()
104+
: nonProxyHosts;
105+
return Collections.unmodifiableSet(hosts != null ? hosts : Collections.emptySet());
93106
}
94107

95108
@Override
@@ -199,6 +212,47 @@ public interface Builder extends CopyableBuilder<Builder, ProxyConfiguration> {
199212
* @return This object for method chaining.
200213
*/
201214
Builder password(String password);
215+
216+
/**
217+
* Set the option whether to use system property values from {@link ProxySystemSetting} if any of the config options
218+
* are missing. The value is set to "true" by default which means SDK will automatically use system property values if
219+
* options are not provided during building the {@link ProxyConfiguration} object. To disable this behaviour, set this
220+
* value to false.
221+
*
222+
* @param useSystemPropertyValues The option whether to use system proerpty values
223+
* @return This object for method chaining.
224+
*/
225+
Builder useSystemPropertyValues(Boolean useSystemPropertyValues);
226+
227+
}
228+
229+
private String resolveHost(String host) {
230+
return resolveValue(host, ProxySystemSetting.PROXY_HOST);
231+
}
232+
233+
private int resolvePort(int port) {
234+
return useSystemPropertyValues ? ProxySystemSetting.PROXY_PORT.getStringValue().map(Integer::parseInt).orElse(0)
235+
: port;
236+
}
237+
238+
/**
239+
* Uses the configuration options, system setting property and returns the final value of the given member.
240+
*/
241+
private String resolveValue(String value, ProxySystemSetting systemSetting) {
242+
return value == null && useSystemPropertyValues ? systemSetting.getStringValue().orElse(null)
243+
: value;
244+
}
245+
246+
private Set<String> parseNonProxyHostProperty() {
247+
String nonProxyHosts = ProxySystemSetting.NON_PROXY_HOSTS.getStringValue().orElse(null);
248+
249+
if (!StringUtils.isEmpty(nonProxyHosts)) {
250+
return Arrays.stream(nonProxyHosts.split("\\|"))
251+
.map(String::toLowerCase)
252+
.map(s -> s.replace("*", ".*?"))
253+
.collect(Collectors.toSet());
254+
}
255+
return Collections.emptySet();
202256
}
203257

204258
private static final class BuilderImpl implements Builder {
@@ -208,11 +262,13 @@ private static final class BuilderImpl implements Builder {
208262
private String username;
209263
private String password;
210264
private Set<String> nonProxyHosts = Collections.emptySet();
265+
private Boolean useSystemPropertyValues = Boolean.TRUE;
211266

212267
private BuilderImpl() {
213268
}
214269

215270
private BuilderImpl(ProxyConfiguration proxyConfiguration) {
271+
this.useSystemPropertyValues = proxyConfiguration.useSystemPropertyValues;
216272
this.scheme = proxyConfiguration.scheme;
217273
this.host = proxyConfiguration.host;
218274
this.port = proxyConfiguration.port;
@@ -262,6 +318,16 @@ public Builder password(String password) {
262318
return this;
263319
}
264320

321+
@Override
322+
public Builder useSystemPropertyValues(Boolean useSystemPropertyValues) {
323+
this.useSystemPropertyValues = useSystemPropertyValues;
324+
return this;
325+
}
326+
327+
public void setUseSystemPropertyValues(Boolean useSystemPropertyValues) {
328+
useSystemPropertyValues(useSystemPropertyValues);
329+
}
330+
265331
@Override
266332
public ProxyConfiguration build() {
267333
return new ProxyConfiguration(this);

0 commit comments

Comments
 (0)