|
49 | 49 | import java.io.File;
|
50 | 50 | import java.io.IOException;
|
51 | 51 | import java.io.InputStream;
|
| 52 | +import java.net.InetSocketAddress; |
52 | 53 | import java.net.MalformedURLException;
|
53 | 54 | import java.net.Proxy;
|
54 | 55 | import java.net.ProxySelector;
|
|
61 | 62 | import java.nio.file.Path;
|
62 | 63 | import java.nio.file.Paths;
|
63 | 64 | import java.nio.file.StandardCopyOption;
|
| 65 | +import java.util.ArrayList; |
64 | 66 | import java.util.Collections;
|
65 | 67 | import java.util.List;
|
66 | 68 | import java.util.Locale;
|
@@ -150,7 +152,16 @@ public void configure(Settings settings) throws InvalidSettingException {
|
150 | 152 | // So don't rely on the system properties for proxy; use the legacy settings configuration
|
151 | 153 | final String proxyHost = settings.getString(Settings.KEYS.PROXY_SERVER);
|
152 | 154 | final int proxyPort = settings.getInt(Settings.KEYS.PROXY_PORT, -1);
|
153 |
| - httpClientBuilder.setProxy(new HttpHost(proxyHost, proxyPort)); |
| 155 | + final String nonProxyHosts = settings.getString(Settings.KEYS.PROXY_NON_PROXY_HOSTS); |
| 156 | + if (nonProxyHosts != null && !nonProxyHosts.isEmpty()) { |
| 157 | + final ProxySelector selector = new SelectiveProxySelector( |
| 158 | + new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort)), |
| 159 | + nonProxyHosts.split("\\|") |
| 160 | + ); |
| 161 | + httpClientBuilder.setProxySelector(selector); |
| 162 | + } else { |
| 163 | + httpClientBuilder.setProxy(new HttpHost(proxyHost, proxyPort)); |
| 164 | + } |
154 | 165 | if (settings.getString(Settings.KEYS.PROXY_USERNAME) != null) {
|
155 | 166 | final String proxyuser = settings.getString(Settings.KEYS.PROXY_USERNAME);
|
156 | 167 | final char[] proxypass = settings.getString(Settings.KEYS.PROXY_PASSWORD).toCharArray();
|
@@ -584,4 +595,51 @@ public <T> T fetchAndHandle(@NotNull URL url, @NotNull HttpClientResponseHandler
|
584 | 595 | throw new IOException(msg, ex);
|
585 | 596 | }
|
586 | 597 | }
|
| 598 | + |
| 599 | + private static class SelectiveProxySelector extends ProxySelector { |
| 600 | + |
| 601 | + /** |
| 602 | + * The suffix-match entries from the nonProxyHosts (those starting with a {@code *}). |
| 603 | + */ |
| 604 | + private final List<String> suffixMatch = new ArrayList<>(); |
| 605 | + /** |
| 606 | + * The full host entries from the nonProxyHosts (those <em>not</em> starting with a {@code *}). |
| 607 | + */ |
| 608 | + private final List<String> fullmatch = new ArrayList<>(); |
| 609 | + /** |
| 610 | + * The proxy use when no proxy-exception is found. |
| 611 | + */ |
| 612 | + private final Proxy configuredProxy; |
| 613 | + |
| 614 | + SelectiveProxySelector(Proxy httpHost, String[] nonProxyHostsPatterns) { |
| 615 | + for (String nonProxyHostPattern : nonProxyHostsPatterns) { |
| 616 | + if (nonProxyHostPattern.startsWith("*")) { |
| 617 | + suffixMatch.add(nonProxyHostPattern.substring(1)); |
| 618 | + } else { |
| 619 | + fullmatch.add(nonProxyHostPattern); |
| 620 | + } |
| 621 | + } |
| 622 | + this.configuredProxy = httpHost; |
| 623 | + } |
| 624 | + |
| 625 | + @Override |
| 626 | + public List<Proxy> select(URI uri) { |
| 627 | + final String theHost = uri.getHost(); |
| 628 | + if (fullmatch.contains(theHost)) { |
| 629 | + return Collections.singletonList(Proxy.NO_PROXY); |
| 630 | + } else { |
| 631 | + for (String suffix : suffixMatch) { |
| 632 | + if (theHost.endsWith(suffix)) { |
| 633 | + return Collections.singletonList(Proxy.NO_PROXY); |
| 634 | + } |
| 635 | + } |
| 636 | + } |
| 637 | + return List.of(configuredProxy); |
| 638 | + } |
| 639 | + |
| 640 | + @Override |
| 641 | + public void connectFailed(URI uri, SocketAddress sa, IOException ioe) { |
| 642 | + // nothing to be done for this single proxy proxy-selector |
| 643 | + } |
| 644 | + } |
587 | 645 | }
|
0 commit comments