不对回环地址应用代理 (#4338)
This commit is contained in:
@@ -19,22 +19,28 @@ package org.jackhuang.hmcl.setting;
|
|||||||
|
|
||||||
import javafx.beans.InvalidationListener;
|
import javafx.beans.InvalidationListener;
|
||||||
import org.jackhuang.hmcl.util.StringUtils;
|
import org.jackhuang.hmcl.util.StringUtils;
|
||||||
|
import org.jackhuang.hmcl.util.io.NetworkUtils;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import static org.jackhuang.hmcl.setting.ConfigHolder.config;
|
import static org.jackhuang.hmcl.setting.ConfigHolder.config;
|
||||||
import static org.jackhuang.hmcl.util.logging.Logger.LOG;
|
import static org.jackhuang.hmcl.util.logging.Logger.LOG;
|
||||||
|
|
||||||
public final class ProxyManager {
|
public final class ProxyManager {
|
||||||
|
|
||||||
private static final ProxySelector NO_PROXY = new SimpleProxySelector(Proxy.NO_PROXY);
|
private static final SimpleProxySelector NO_PROXY = new SimpleProxySelector(Proxy.NO_PROXY);
|
||||||
private static final ProxySelector SYSTEM_DEFAULT = Objects.requireNonNullElse(ProxySelector.getDefault(), NO_PROXY);
|
private static final ProxySelector SYSTEM_DEFAULT;
|
||||||
|
|
||||||
|
static {
|
||||||
|
ProxySelector systemProxySelector = ProxySelector.getDefault();
|
||||||
|
SYSTEM_DEFAULT = systemProxySelector != null
|
||||||
|
? new ProxySelectorWrapper(systemProxySelector)
|
||||||
|
: NO_PROXY;
|
||||||
|
}
|
||||||
|
|
||||||
private static volatile @NotNull ProxySelector defaultProxySelector = SYSTEM_DEFAULT;
|
private static volatile @NotNull ProxySelector defaultProxySelector = SYSTEM_DEFAULT;
|
||||||
private static volatile @Nullable SimpleAuthenticator defaultAuthenticator = null;
|
private static volatile @Nullable SimpleAuthenticator defaultAuthenticator = null;
|
||||||
@@ -51,7 +57,7 @@ public final class ProxyManager {
|
|||||||
LOG.warning("Illegal proxy port: " + port);
|
LOG.warning("Illegal proxy port: " + port);
|
||||||
return NO_PROXY;
|
return NO_PROXY;
|
||||||
} else {
|
} else {
|
||||||
return new SimpleProxySelector(new Proxy(proxyType, new InetSocketAddress(host, port)));
|
return new ProxySelectorWrapper(new SimpleProxySelector(new Proxy(proxyType, new InetSocketAddress(host, port))));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return ProxyManager.SYSTEM_DEFAULT;
|
return ProxyManager.SYSTEM_DEFAULT;
|
||||||
@@ -106,15 +112,41 @@ public final class ProxyManager {
|
|||||||
config().proxyPassProperty().addListener(updateAuthenticator);
|
config().proxyPassProperty().addListener(updateAuthenticator);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class SimpleProxySelector extends ProxySelector {
|
private static abstract class AbstractProxySelector extends ProxySelector {
|
||||||
|
@Override
|
||||||
|
public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
|
||||||
|
if (uri == null || sa == null || ioe == null) {
|
||||||
|
throw new IllegalArgumentException("Arguments can't be null.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class SimpleProxySelector extends AbstractProxySelector {
|
||||||
private final List<Proxy> proxies;
|
private final List<Proxy> proxies;
|
||||||
|
|
||||||
SimpleProxySelector(Proxy proxy) {
|
SimpleProxySelector(Proxy proxy) {
|
||||||
this(Collections.singletonList(proxy));
|
this.proxies = List.of(proxy);
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleProxySelector(List<Proxy> proxies) {
|
@Override
|
||||||
this.proxies = proxies;
|
public List<Proxy> select(URI uri) {
|
||||||
|
if (uri == null)
|
||||||
|
throw new IllegalArgumentException("URI can't be null.");
|
||||||
|
return proxies;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "SimpleProxySelector" + proxies;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wraps another ProxySelector to avoid using proxy for loopback addresses.
|
||||||
|
private static final class ProxySelectorWrapper extends AbstractProxySelector {
|
||||||
|
private final ProxySelector source;
|
||||||
|
|
||||||
|
ProxySelectorWrapper(ProxySelector source) {
|
||||||
|
this.source = source;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -122,19 +154,10 @@ public final class ProxyManager {
|
|||||||
if (uri == null)
|
if (uri == null)
|
||||||
throw new IllegalArgumentException("URI can't be null.");
|
throw new IllegalArgumentException("URI can't be null.");
|
||||||
|
|
||||||
return proxies;
|
if (NetworkUtils.isLoopbackAddress(uri))
|
||||||
}
|
return NO_PROXY.proxies;
|
||||||
|
|
||||||
@Override
|
return source.select(uri);
|
||||||
public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
|
|
||||||
if (uri == null || sa == null || ioe == null) {
|
|
||||||
throw new IllegalArgumentException("Arguments can't be null.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "SimpleProxySelector" + proxies;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
package org.jackhuang.hmcl.util.io;
|
package org.jackhuang.hmcl.util.io;
|
||||||
|
|
||||||
import org.jackhuang.hmcl.util.Pair;
|
import org.jackhuang.hmcl.util.Pair;
|
||||||
|
import org.jackhuang.hmcl.util.StringUtils;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
@@ -45,6 +46,19 @@ public final class NetworkUtils {
|
|||||||
private NetworkUtils() {
|
private NetworkUtils() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isLoopbackAddress(URI uri) {
|
||||||
|
String host = uri.getHost();
|
||||||
|
if (StringUtils.isBlank(host))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
InetAddress addr = InetAddress.getByName(host);
|
||||||
|
return addr.isLoopbackAddress();
|
||||||
|
} catch (UnknownHostException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isHttpUri(URI uri) {
|
public static boolean isHttpUri(URI uri) {
|
||||||
return "http".equals(uri.getScheme()) || "https".equals(uri.getScheme());
|
return "http".equals(uri.getScheme()) || "https".equals(uri.getScheme());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,17 +19,31 @@ package org.jackhuang.hmcl.util.io;
|
|||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
import static java.nio.charset.StandardCharsets.US_ASCII;
|
import static java.nio.charset.StandardCharsets.US_ASCII;
|
||||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
import static org.jackhuang.hmcl.util.io.NetworkUtils.encodeLocation;
|
import static org.jackhuang.hmcl.util.io.NetworkUtils.*;
|
||||||
import static org.jackhuang.hmcl.util.io.NetworkUtils.getCharsetFromContentType;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Glavo
|
* @author Glavo
|
||||||
*/
|
*/
|
||||||
public class NetworkUtilsTest {
|
public class NetworkUtilsTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIsLoopbackAddress() {
|
||||||
|
assertTrue(isLoopbackAddress(URI.create("https://127.0.0.1/test")));
|
||||||
|
assertTrue(isLoopbackAddress(URI.create("https://127.0.0.1:8080/test")));
|
||||||
|
assertTrue(isLoopbackAddress(URI.create("https://localhost/test")));
|
||||||
|
assertTrue(isLoopbackAddress(URI.create("https://localhost:8080/test")));
|
||||||
|
assertTrue(isLoopbackAddress(URI.create("https://[::1]/test")));
|
||||||
|
assertTrue(isLoopbackAddress(URI.create("https://[::1]:8080/test")));
|
||||||
|
|
||||||
|
assertFalse(isLoopbackAddress(URI.create("https://www.example.com/test")));
|
||||||
|
assertFalse(isLoopbackAddress(URI.create("https://www.example.com:8080/test")));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEncodeLocation() {
|
public void testEncodeLocation() {
|
||||||
assertEquals("https://github.com", encodeLocation("https://github.com"));
|
assertEquals("https://github.com", encodeLocation("https://github.com"));
|
||||||
|
|||||||
Reference in New Issue
Block a user