ProxySelector: Different Proxy for Each URL
Asked Answered
K

2

6

I'm trying to understand how the ProxySelector class works. My current code looks like this:

    URI uri = new URI("http://google.com");
    proxySelector.select(uri);

I understand that when calling proxySelector.select(uri); this is suppose to return a list of proxies for the respective URI. But I don't see how to set the proxy for each URI.

I know I could set the default proxy using the setDefault() method but as far as I understand this will set the system wide proxy, not the proxy for a specific URI.

I might be missing some basic point here but how do I set one proxy for url A (such as http://google.com) and a different proxy for url B (such as http://ebay.com) and then have the system automatically select the correct proxy each time it connects to the corresponding url?

Kobi answered 6/11, 2017 at 16:2 Comment(2)
See: #34320179Carborundum
Thanks. So basically you need to implement the logic of which proxy is selected in the "select" method? How to you actually connect to the URL with the proxy by using System.setProperty()?Kobi
C
7
  1. Override ProxySelector.select(URI uri) method where you implement custom logic to choose right proxy or list of proxies for the URI.

  2. either set the new, custom, ProxySelector as system wide by calling ProxySelector.setDefault(customProxySelector).

    Any subclass of URLConnection will use ProxySelector, e.g.:

    URLConnection conn = url.openConnection();
    
  3. or configure framework you are going to use to invoke remote URI, e.g Spring RestTemplate:

    HttpRoutePlanner routePlanner = new SystemDefaultRoutePlanner(new MyProxySelector());
    
    HttpComponentsClientHttpRequestFactory clientHttpRequestFactory 
        = new HttpComponentsClientHttpRequestFactory(
            HttpClientBuilder.create()
                .setRoutePlanner(routePlanner)
                .build());
    restTemplate = new RestTemplate(clientHttpRequestFactory);
    

It is good practice to fallback to default ProxySelector in custom select(URI uri) in case the custom logic does not determine suitable proxy for the uri.

See my other answer for ProxySelector example.

Networking and proxies is well explained in Java Networking and Proxies (paragraph 4 ProxySelector) and ProxySelector Java docs.

Carborundum answered 7/11, 2017 at 19:52 Comment(2)
I'm trying to use ProxySelector class in conjunction with ebay API sdk - if I set the proxy can I guarantee all calls to ebay will be routed through a proxy?Kobi
My guess is yes, but I do not have experience with ebay API. I am backing my opinion on developer.ebay.com/DevZone/javasdk-jaxb/docs/readme.htm#631 where they introduce custom ProxySelector. Which is (if I can trust following source code github.com/prestonvanloon/ebaysdkcore/blob/master/src/main/java/… ) nothing just a selector leading to single proxy for each URL.Carborundum
L
2

Actually, that works pretty well without any reflection, by just using an enhanced ProxySelector, that supports whitelisting for specific urls and passes the rest through to a delegate (aka the default) ProxySelector.

public class DelegatingProxySelector extends ProxySelector {

    private final Set<URI> allProxiedUri = new HashSet<>();

    private String proxyHost;
    private Integer proxyPort;

    private final ProxySelector delegate;

    public DelegatingProxySelector(
        String proxyHost, Integer proxyPort, ProxySelector delegate) {
        this.proxyHost = proxyHost;
        this.proxyPort = proxyPort;
        this.delegate = delegate;
    }

    @Override
    public List<Proxy> select(final URI uri) {
        if (allProxiedUri.contains(uri)) {
            final InetSocketAddress proxyAddress = InetSocketAddress
                .createUnresolved(proxyHost, proxyPort);
            return Collections.singletonList(new Proxy(Type.HTTP, proxyAddress));
        }
        return delegate.select(uri);
    }

    @Override
    public void connectFailed(final URI uri, final SocketAddress sa, final IOException ioe) {
        System.err.println("Unable to reach uri " + uri + " via proxy: " + ioe.getMessage());
    }
    
    public void addProxiedUri(URI uri) {
        allProxiedUri.add(uri);
    }
}

...

final DelegatingProxySelector delegatingProxySelector = new DelegatingProxySelector("localhost", 3128, ProxySelector.getDefault());
ProxySelector.setDefault(delegatingProxySelector);
Lemuroid answered 13/11, 2020 at 9:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.