Skip to content

Commit 6700fc0

Browse files
committed
Support leading-dot suffixes in NO_PROXY
1 parent ca8030a commit 6700fc0

10 files changed

Lines changed: 61 additions & 6 deletions

File tree

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"type": "bugfix",
3+
"category": "AWS SDK for Java v2",
4+
"contributor": "afarber",
5+
"description": "Support leading-dot domain suffixes in the NO_PROXY environment variable."
6+
}

core/crt-core/src/main/java/software/amazon/awssdk/crtcore/CrtProxyConfiguration.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,8 @@ public interface Builder {
276276
* originate from environment variableValues, and no partial settings will be obtained from SystemPropertyValues.
277277
* <p>Comma-separated host names in the NO_PROXY environment variable indicate multiple hosts to exclude from
278278
* proxy settings. Surrounding empty spaces around each host name are trimmed, so both {@code "a.com,b.com"} and
279-
* {@code "a.com, b.com"} are accepted.
279+
* {@code "a.com, b.com"} are accepted. A leading-dot suffix such as {@code .example.com} is equivalent to
280+
* {@code *.example.com}.
280281
*
281282
* @param useEnvironmentVariableValues The option whether to use environment variable values
282283
* @return This object for method chaining.
@@ -410,4 +411,4 @@ public void setUseSystemPropertyValues(Boolean useSystemPropertyValues) {
410411
}
411412

412413
}
413-
}
414+
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,7 @@ public interface Builder extends CopyableBuilder<Builder, ProxyConfiguration> {
313313
* proxy settings. Surrounding empty spaces around each host name are trimmed, so both {@code "a.com,b.com"} and
314314
* {@code "a.com, b.com"} are accepted. Each entry may be an exact host name (e.g. {@code example.com}), a
315315
* leading-wildcard suffix (e.g. {@code *.example.com}, which matches {@code example.com} and its subdomains),
316+
* or a leading-dot suffix (e.g. {@code .example.com}, equivalent to {@code *.example.com}),
316317
* a single {@code *} (which matches all hosts), or a CIDR range for IP addresses (e.g. {@code 10.0.0.0/8}).
317318
*
318319
* @param useEnvironmentVariableValues The option whether to use environment variable values.

http-clients/apache-client/src/test/java/software/amazon/awssdk/http/apache/internal/SdkProxyRoutePlannerTest.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package software.amazon.awssdk.http.apache.internal;
1717

1818
import static org.junit.jupiter.api.Assertions.assertEquals;
19+
import static org.junit.jupiter.api.Assertions.assertNull;
1920

2021
import java.util.Collections;
2122
import org.apache.http.HttpException;
@@ -29,6 +30,7 @@
2930
*/
3031
public class SdkProxyRoutePlannerTest {
3132
private static final HttpHost S3_HOST = new HttpHost("s3.us-west-2.amazonaws.com", 443, "https");
33+
private static final HttpHost INTERNAL_HOST = new HttpHost("s3.storage.company.internal", 443, "https");
3234
private static final HttpGet S3_REQUEST = new HttpGet("/my-bucket/my-object");
3335
private static final HttpClientContext CONTEXT = new HttpClientContext();
3436

@@ -49,4 +51,12 @@ public void testSetsCorrectSchemeBasedOnProcotol_HTTP() throws HttpException {
4951
assertEquals("localhost", proxyHost.getHostName());
5052
assertEquals("http", proxyHost.getSchemeName());
5153
}
54+
55+
@Test
56+
public void leadingDotSuffixPatternBypassesProxy() throws HttpException {
57+
SdkProxyRoutePlanner planner = new SdkProxyRoutePlanner("localhost", 1234, "https",
58+
Collections.singleton(".*?.company.internal"));
59+
60+
assertNull(planner.determineRoute(INTERNAL_HOST, S3_REQUEST, CONTEXT).getProxyHost());
61+
}
5262
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,7 @@ public interface Builder extends CopyableBuilder<Builder, ProxyConfiguration> {
308308
* proxy settings. Surrounding empty spaces around each host name are trimmed, so both {@code "a.com,b.com"} and
309309
* {@code "a.com, b.com"} are accepted. Each entry may be an exact host name (e.g. {@code example.com}), a
310310
* leading-wildcard suffix (e.g. {@code *.example.com}, which matches {@code example.com} and its subdomains),
311+
* or a leading-dot suffix (e.g. {@code .example.com}, equivalent to {@code *.example.com}),
311312
* a single {@code *} (which matches all hosts), or a CIDR range for IP addresses (e.g. {@code 10.0.0.0/8}).
312313
*
313314
* @param useEnvironmentVariableValues The option whether to use environment variable values.

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ public interface Builder extends CrtProxyConfiguration.Builder, CopyableBuilder<
126126
* proxy settings will exclusively originate from Environment Variable Values, and no partial settings will be obtained
127127
* from System Property Values.
128128
* <p>Comma-separated host names in the NO_PROXY environment variable indicate multiple hosts to exclude from
129-
* proxy settings.
129+
* proxy settings. A leading-dot suffix such as {@code .example.com} is equivalent to {@code *.example.com}.
130130
*
131131
* @param useEnvironmentVariableValues The option whether to use environment variable values
132132
* @return This object for method chaining.
@@ -177,4 +177,4 @@ public ProxyConfiguration build() {
177177
return new ProxyConfiguration(this);
178178
}
179179
}
180-
}
180+
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,7 @@ public interface Builder extends CopyableBuilder<Builder, ProxyConfiguration> {
353353
* proxy settings. Surrounding empty spaces around each host name are trimmed, so both {@code "a.com,b.com"} and
354354
* {@code "a.com, b.com"} are accepted. Each entry may be an exact host name (e.g. {@code example.com}), a
355355
* leading-wildcard suffix (e.g. {@code *.example.com}, which matches {@code example.com} and its subdomains),
356+
* or a leading-dot suffix (e.g. {@code .example.com}, equivalent to {@code *.example.com}),
356357
* a single {@code *} (which matches all hosts), or a CIDR range for IP addresses (e.g. {@code 10.0.0.0/8}).
357358
*
358359
* @param useEnvironmentVariablesValues The option whether to use environment variable values
@@ -460,4 +461,4 @@ public ProxyConfiguration build() {
460461
return new ProxyConfiguration(this);
461462
}
462463
}
463-
}
464+
}

http-clients/url-connection-client/src/main/java/software/amazon/awssdk/http/urlconnection/ProxyConfiguration.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ public interface Builder extends CopyableBuilder<Builder, ProxyConfiguration> {
261261
* proxy settings. Surrounding empty spaces around each host name are trimmed, so both {@code "a.com,b.com"} and
262262
* {@code "a.com, b.com"} are accepted. Each entry may be an exact host name (e.g. {@code example.com}), a
263263
* leading-wildcard suffix (e.g. {@code *.example.com}, which matches {@code example.com} and its subdomains),
264+
* or a leading-dot suffix (e.g. {@code .example.com}, equivalent to {@code *.example.com}),
264265
* a single {@code *} (which matches all hosts), or a CIDR range for IP addresses (e.g. {@code 10.0.0.0/8}).
265266
*
266267
* @param useEnvironmentVariablesValues The option whether to use environment variable values

utils/src/main/java/software/amazon/awssdk/utils/http/SdkHttpUtils.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,10 +436,15 @@ public static Set<String> parseNonProxyHostsProperty() {
436436
}
437437

438438
private static Set<String> extractNonProxyHosts(String nonProxyHosts) {
439+
return extractNonProxyHosts(nonProxyHosts, UnaryOperator.identity());
440+
}
441+
442+
private static Set<String> extractNonProxyHosts(String nonProxyHosts, UnaryOperator<String> tokenMapper) {
439443
if (nonProxyHosts != null && !isEmpty(nonProxyHosts)) {
440444
return Arrays.stream(nonProxyHosts.split("\\|"))
441445
.map(String::trim)
442446
.map(String::toLowerCase)
447+
.map(tokenMapper)
443448
.map(s -> StringUtils.replace(s, "*", ".*?"))
444449
.collect(Collectors.toSet());
445450
}
@@ -450,6 +455,10 @@ public static Set<String> parseNonProxyHostsEnvironmentVariable() {
450455
String hosts = ProxyEnvironmentSetting.NO_PROXY.getStringValue()
451456
.map(noProxyHost -> noProxyHost.replace(",", "|"))
452457
.orElse(null);
453-
return extractNonProxyHosts(hosts);
458+
return extractNonProxyHosts(hosts, SdkHttpUtils::convertLeadingDotToWildcard);
459+
}
460+
461+
private static String convertLeadingDotToWildcard(String host) {
462+
return host.startsWith(".") ? "*" + host : host;
454463
}
455464
}

utils/src/test/java/software/amazon/awssdk/utils/SdkHttpUtilsTest.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,16 @@ void parseListOfNonProxyHostWithPipesAndWildCard(){
318318
.collect(Collectors.toSet()));
319319
}
320320

321+
@Test
322+
void parseListOfNonProxyHostWithLeadingDotSuffix() {
323+
ENVIRONMENT_VARIABLE_HELPER.set("no_proxy", "example.com, .company.internal,*.greedy.org");
324+
325+
Set<String> strings = SdkHttpUtils.parseNonProxyHostsEnvironmentVariable();
326+
327+
assertThat(strings).isEqualTo(Stream.of("example.com", ".*?.company.internal", ".*?.greedy.org")
328+
.collect(Collectors.toSet()));
329+
}
330+
321331
@Test
322332
void parseNonProxyHostsProperty_regexPathStillRewritesWildcard() {
323333
String previous = System.getProperty("http.nonProxyHosts");
@@ -334,6 +344,21 @@ void parseNonProxyHostsProperty_regexPathStillRewritesWildcard() {
334344
}
335345
}
336346

347+
@Test
348+
void parseNonProxyHostsProperty_leadingDotIsNotNormalized() {
349+
String previous = System.getProperty("http.nonProxyHosts");
350+
System.setProperty("http.nonProxyHosts", ".company.internal");
351+
try {
352+
assertThat(SdkHttpUtils.parseNonProxyHostsProperty()).containsExactly(".company.internal");
353+
} finally {
354+
if (previous == null) {
355+
System.clearProperty("http.nonProxyHosts");
356+
} else {
357+
System.setProperty("http.nonProxyHosts", previous);
358+
}
359+
}
360+
}
361+
337362
@Test
338363
void parseListOfNonProxyHostWithCommaSpace_trimsSurroundingWhitespace(){
339364
String multipleHostNames = "example.com, *greedy.org, 192.168.1.1";

0 commit comments

Comments
 (0)