Created
April 18, 2014 12:18
-
-
Save azakordonets/11041117 to your computer and use it in GitHub Desktop.
This class allows you to get a hacky but working way of connecting with Java to SOCKS proxy, when standart ways are not working. Java has a problem with DNS resolving and therefore i had an issue with one of my project. When i was enabling proxy setting through System.Properties , i still was hitting production server, not the test server behind…
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.net.*; | |
import java.util.ArrayList; | |
import java.util.HashMap; | |
import java.io.IOException; | |
/** | |
* this class is needed for Java to connect to SOCKS proxy server | |
* Unfortunately Java cannot resolve remote DNS and therefore, when we set System.properties | |
* with our proxy server details, we hit incorrect server . This is because | |
* Java is connecting to Proxy, but DNS is resolving with system details and therefore goes to server directly. | |
* Therefore, to fix this issue, we had to add one more local HTTP proxy, that would redirect Java to proxy and | |
* resolve DNS properly for it. | |
*/ | |
public class MyProxySelector extends ProxySelector { | |
// Keep a reference on the previous default | |
public ProxySelector defsel = null; | |
/* | |
* Inner class representing a Proxy and a few extra data | |
*/ | |
class InnerProxy { | |
Proxy proxy; | |
SocketAddress addr; | |
// How many times did we fail to reach this proxy? | |
int failedCount = 0; | |
InnerProxy(InetSocketAddress a) { | |
addr = a; | |
proxy = new Proxy(Proxy.Type.HTTP, a); | |
} | |
SocketAddress address() { | |
return addr; | |
} | |
Proxy toProxy() { | |
return proxy; | |
} | |
int failed() { | |
return ++failedCount; | |
} | |
} | |
/* | |
* A list of proxies, indexed by their address. | |
*/ | |
HashMap<SocketAddress, InnerProxy> proxies = new HashMap<SocketAddress, InnerProxy>(); | |
public MyProxySelector(ProxySelector def, String host, int port) { | |
// Save the previous default | |
defsel = def; | |
// Populate the HashMap (List of proxies) | |
InnerProxy i = new InnerProxy(new InetSocketAddress(host, port)); | |
proxies.put(i.address(), i); | |
} | |
/* | |
* This is the method that the handlers will call. | |
* Returns a List of proxy. | |
*/ | |
public java.util.List<Proxy> select(URI uri) { | |
// Let's stick to the specs. | |
if (uri == null) { | |
throw new IllegalArgumentException("URI can't be null."); | |
} | |
/* | |
* If it's a http (or https) URL, then we use our own | |
* list. | |
*/ | |
String protocol = uri.getScheme(); | |
if ("http".equalsIgnoreCase(protocol) || | |
"https".equalsIgnoreCase(protocol)) { | |
ArrayList<Proxy> l = new ArrayList<Proxy>(); | |
for (InnerProxy p : proxies.values()) { | |
l.add(p.toProxy()); | |
} | |
return l; | |
} | |
/* | |
* Not HTTP or HTTPS (could be SOCKS or FTP) | |
* defer to the default selector. | |
*/ | |
if (defsel != null) { | |
return defsel.select(uri); | |
} else { | |
ArrayList<Proxy> l = new ArrayList<Proxy>(); | |
l.add(Proxy.NO_PROXY); | |
return l; | |
} | |
} | |
/* | |
* Method called by the handlers when it failed to connect | |
* to one of the proxies returned by select(). | |
*/ | |
public void connectFailed(URI uri, SocketAddress sa, IOException ioe) { | |
// Let's stick to the specs again. | |
if (uri == null || sa == null || ioe == null) { | |
throw new IllegalArgumentException("Arguments can't be null."); | |
} | |
/* | |
* Let's lookup for the proxy | |
*/ | |
InnerProxy p = proxies.get(sa); | |
if (p != null) { | |
/* | |
* It's one of ours, if it failed more than 3 times | |
* let's remove it from the list. | |
*/ | |
if (p.failed() >= 3) | |
proxies.remove(sa); | |
} else { | |
/* | |
* Not one of ours, let's delegate to the default. | |
*/ | |
if (defsel != null) | |
defsel.connectFailed(uri, sa, ioe); | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment