Page tree
Skip to end of metadata
Go to start of metadata

Last updated: Jul 13, 2017 11:12

by Jeremy Payne

Configure Selenium/Appium to work through Proxy without the use of JVM proxy configurations.

You can use JVM proxy settings to accomplish passing through a proxy however there are some limitations with this. First - ALL web requests will travel over your proxy if you utilize the JVM settings and this is likely not desired if you must call internal services as part of your process. Secondly in the event where your Proxy system requires re-authentication after a period of time the JVM settings don't know how to do this and you will end up getting your connections interrupted.

Selenium and Appium communicate to the Selenium Grid system by default through the Apache HTTP Client library in Java. We can override the Apache HttpClient configuration to use a proxy by utilizing Selenium's HttpCommandExecutor.

Solution for this article can be referenced on stack overflow here. Code from this article and usage can be seen below, this is leveraging NTLM authentication however you could modify this to support other authentication schemes as well.

First create a new class in your project as outlined below

import java.net.URL;
import org.apache.http.impl.client.HttpClientBuilder; import org.openqa.selenium.remote.internal.ApacheHttpClient;
public class MyHttpClientFactory implements org.openqa.selenium.remote.http.HttpClient.Factory {
    final HttpClientBuilder builder; 
    public MyHttpClientFactory(HttpClientBuilder builder) {
        this.builder = builder;
    }
    @Override
    public org.openqa.selenium.remote.http.HttpClient createClient(URL url) {
        return new ApacheHttpClient(builder.build(), url);
    } }

 

Next add the below methods to the class you are using to create your driver instance. Utilize the connectViaProxy method to create your instance for you instead of the default new RemoteWebDriver(...) or new AppiumDriver(...). You should modify the proxy and host variables at the top of the method to match your own.

 public RemoteWebDriver connectViaProxy(DesiredCapabilities caps) {
        String proxyHost = "?";
        int proxyPort = 8080;
        String proxyUserDomain = "?";
        String proxyUser = "?";
        String proxyPassword = "?";
        String host="yourCloud.perfectomobile.com";
        URL url;
        try {
            url = new URL("https://" + host + "/nexperience/perfectomobile/wd/hub");
        } catch (MalformedURLException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
        HttpClientBuilder builder = HttpClientBuilder.create();
        HttpHost proxy = new HttpHost(proxyHost, proxyPort);
        CredentialsProvider credsProvider = new BasicCredentialsProvider();
        credsProvider.setCredentials(new AuthScope(proxyHost, proxyPort), new NTCredentials(proxyUser, proxyPassword, getWorkstation(), proxyUserDomain));
        if (url.getUserInfo() != null && !url.getUserInfo().isEmpty()) {
            credsProvider.setCredentials(new AuthScope(url.getHost(), (url.getPort() > 0 ? url.getPort() : url.getDefaultPort())), new UsernamePasswordCredentials(url.getUserInfo()));
        }
        builder.setProxy(proxy);
        builder.setDefaultCredentialsProvider(credsProvider);
        Factory factory = new MyHttpClientFactory(builder);
        HttpCommandExecutor executor = new HttpCommandExecutor(new HashMap<String, CommandInfo>(), url, factory);
        return new RemoteWebDriver(executor, caps);
    }
    private String getWorkstation() {
        Map<String, String> env = System.getenv();
        if (env.containsKey("COMPUTERNAME")) {
            // Windows
            return env.get("COMPUTERNAME");         
        } else if (env.containsKey("HOSTNAME")) {
            // Unix/Linux/MacOS
            return env.get("HOSTNAME");
        } else {
            // From DNS
            try
            {
                return InetAddress.getLocalHost().getHostName();
            }
            catch (UnknownHostException ex)
            {
                return "Unknown";
            }
        }
    }


 
  • No labels