Slow Selenium tests when using proxy with BrowserMob - java

I am setting up a ChromeDriver using BrowserMob(http://bmp.lightbody.net/) for intercepting HTTP responses.
ProxyServer proxyServer = null;
proxyServer = new ProxyServer(9101);
proxyServer.start();
proxyServer.setCaptureContent(true);
proxyServer.setCaptureHeaders(true);
Proxy proxy = proxyServer.seleniumProxy();
proxy.setHttpProxy("localhost:9101");
proxyServer.addResponseInterceptor(new ResponseInterceptor() {
#Override
public void process(BrowserMobHttpResponse response, Har har) {
if (response.getRawResponse().getStatusLine().getStatusCode() == 500) {
// do something
}
}
});
DesiredCapabilities capabilities = DesiredCapabilities.chrome();
capabilities.setCapability(CapabilityType.PROXY, proxy);
System.setProperty("webdriver.chrome.driver", "seleniumdrivers/chromedriver.exe");
ChromeOptions options = new ChromeOptions();
options.addArguments("--lang=nl");
capabilities.setCapability(ChromeOptions.CAPABILITY, options);
this.driver = new ChromeDriver(capabilities);
When running a Selenium test every page load is extremely slow. Without the proxy it works fine. Anyone knows the reason/ solution for this?
In the log console the following message appears: jan 10, 2014 12:58:06 PM net.sf.uadetector.datastore.AbstractUpdateOperation isUpdateAvailable
INFO: Can not check for an updated version. Are you sure you have an established internet connection?
No idea if this is related.
Running Selenium tests on an online website (not local server), which means I have internet connection

Related

Selenium opening browser but not loading websites in Java

I am using Selenium in a Burp plugin but I can't load pages with the get method. Browsers open correctly, both Firefox and Chrome, but they don't load the page. Chrome address bar shows "data;.", while Firefox has no text in it. I am using the last driver available, Chrome 81.0.4044.183 and the driver for this exact version, while Firefox is 76.0.1 and I am using GeckoDriver 0.24 (since 0.25+ have a known bug) and it works with the last version of Firefox.
The code is the following
void runBrowserAutomatization(File fileDriver, String seleniumTrack, boolean isHeadless) {
WebDriver driver;
if (gui.usedBrowser().toLowerCase().contains("chrome")) {
ChromeOptions options = new ChromeOptions();
Proxy proxy = new Proxy();
proxy.setHttpProxy("localhost:8080");
proxy.setSslProxy("localhost:8080");
options.setCapability(CapabilityType.PROXY, proxy);
options.setHeadless(isHeadless);
System.setProperty("webdriver.chrome.driver", fileDriver.getPath());
driver = new ChromeDriver(options);
} else if (gui.usedBrowser().toLowerCase().contains("firefox")) {
FirefoxOptions options = new FirefoxOptions();
Proxy proxy = new Proxy();
proxy.setHttpProxy("localhost:8080");
proxy.setSslProxy("localhost:8080");
options.setCapability(CapabilityType.PROXY, proxy);
options.setHeadless(isHeadless);
System.setProperty("webdriver.gecko.driver", fileDriver.getPath());
driver = new FirefoxDriver(options);
} else {
PrintMsg("No browser selected...");
return;
}
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get("https://www.nytimes.com/");
driver.quit();
}
I may also think it is a Proxy misconfiguration, Burp certificate is installed in Firefox and Windows (where Chrome gets Certificate Authorities) but is not shown in the settings of the instance started by Selenium. Any help or suggestion is highly appreciated, thnaks.

Add ssl certificate to selenium-webdriver

I use selenium for end-to-end test with chromeDriver. The websites to test require an ssl certificate. When I manually open the browser, there is a popup that lets me select an installed certificate. Different tests access different URLs and also need different certificates. However, if I run the tests in headless mode, there is no popup. So I need a way to programatically set a certificate (eg. set a .pem file) to be used for the current test.
How can I achieve this?
I tried setting up a browserMob proxy which I then configured as a proxy in selenium - however, this does not seem to do anything... Are there better approaches? What am I doing wrong? Here's what I tried:
PemFileCertificateSource pemFileCertificateSource = new PemFileCertificateSource(
new File("myCertificate.pem"),
new File("myPrivateKey.pem"),
"myPrivateKeyPassword");
ImpersonatingMitmManager mitmManager = ImpersonatingMitmManager.builder()
.rootCertificateSource(pemFileCertificateSource)
.build();
BrowserMobProxy browserMobProxy = new BrowserMobProxyServer();
browserMobProxy.setTrustAllServers(true);
browserMobProxy.setMitmManager(mitmManager);
browserMobProxy.start(8080);
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.setProxy(ClientUtil.createSeleniumProxy(browserMobProxy));
WebDriver webDriver = new ChromeDriver(chromeOptions);
// use the webdriver for tests, e.g. assertEquals("foo", webDriver.findElement(...))
So apparantly this is not possible with BrowserMob out of the box. I therefore wrote a proxy extension SeleniumSslProxy that can be plugged into Selenium and adds certificate based authentication to create a HTTPS connection.
This is how it works:
intercept Selenium HTTP requests with BrowserMob
setup an SSLContext given a certificate (.pfx file) and password
use okhttp to forward the request to the target URL
convert the okhttp Response to a netty FullHttpResponse so it can be handled by Selenium
You can find the code on github. Here's an example how it can be used in Selenium end-to-end tests (also works in headless mode):
#Before
public void setup() {
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
File clientSslCertificate = new File(
classLoader.getResource("certificates/some-certificate.pfx").getFile());
String certificatePassword = "superSecret";
this.proxy = new SeleniumSslProxy(clientSslCertificate, certificatePassword);
this.proxy.start();
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.setProxy(proxy);
this.webDriver = new ChromeDriver(chromeOptions);
}
#Test
public void pageTitleIsFoo() {
// given
String url = "http://myurl.lol";
// NOTE: do not use https in the URL here. It will be converted to https by the proxy.
// when
this.webDriver.get(url);
this.webDriver.manage().timeouts().implicitlyWait(5, SECONDS);
// then
WebElement title = this.webDriver.findElement(By.className("title"));
assertEquals("Foo", title.getText());
}
#After
public void teardown() {
this.webDriver.quit();
this.proxy.stop();
}
Note that I only used chromeDriver and never tested it with other drivers. Minor adjustments to the SeleniumSslProxy might be necessary to be used with other drivers.

Selenium + Proxy = Fail

Proxy not working in Selenium
First of all i use free proxys from proxyfish (maybe thats the problem alrdy) https://hidemyna.me/en/proxy-checker/ tells me theyre working.
I found lots of code/solutions, most is outdated (capabilities=options..) or not working for me.
Tried several code/proxys chrome/ff however https://www.iplocation.net/ and https://whatismyipaddress.com showing actual IP address (IPv4 and IPv6).
What I tried..
System.setProperty("webdriver.chrome.driver", "C:\\selenium\\chromedriver.exe");
System.getProperties().put("74.208.112.***", "8080"); //1st try
Proxy proxy = new Proxy();
proxy.setHttpProxy("74.208.112.***:8080"); //2nd try
ChromeOptions options = new ChromeOptions();
options.setCapability("proxy", proxy);
options.setProxy(proxy);
options.addArguments("--proxy-server=74.208.112.***:8080"); //3rd try
ChromeDriver driver = new ChromeDriver(options);
driver.get("https://www.iplocation.net/");
driver.get("https://whatismyipaddress.com/");
Solution:
proxy.setSslProxy("74.208.112.***:8080");
Is there a way to test proxy connection before using proxy?

Selenium (Chrome) and BrowserMob doesn't work for https

I have been trying to integrate BrowserMob to my selenium tests. It works fine with website that work on http, but with https websites the browsers stop working and the HAR file doesn't contain any requests.
When navigating to a https site I get this error on the browser.
"There is something wrong with the proxy server or the address is incorrect."
Here is my code.
public class Browsermob {
BrowserMobProxy proxy = new BrowserMobProxyServer();
#Test
public void browsermobtest() {
proxy.start(9091);
// get the Selenium proxy object
Proxy seleniumProxy = ClientUtil.createSeleniumProxy(proxy);
// configure it as a desired capability
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability(CapabilityType.PROXY, seleniumProxy);
System.setProperty("webdriver.chrome.driver", "C:/Users/Madis/Documents/chromedriver.exe");
WebDriver driver = new ChromeDriver(capabilities);
// enable more detailed HAR capture, if desired (see CaptureType for the complete list)
proxy.enableHarCaptureTypes(CaptureType.REQUEST_CONTENT, CaptureType.RESPONSE_CONTENT);
// create a new HAR with the label "google.com"
proxy.newHar("http://www.google.com/");
// open google.com
driver.get("https://www.google.ee/#gfe_rd=cr");
driver.findElement(By.cssSelector("#gb_70")).click();
}
#AfterMethod
public void Afterthetest() {
// get the HAR data
Har har = proxy.getHar();
File harFile = new File("C:/Users/Madis/Documents/har.har");
try {
har.writeTo(harFile);
} catch (IOException e) {
e.printStackTrace();
}
}
}
You don't need to specify the sslProxy on the Selenium Proxy object. ClientUtil.createSeleniumProxy does this for you, and in most simple cases it chooses a suitable default value (using InetAddress.getLocalHost(); if that's working for HTTP, it will work for HTTPS as well).
A few things to keep in mind:
You'll receive SSL warnings in the browser unless you either tell the browser to ignore cert errors (on Chrome, use the --ignore-certificate-errors command-line flag), or install the BMP CA in the browser's trust store (for Chrome on Windows, you must install it in the Windows trust store).
Depending on your version of Chrome and OS, you may need to specify an alternate user-data-dir using a command line option. For example, --user-data-dir=/tmp/insecurechrome.
BMP has its own source of trusted certificates (Java trust store + a recent list from Mozilla), so if you're trying to connect to internal websites with certificates issued by a private CA, you need to tell BMP to either trust the private CA or skip certificate validation using .setTrustAllServers(true).
The proxy must be started using .start(...) before calling createSeleniumProxy().
Combining all these things, your code would look something like this:
BrowserMobProxy proxy = new BrowserMobProxyServer();
proxy.setTrustAllServers(true);
proxy.start(9091);
// get the Selenium proxy object
Proxy seleniumProxy = ClientUtil.createSeleniumProxy(proxy);
// NOTE: there is no call to .setSslProxy() here
// configure it as a desired capability
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability(CapabilityType.PROXY, seleniumProxy);
System.setProperty("webdriver.chrome.driver", "C:/Users/Madis/Documents/chromedriver.exe");
ChromeOptions options = new ChromeOptions();
options.addArgument("--ignore-certificate-errors");
// replace 'somedirectory' with a suitable temp dir on your filesystem
options.addArgument("--user-data-dir=somedirectory");
capabilities.setCapability(ChromeOptions.CAPABILITY, options);
WebDriver driver = new ChromeDriver(capabilities);
// [...]
I had this problem. After numerous trials, I got to know we have to add setmitmManager and upstream proxy if you are connected to corporate proxy. It worked for me.
Here is the example code.
BrowserMobProxy proxy = new BrowserMobProxyServer();
proxy.setTrustAllServers(true);
//Add below line if you are under corporate proxy.
proxy.setChainedProxy(new InetSocketAddress("XXX.XXX.com", 8080));
proxy.setMitmManager(ImpersonatingMitmManager.builder().trustAllServers(true).build());
proxy.start(9091);
// get the Selenium proxy object
Proxy seleniumProxy = ClientUtil.createSeleniumProxy(proxy);
// configure it as a desired capability
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability(CapabilityType.PROXY, seleniumProxy);
System.setProperty("webdriver.chrome.driver","C:/Users/Madis/Documents/chromedriver.exe");
WebDriver driver = new ChromeDriver(capabilities);
// your code to start, get har
You're confusing the browser mob proxy object and the selenium proxy object.
Your proxy variable proxy is the actual proxy which your browser will connect to.
Your seleniumProxy variable is an object which represents your browser's proxy settings.
You are telling your browser to use "trustAllSSLCertificates" as the address for your proxy server, which is why you are getting an error. Instead, you should tell browsermob (proxy) to trustAllSSLCertificates, and your sslProxy needs to reference your browsermob proxy.
Start the proxy like so:
public void startProxy() {
proxy = new BrowserMobProxyServer();
proxy.setTrustAllServers(true);
proxy.start(9091);
}
Start the driver like so:
public void startBrowserWithProxy() {
Proxy seleniumProxy = ClientUtil.createSeleniumProxy(proxy);
seleniumProxy.setSslProxy("localhost:" + proxy.getPort());
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability(CapabilityType.PROXY, seleniumProxy);
System.setProperty("webdriver.chrome.driver", "C:/Users/Madis/Documents/chromedriver.exe");
WebDriver driver = new ChromeDriver(capabilities);
}
I managed to get it to work. After adding log4j and debugging the browsermob logs the issue was caused by
Caught an exception on ClientToProxyConnection
java.lang.NoSuchMethodError: com.google.common.net.HostAndPort.fromHost(Ljava/lang/String;)Lcom/google/common/net/HostAndPort;
In order to make it to work I had to add a dependency to my maven project. This fixed this issue and I was able to see the capture the traffic on https sites aswell http sites.
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>20.0</version>
</dependency>
I hade a lot for capabilities, options and etc but it did not work
In my case, I changed exist dependency in pom
<artifactId>browsermob-core-littleproxy</artifactId>
to
<dependency>
<groupId>net.lightbody.bmp</groupId>
<artifactId>browsermob-core</artifactId>
<version>2.1.5</version>
</dependency>
and up "guava" version.
After that everything became good

How to set BrowserMob with WebDriver?

I am trying to intercept the requests made by Webdriver using BrowserMobProxy.
But the below code is not working..It is not able to open the site google.com.
It says the "Internet Explorer cannot open the site"
proxyServer = new ProxyServer(9101);
proxyServer.start();
proxyServer.setCaptureHeaders(true);
proxyServer.setCaptureContent(true);
proxyServer.addRequestInterceptor(new RequestInterceptor() {
#Override
public void process(BrowserMobHttpRequest request, Har har) {
System.out.println("From Process method");
}
});
seleniumProxy = proxy.seleniumProxy();
seleniumProxy.setHttpProxy("localhost:9101");
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability(CapabilityType.PROXY, seleniumProxy);
capabilities.setCapability("ie.setProxyByServer", true);
File file = new File("C:\\path\\IEDriverServer.exe");
System.setProperty("webdriver.ie.driver", file.getAbsolutePath());
driver = new InternetExplorerDriver(capabilities);
driver.get("www.google.com");
I get the below error when trying to access google.com from webdrviver
From Process method
Nov 09, 2014 2:07:58 AM net.lightbody.bmp.proxy.util.Log info
INFO: java.net.UnknownHostException: www.google.com when requesting http://www.google.com/
Browsermob uses xbill DNS instead of regular Java/native DNS resolution, which may not play nice with your VPN. The latest browsermob snapshot allows you to enable native DNS fallback by setting the system property bmp.allowNativeDnsFallback to true:
System.setProperty("bmp.allowNativeDnsFallback", "true");
proxyServer = new ProxyServer(9101);
proxyServer.start();
You can get the latest snapshot at the browsermob github page.

Categories

Resources