lightbody / browsermob-proxy

A free utility to help web developers watch and manipulate network traffic from their AJAX applications.
http://bmp.lightbody.net
Apache License 2.0
2.17k stars 654 forks source link

Browsermob does not work when behind upstream proxy and establishing https/ssl connection #121

Closed mediga closed 8 years ago

mediga commented 9 years ago

I have a very simple scenario of using browser mob behind the corporare proxy. When i try to open http://www.cnn.com things work fine, but if i try to access any secure sites like https://google.com, browsermob fails to get the connection go through.

I have specified the outgoing proxy details and required authentication for successfully making an outgoing connection from behind corporate proxy, as is evident that http://www.cnn.com works fine.

Strangely, this happens when i am at work only. If I am at home and connected to my company network via VPN, everything works fine.

Please help. This issue has become a show stopper for us to further evaluate the usage of Browsermob in the organization

lightbody commented 9 years ago

I need a bit more info to understand your test scenario. I can confirm regular SSL connections on a normal network (not your corporate network) work fine: we have test cases for those and they pass.

Does your corporate network itself require a proxy to work? In other words: are you trying to chain proxies? If so can you tell me how you're configuring that?

mediga commented 9 years ago

Hello Patrick,

For me to make connection to internet from within my corporate network, i need to connect via corporate upstream proxy. Here is the network topology.

(my computer) <<---->> (BrowserMob proxy) <<---->> (Corporate Upstream Proxy) <<--->> (internet sites)

I am configuring the upstream proxy in the code below and passing the configuraton to browsermob.

This configuration works great with http sites, but does not work with https.

I am pasting my test class here.

package com.example.tests.bmp;

import java.io.File; import java.net.URI; import java.net.URL; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map;

import net.lightbody.bmp.core.har.Har; import net.lightbody.bmp.proxy.ProxyServer; import net.lightbody.bmp.proxy.http.BrowserMobHttpRequest; import net.lightbody.bmp.proxy.http.RequestInterceptor;

import org.openqa.selenium.Proxy; import org.openqa.selenium.WebDriver; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.firefox.FirefoxProfile; import org.openqa.selenium.remote.CapabilityType; import org.openqa.selenium.remote.DesiredCapabilities;

public class Test2 {

public static final Map<String, String> hostHeaderSpoofMap;
static {
    hostHeaderSpoofMap = new LinkedHashMap<String, String>();
    hostHeaderSpoofMap.put("www.google.com", "www.google.com");
}

    public static void main(String[] args) {
        //set this to true if need to tunnel through outgoing corporate traffic
        boolean enableOutgoingCorpProxy=true;

        final String authUser = "<username>";
        final String authPassword = "<Password>"; //set network password
        int MOB_PROXY_PORT=8105;       
        String MOB_PROXY_HOST="localhost";

        try{

        String strFilePath = "C:\\testmystuff\\testhar\\";

        ProxyServer mobProxyServer = new ProxyServer(8105);
        Map<String,String> mobProxyServerOptions = new HashMap<String, String>();
        mobProxyServerOptions.put("httpProxy", "<proxyHost>:<proxyPort>");

        try{
            //stop if already running
        mobProxyServer.stop();
        }catch(Exception e){e.printStackTrace();}

        mobProxyServer.start();
         // set corporate outgoing proxy
        if(enableOutgoingCorpProxy){
        mobProxyServer.setOptions(mobProxyServerOptions);
        mobProxyServer.autoBasicAuthorization("AD",authUser, authPassword);
        }

        mobProxyServer.setCaptureHeaders(true);
        mobProxyServer.setCaptureContent(true);

        Proxy mobProxySeleniumClient = new Proxy();
        String mobProxyString = MOB_PROXY_HOST + ":" + MOB_PROXY_PORT;
      //  mobProxy.setHttpProxy(proxyString);//.setSslProxy(proxyString);
        mobProxySeleniumClient.setHttpProxy("");
        mobProxySeleniumClient.setSslProxy(mobProxyString);

        WebDriver driver = createWebDriver(mobProxySeleniumClient);

        String pageUrl="https://www.google.com";
        URL url = new URL(pageUrl); 

        mobProxyServer.addRequestInterceptor(new RequestInterceptor() {
            @Override
            public void process(BrowserMobHttpRequest request, Har har) {
                URI requestURI=request.getMethod().getURI();

                String requestHost=requestURI.getHost();
                if(hostHeaderSpoofMap.containsKey(requestHost)){
                System.out.println("request Intercepted");
                System.out.println("request uri:" + requestURI.toString());

                System.out.println("Host header -Before :" + request.getMethod().getHeaders("Host")[0]);

                //spoof the host header for 
                request.getMethod().setHeader("Host",hostHeaderSpoofMap.get(requestHost) );
                System.out.println("Host header -After>> :" + request.getMethod().getHeaders("Host")[0]);
                System.out.println(">>>>>>");
                System.out.println("");
                }
            }
        });

       mobProxyServer.newHar(pageUrl); 

      driver.get(pageUrl);
       mobProxyServer.clearBlacklist();
       Har har = mobProxyServer.getHar();

       System.out.println("### HAR file generated");
        System.out.println(har.getLog().getEntries());

        har.writeTo(new File(strFilePath+url.getHost()+url.getPath().replace("/", ".")+".har"));
        mobProxyServer.waitForNetworkTrafficToStop(40000, 20000);
        mobProxyServer.stop();
        }catch(Exception e){
            e.printStackTrace();
        }

    }
    private static WebDriver createWebDriver(Proxy proxy){
        // configure it as a desired capability
        DesiredCapabilities capabilities = new DesiredCapabilities();

        FirefoxProfile profile = new FirefoxProfile();
        profile.setAcceptUntrustedCertificates(true);
        profile.setAssumeUntrustedCertificateIssuer(true);       
        profile.setPreference("network.proxy.http", "localhost");
        profile.setPreference("network.proxy.http_port", 8105);
       proxy.setProxyType(Proxy.ProxyType.MANUAL);

      capabilities.setCapability(FirefoxDriver.PROFILE,profile);
      capabilities.setCapability(CapabilityType.PROXY, proxy);     
      capabilities.setCapability(CapabilityType.ACCEPT_SSL_CERTS, true);

        // start the browser up
        WebDriver driver = new FirefoxDriver(capabilities);
        return driver;
    }
}
mediga commented 9 years ago

Hello Patrick, do you have any suggestions on what might be going wrong and if there is workaround?

lightbody commented 9 years ago

Sorry been busy. I'll try to help debug soon.

mediga commented 9 years ago

Hello Patrick, can you provide me suggestion on what to look for? if there is a debug flag that i can turn on to see what is happening in the browser mob code?

mediga commented 9 years ago

want to update this issue with my findings.

I believe the issue i was facing is because of the way java does dns lookup. Java dns lookup for https sites was not going through the upstream corporate web proxy and hence dns lookup resulted in unknownhost exception.

When using a web browser behind a upstream proxy,web browser routes all traffic to upstream web proxy and upstream web proxy does the dns lookup. In case of java, i could not figure out a way to force java to do dns lookup via web proxy.

for now I have a workaround of remphost with its ip address like server.remapHost("www.google.com", "74.125.224.72");

I am going to continue testing this way. If anyone has better idea let know please

jekh commented 9 years ago

Thanks for the update, @mediga. Based on your use case, a couple solutions come to mind:

//Override system DNS setting with Google free DNS server
System.setProperty("sun.net.spi.nameservice.nameservers", "8.8.8.8");
System.setProperty("sun.net.spi.nameservice.provider.1", "dns,sun");

The downside is that you wouldn't be able to resolve internal corporate addresses. It should be possible to configure multiple DNS servers, but I'm not sure how to do it with the JVM implementation.

There's no standard way to determine what the local nameserver or DNS search
path is at runtime from within the JVM.  dnsjava attempts several methods
until one succeeds.

 - The properties 'dns.server' and 'dns.search' (comma delimited lists) are
   checked.  The servers can either be IP addresses or hostnames (which are
   resolved using Java's built in DNS support).
 - The sun.net.dns.ResolverConfiguration class is queried.
 - On Unix, /etc/resolv.conf is parsed.
 - On Windows, ipconfig/winipcfg is called and its output parsed.  This may
   fail for non-English versions on Windows.
 - As a last resort, "localhost" is used as the nameserver, and the search
   path is empty.

You could use one of those listed methods to set dnsjava to use an alternate nameserver, then configure BMP to use dnsjava:

proxy.setHostNameResolver(ClientUtil.createDnsJavaResolver());
mediga commented 9 years ago

thanks @jekh

I tried these options already. from within my corporate firewall/web proxy there is no way to do dns lookup to google dns. The only outgoing connection i can make is a http connection to web proxy and for http sites corp web proxy does the dns lookup. When java does dns lookup it makes a udp call from my machine and this udp call does not go outside the corporate network.

I am experimenting with http api's like whois/statdns which can do a dns lookup for a host and return the ip over an http connection. After the IP is received i use proxy.remaphost to map the domain with the ip adddress.

With this method I got some success and am continuing to test.

Here is the example :

    public static String getIPofDomain(String domainName) throws IOException{
        String ip=null;
        //http://api.statdns.com/facebook.com/a
         String protocol = "http";
            String host = "api.statdns.com";
            String file = "/"+domainName+"/a";

            // create a URL object
            URL url = new URL(protocol, host, file);

            java.net.Proxy proxy = new java.net.Proxy(java.net.Proxy.Type.HTTP, new java.net.InetSocketAddress("127.0.0.1", 8888));

            // create the connection object
            HttpURLConnection conn = (HttpURLConnection) url.openConnection(proxy);

            conn.connect();

            // create a stream reader
            BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String inputLine;

            StringBuffer sb = new StringBuffer();
            // read contents and print on std out
            while ((inputLine = in.readLine()) != null) {
                sb.append(inputLine);
                System.out.println("line :" +inputLine);
            }

            Gson gson = new Gson();
            JsonObject jsonObject = gson.fromJson( sb.toString(), JsonObject.class);

          int arraySize=  jsonObject.getAsJsonArray("answer").getAsJsonArray().size();
          for(int i=0;i<arraySize;i++){
            ip=jsonObject.getAsJsonArray("answer").getAsJsonArray().get(i).getAsJsonObject().get("rdata").getAsString();
           System.out.println("ip :"+ ip);
          }
            //jsonObject.get(fieldName); // returns a JsonElement for that name

        return ip;

    }
jekh commented 9 years ago

Wow, that is a really clever solution to your problem, @mediga. You could actually implement the HTTP-based lookup as an AdvancedHostResolver and tell BMP to use your code instead of dnsjava or the JVM, and thus eliminate the need to remap hosts.

If you subclass net.lightbody.bmp.proxy.dns.BasicHostResolver, you can implement the Collection<InetAddress> resolve(String host) method with the code you pasted above. Then you can have BMP use your resolver by using proxy.setHostNameResolver(...your resolver instance...). By default that would result in a new HTTP call for every address, so you may want to add a simple ConcurrentHashMap or guava Cache to your method, to speed things up. But that should work and will be much cleaner than remapping every host.

mediga commented 9 years ago

Thanks @jekh , good idea.

Also I started playing around with httpclient 4.4.1. What i find interesting is making a http/https call from behind corporate proxy using httpclient does not lead to dns lookup for https connections, unlike the way it works in core Java. but rather the https call goes to corporate proxy. Is it possible to swap out the current implementation of https connection mechanism in BMP with httpclient api? If so please guide, i will give it a try.

Example here: public static void main(String[] args)throws Exception { CloseableHttpClient httpclient = HttpClients.createDefault(); try { HttpHost target = new HttpHost("localhost", 443, "https"); HttpHost proxy = new HttpHost("127.0.0.1", 8080, "http");

        RequestConfig config = RequestConfig.custom()
                .setProxy(proxy)
                .build();
        HttpGet request = new HttpGet("/");
        request.setConfig(config);

        System.out.println("Executing request " + request.getRequestLine() + " to " + target + " via " + proxy);

        CloseableHttpResponse response = httpclient.execute(target, request);
        try {
            System.out.println("----------------------------------------");
            System.out.println(response.getStatusLine());
            EntityUtils.consume(response.getEntity());
        } finally {
            response.close();
        }
    } finally {
        httpclient.close();
    }
}
jekh commented 9 years ago

In your example code, you're setting the http proxy but not the https proxy, so HttpClient may be using your default proxy settings (i.e. corporate proxy) for HTTPS. But no matter what, you should be able to configure BMP to access your network in exactly the way you want it to. What would you like to do for HTTP and HTTPS requests: have BMP route requests through the corporate proxy, or have BMP attempt direct connections?

mediga commented 9 years ago

This is what will work in my corporate network.

browser <--> bmp <--> charles proxy for ntlm authentication against corp proxy <--> corporate web http proxy does dns lookup <--> internet/intranet sites

only corporate web proxy does the dns lookup for internet sites and intranet sites.

I want BMP/java to route all the http and https requests to corporate proxy and not do a dns lookup by itself.

mediga commented 9 years ago

Hello @jekh , please guide on how should i approach writing the code to achieve the above requirement i have.

jekh commented 9 years ago

I have some good news: it looks like you want to set up BMP with a chained proxy. There is a method in BrowserMobProxy called setChainedProxy(InetSocketAddress chainedProxyAddress) that will allow you to route traffic through an upstream proxy. In your case, you would want to set the chained proxy to the address of the Charles Proxy instance.

There is some bad news though: BrowserMob Proxy cannot intercept HTTPS traffic with a chained proxy. This is due to a limitation in LittleProxy. (I am planning to help address this limitation in LP at some point, but it will not be for at least 1-2 months.) This means you will be able to capture HTTP traffic in a HAR, but not HTTPS.

Alternatively, if you are able to bypass your corporate proxy and charles proxy entirely, you can capture HTTPS traffic in the har, but you will need to find a way to work around the DNS limitations of your corporate network. It sounds like the DNS web service approach that you've implemented might be a good medium-term work-around until LittleProxy can be enhanced with chained proxy MITM support.

mediga commented 9 years ago

@jekh any way to disable dns lookup by bmp and is bmp designed to work without doing dns lookup? Specially for my corporate network scenario where the only way of doing dns lookup is by upstream corporate proxy.

jekh commented 9 years ago

@mediga - when the LittleProxy implementation of BMP is configured with an upstream proxy, there shouldn't be any DNS lookups. If there are, that would be a defect. Do you have a test case or other reproducible example of the LittleProxy-based implementation of BMP causing a DNS lookup when there is a chained proxy? Then I could take a deeper look and fix the defect.

The answer to your first question is yes, you can disable DNS lookups. You could subclass BasicHostResolver and override resolve() to always return an empty list. However, this probably won't give you the results you're looking for, since the proxy would never be able to connect to any non-IP address URLs.

jekh commented 8 years ago

@mediga - BMP now works with MITM+Chained Proxies, as of the latest beta-4 release. So if you configure BMP to use your corporate proxy, it should "just work".

jekh commented 8 years ago

Since there's been no update, I'll close this issue.

kandiahsureshkumar commented 6 years ago

Anyone has made BMP work behind the corporate proxy, I am facing a similar issue. Can you please advise ?

TTJudy commented 5 years ago

I am also in a (my computer) <<---->> (BrowserMob proxy) <<---->> (Corporate Upstream Proxy) <<--->> (internet sites) setting. The chain proxy approach works for me. Thanks everybody for the contribution!

kheerthi commented 5 years ago

@TTJudy Can you provide a sample implementation for refernce

sridharrajendran1 commented 4 years ago

But the given URL is not opening. Can someone help me with this?

Error com.google.common.util.concurrent.ExecutionError: java.lang.NoSuchFieldError: id_tc26_signwithdigest_gost_3410_12_256 at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2216) at com.google.common.cache.LocalCache.get(LocalCache.java:4147) at com.google.common.cache.LocalCache$LocalManualCache.get(LocalCache.java:5053) at net.lightbody.bmp.mitm.manager.ImpersonatingMitmManager.getHostnameImpersonatingSslContext(ImpersonatingMitmManager.java:242) at net.lightbody.bmp.mitm.manager.ImpersonatingMitmManager.clientSslEngineFor(ImpersonatingMitmManager.java:223) at org.littleshoot.proxy.impl.ProxyToServerConnection$3.execute(ProxyToServerConnection.java:724) at org.littleshoot.proxy.impl.ConnectionFlow.doProcessCurrentStep(ConnectionFlow.java:140) at org.littleshoot.proxy.impl.ConnectionFlow.processCurrentStep(ConnectionFlow.java:128) at org.littleshoot.proxy.impl.ConnectionFlow.advance(ConnectionFlow.java:90) at org.littleshoot.proxy.impl.ConnectionFlowStep.onSuccess(ConnectionFlowStep.java:83) at org.littleshoot.proxy.impl.ConnectionFlow$2.operationComplete(ConnectionFlow.java:149) at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:507) at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:481) at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:420) at io.netty.util.concurrent.DefaultPromise.addListener(DefaultPromise.java:163) at io.netty.channel.DefaultChannelPromise.addListener(DefaultChannelPromise.java:93) at io.netty.channel.DefaultChannelPromise.addListener(DefaultChannelPromise.java:28) at org.littleshoot.proxy.impl.ConnectionFlow.doProcessCurrentStep(ConnectionFlow.java:140) at org.littleshoot.proxy.impl.ConnectionFlow.access$000(ConnectionFlow.java:14) at org.littleshoot.proxy.impl.ConnectionFlow$1.run(ConnectionFlow.java:124) at io.netty.util.concurrent.PromiseTask$RunnableAdapter.call(PromiseTask.java:38) at io.netty.util.concurrent.PromiseTask.run(PromiseTask.java:73) at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:399) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:464) at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:131) at java.lang.Thread.run(Thread.java:748) Caused by: java.lang.NoSuchFieldError: id_tc26_signwithdigest_gost_3410_12_256 at org.bouncycastle.operator.jcajce.OperatorHelper.(Unknown Source) at org.bouncycastle.operator.jcajce.JcaContentSignerBuilder.(Unknown Source) at net.lightbody.bmp.mitm.tools.BouncyCastleSecurityProviderTool.getCertificateSigner(BouncyCastleSecurityProviderTool.java:333) at net.lightbody.bmp.mitm.tools.BouncyCastleSecurityProviderTool.createServerCertificate(BouncyCastleSecurityProviderTool.java:99) at net.lightbody.bmp.mitm.tools.DefaultSecurityProviderTool.createServerCertificate(DefaultSecurityProviderTool.java:43) at net.lightbody.bmp.mitm.manager.ImpersonatingMitmManager.createImpersonatingSslContext(ImpersonatingMitmManager.java:308) at net.lightbody.bmp.mitm.manager.ImpersonatingMitmManager.createImpersonatingSslContext(ImpersonatingMitmManager.java:271) at net.lightbody.bmp.mitm.manager.ImpersonatingMitmManager.access$3(ImpersonatingMitmManager.java:264) at net.lightbody.bmp.mitm.manager.ImpersonatingMitmManager$3.call(ImpersonatingMitmManager.java:245) at net.lightbody.bmp.mitm.manager.ImpersonatingMitmManager$3.call(ImpersonatingMitmManager.java:1) at com.google.common.cache.LocalCache$LocalManualCache$1.load(LocalCache.java:5058) at com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3708) at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2416) at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2299) at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2212) ... 25 more WARN DefaultPromise: An exception was thrown by org.littleshoot.proxy.impl.ConnectionFlow$2.operationComplete() com.google.common.util.concurrent.ExecutionError: java.lang.NoClassDefFoundError: Could not initialize class org.bouncycastle.operator.jcajce.OperatorHelper at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2216) at com.google.common.cache.LocalCache.get(LocalCache.java:4147) at com.google.common.cache.LocalCache$LocalManualCache.get(LocalCache.java:5053) at net.lightbody.bmp.mitm.manager.ImpersonatingMitmManager.getHostnameImpersonatingSslContext(ImpersonatingMitmManager.java:242) at net.lightbody.bmp.mitm.manager.ImpersonatingMitmManager.clientSslEngineFor(ImpersonatingMitmManager.java:223) at org.littleshoot.proxy.impl.ProxyToServerConnection$3.execute(ProxyToServerConnection.java:724) at org.littleshoot.proxy.impl.ConnectionFlow.doProcessCurrentStep(ConnectionFlow.java:140) at org.littleshoot.proxy.impl.ConnectionFlow.processCurrentStep(ConnectionFlow.java:128) at org.littleshoot.proxy.impl.ConnectionFlow.advance(ConnectionFlow.java:90) at org.littleshoot.proxy.impl.ConnectionFlowStep.onSuccess(ConnectionFlowStep.java:83) at org.littleshoot.proxy.impl.ConnectionFlow$2.operationComplete(ConnectionFlow.java:149) at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:507) at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:481) at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:420) at io.netty.util.concurrent.DefaultPromise.addListener(DefaultPromise.java:163) at io.netty.channel.DefaultChannelPromise.addListener(DefaultChannelPromise.java:93) at io.netty.channel.DefaultChannelPromise.addListener(DefaultChannelPromise.java:28) at org.littleshoot.proxy.impl.ConnectionFlow.doProcessCurrentStep(ConnectionFlow.java:140) at org.littleshoot.proxy.impl.ConnectionFlow.access$000(ConnectionFlow.java:14) at org.littleshoot.proxy.impl.ConnectionFlow$1.run(ConnectionFlow.java:124) at io.netty.util.concurrent.PromiseTask$RunnableAdapter.call(PromiseTask.java:38) at io.netty.util.concurrent.PromiseTask.run(PromiseTask.java:73) at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:399) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:464) at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:131) at java.lang.Thread.run(Thread.java:748) Caused by: java.lang.NoClassDefFoundError: Could not initialize class org.bouncycastle.operator.jcajce.OperatorHelper at org.bouncycastle.operator.jcajce.JcaContentSignerBuilder.(Unknown Source) at net.lightbody.bmp.mitm.tools.BouncyCastleSecurityProviderTool.getCertificateSigner(BouncyCastleSecurityProviderTool.java:333) at net.lightbody.bmp.mitm.tools.BouncyCastleSecurityProviderTool.createServerCertificate(BouncyCastleSecurityProviderTool.java:99) at net.lightbody.bmp.mitm.tools.DefaultSecurityProviderTool.createServerCertificate(DefaultSecurityProviderTool.java:43) at net.lightbody.bmp.mitm.manager.ImpersonatingMitmManager.createImpersonatingSslContext(ImpersonatingMitmManager.java:308) at net.lightbody.bmp.mitm.manager.ImpersonatingMitmManager.createImpersonatingSslContext(ImpersonatingMitmManager.java:271) at net.lightbody.bmp.mitm.manager.ImpersonatingMitmManager.access$3(ImpersonatingMitmManager.java:264) at net.lightbody.bmp.mitm.manager.ImpersonatingMitmManager$3.call(ImpersonatingMitmManager.java:245) at net.lightbody.bmp.mitm.manager.ImpersonatingMitmManager$3.call(ImpersonatingMitmManager.java:1) at com.google.common.cache.LocalCache$LocalManualCache$1.load(LocalCache.java:5058) at com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3708) at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2416) at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2299) at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2212) ... 25 more

Code

package makemyhar;

import java.net.Inet4Address; import java.net.UnknownHostException; import java.util.Arrays; import java.util.List;

import org.openqa.selenium.Proxy; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.remote.CapabilityType; import org.openqa.selenium.remote.DesiredCapabilities; import org.testng.Assert; import org.testng.annotations.Test;

import net.lightbody.bmp.BrowserMobProxy; import net.lightbody.bmp.BrowserMobProxyServer; import net.lightbody.bmp.client.ClientUtil; import net.lightbody.bmp.core.har.HarEntry;

public class test { @Test public test() throws Exception { System.setProperty("webdriver.chrome.driver", "/Users/srajendran/Desktop/chromedriver"); DesiredCapabilities capabilities = new DesiredCapabilities(); BrowserMobProxy proxy = getProxyServer(); // getting browsermob proxy Proxy seleniumProxy = getSeleniumProxy(proxy); capabilities.setCapability(CapabilityType.PROXY, seleniumProxy); capabilities.setCapability("chrome.switches", Arrays.asList("--ignore-certificate-errors")); WebDriver driver = new ChromeDriver(capabilities); proxy.newHar("test.har"); // creating new HAR driver.get("http://www.google.com"); List entries = proxy.getHar().getLog().getEntries(); for (HarEntry entry : entries) { System.out.println(entry.getRequest().getUrl()); } proxy.stop(); driver.close(); }

public Proxy getSeleniumProxy(BrowserMobProxy proxyServer) {
    Proxy seleniumProxy = ClientUtil.createSeleniumProxy(proxyServer);
    try {
        String hostIp = Inet4Address.getLocalHost().getHostAddress();
        seleniumProxy.setHttpProxy(hostIp + ":" + proxyServer.getPort());
        seleniumProxy.setSslProxy(hostIp + ":" + proxyServer.getPort());
    } catch (UnknownHostException e) {
        e.printStackTrace();
        Assert.fail("invalid Host Address");
    }
    return seleniumProxy;
}

public BrowserMobProxy getProxyServer() {
    BrowserMobProxy proxy = new BrowserMobProxyServer();
    proxy.setTrustAllServers(true);
    proxy.start();
    return proxy;
}

}