27

I want my Java program to use the system's proxy configuration. Accordingly, I used the code found in many places, such as this answer, to set java.net.useSystemProxies to true and call ProxySelector.getDefault().select(...) to discover the proxy for the particular host I want to reach. This works fine when I've configured a single explicit proxy server in Internet Properties. But if I have set "Use automatic configuration script", it always returns the DIRECT "proxy".

I know that the script works, as my browser can access the hosts for which it returns a proxy server, and without the script set, it can't. I even tried simplifying the script to its barest essentials:

function FindProxyForURL(url, host)
{
    return "PROXY my.proxy.mydomain:3128";
}

and it works in my browser, but ProxySelector.getDefault().select(...) still returns only DIRECT.

Am I missing something? (This is on Java 1.6 & Windows 7, should it matter.)

Community
  • 1
  • 1
vanmelle
  • 1,605
  • 1
  • 14
  • 22

5 Answers5

34

No, the Java ProxySelector does not read Proxy Auto-Config (PAC) files.

However, as suggested by Brian de Alwis as an answer to my similar question, the Proxy Vole library appears to provide that support/capability.

To provide network connectivity out of the box for you Java application you can use the Proxy - Vole library. It provides some strategies for autodetecting the current proxy settings. There are many configureable strategies to choose from. At the moment Proxy - Vole supports the following proxy detection strategies.

  • Read platform settings (Supports: Windows, KDE, Gnome, OSX)
  • Read browser setting (Supports: Firefox 3.x, Internet Explorer; Chrome and Webkit use the platform settings)
  • Read environment variables (often used variables on Linux / Unix server systems)
  • Autodetection script by using WPAD/PAC (Not all variations supported)
Community
  • 1
  • 1
Mads Hansen
  • 63,927
  • 12
  • 112
  • 147
  • 2
    Thanks for the tip. Googling for "java proxy selector" doesn't find this library, unless you're sharp enough to realize that some of the code fragments going by are part of a useful library. It's a shame Java doesn't already do it by itself, since it has the ProxySelector structure, and knows how to find an ordinary fixed proxy. – vanmelle Apr 26 '12 at 23:47
  • 2
    By the way, the instructions are a little misleading, in that the "default" configuration is kind of useless -- it uses the "read the java system properties" strategy, which is what you'd get without this library in the first place. What worked for me was ProxySearch proxySearch = new ProxySearch(); proxySearch.addStrategy(Strategy.OS_DEFAULT); myProxySelector = proxySearch.getProxySelector(); – vanmelle Apr 26 '12 at 23:50
  • Anyone knows about a lightweight alternative to proxy-vole? 6 MB feels a bit heavy for just some missing Java functionality. – Hummeling Engineering BV Feb 27 '19 at 14:03
  • The simplest solution happens to be to let JVM pick up the system proxies on program startup via -Djava.net.useSystemProxies=true as described in https://docs.oracle.com/javase/7/docs/api/java/net/doc-files/net-properties.html#Proxies – Ashwin Prabhu Aug 05 '22 at 07:19
15

As already suggested by Mads Hansen, Proxy-Vole does the trick!

You just need to add the jar from the download site to your classpath (dlls are included) and this code helped me to configure the proxy stettings:

ProxySearch proxySearch = new ProxySearch();
proxySearch.addStrategy(Strategy.OS_DEFAULT); 
proxySearch.addStrategy(Strategy.JAVA); 
proxySearch.addStrategy(Strategy.BROWSER); 
ProxySelector proxySelector = proxySearch.getProxySelector(); 

ProxySelector.setDefault(proxySelector); 
URI home = URI.create("http://www.google.com"); 
System.out.println("ProxySelector: " + proxySelector); 
System.out.println("URI: " + home); 
List<Proxy> proxyList = proxySelector.select(home); 
if (proxyList != null && !proxyList.isEmpty()) { 
 for (Proxy proxy : proxyList) { 
   System.out.println(proxy); 
   SocketAddress address = proxy.address(); 
   if (address instanceof InetSocketAddress) { 
     String host = ((InetSocketAddress) address).getHostName(); 
     String port = Integer.toString(((InetSocketAddress) address).getPort()); 
     System.setProperty("http.proxyHost", host); 
     System.setProperty("http.proxyPort", port); 
   } 
 } 
}
deradam
  • 276
  • 2
  • 4
  • The code isn't working for me :( I get NullPointerException in line List proxyList = proxySelector.select(home); proxySelector is null and if you look at getProxySelector() body, you'll see that it always returns null. – Suspended Apr 28 '15 at 00:34
  • same for me, getProxySelector() returns NULL (but only on my Windows, on my Linux the same code works!). – Ben Dec 11 '15 at 15:29
  • 5
    The Proxy-Vole project has been dormant since 2013, but there is some activity in a fork at GitHub: https://github.com/MarkusBernhardt/proxy-vole – Halvor Holsten Strand Dec 07 '17 at 21:02
  • @Ben do you found solution for this problem, because i add this lib and get same problem getProxySelector() returns NULL, please help because i`m stuck. – Kristiyan Varbanov Mar 14 '19 at 07:23
  • @Suspended do you found solution for this problem, because i add this lib and get same problem getProxySelector() returns NULL, please help because i`m stuck. – Kristiyan Varbanov Mar 14 '19 at 07:23
  • @deradam Why do we set env System.setProperty("http.proxyHost", host); because ProxySelector.setDefault(proxySelector); with this it work. – Shramik Jan 04 '21 at 12:09
  • @Shramik good question, I do not remember to be hones as this is almost 9 years ago that I have written it. But you are right, ProxySelector.setDefault(proxySelector); should be enough. The remaining lines however give you an idea how to access the results from the proxy selection process. – deradam Jun 12 '21 at 06:30
  • The simplest solution happens to be to let JVM pick up the system proxies on program startup via -Djava.net.useSystemProxies=true as described in https://docs.oracle.com/javase/7/docs/api/java/net/doc-files/net-properties.html#Proxies – Ashwin Prabhu Aug 05 '22 at 07:19
9

Yes, from version 9 automatic proxy configurations (PAC/WPAD) will be read from the operating system.

CleanUp
  • 410
  • 4
  • 12
5

You can use Proxy Vole to solve this issue:

If you know exactly which PAC-file you want to use, you can do:

UrlPacScriptSource source = new UrlPacScriptSource("http://www.example.org/proxy.pac");
PacProxySelector selector = new PacProxySelector(source);

ProxySelector.setDefault(selector);

The advantage of this is that it is not user-related. For example if running this as a Windows service, you may end up running it on the SYSTEM-user which may not have the same OS_DEFAULT proxy settings (if any) as the Administrator-user.

The approach using system/software values is:

ProxySearch proxySearch = new ProxySearch();
proxySearch.addStrategy(Strategy.OS_DEFAULT);
proxySearch.addStrategy(Strategy.BROWSER);
proxySearch.addStrategy(Strategy.JAVA);
ProxySelector proxySelector = proxySearch.getProxySelector();

ProxySelector.setDefault(proxySelector); 

This starts with OS_DEFAULT, then JAVA and lastly BROWSER as strategies for the proxy selector.

This code is based on the GitHub code, release version 1.0.3.

Halvor Holsten Strand
  • 19,829
  • 17
  • 83
  • 99
4

I could load Proxy Auto-Config (PAC) file on Java. Please see below codes and package. I hope this would what you were looking for:

import com.sun.deploy.net.proxy.*;
.
.
BrowserProxyInfo b = new BrowserProxyInfo();        
b.setType(ProxyType.AUTO);
b.setAutoConfigURL("http://yourhost/proxy.file.pac");       
DummyAutoProxyHandler handler = new DummyAutoProxyHandler();
handler.init(b);

URL url = new URL("http://host_to_query");
ProxyInfo[] ps = handler.getProxyInfo(url);     
for(ProxyInfo p : ps){
    System.out.println(p.toString());
}

You already have a [com.sun.deploy.net.proxy] package on your machine! Find [deploy.jar] ;D

Jaeh
  • 609
  • 1
  • 6
  • 19