Skip to content

Instantly share code, notes, and snippets.

@azakordonets
Created April 18, 2014 12:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save azakordonets/11041117 to your computer and use it in GitHub Desktop.
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…
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