Search code examples
javascriptgoogle-chrome-extensionproxy

Add or remove proxy based on url in chrome extension


I want to proxy only certain domains through my chrome extension but i need to do some checks on current url to decide if i need to proxy.

chrome.webRequest.onBeforeRequest.addListener(function(d){
    chrome.proxy.settings.set({value: getProxyConfig(d.url), scope: 'regular'},function() {});

},{urls:[
    "http://*/*",
    "https://*/*"]},
["blocking"]);

The function getProxyConfig(d.url) is a simple function that will return the appropriate ProxyConfig object(mode is direct or fixed_servers) based on the url. The function doesn't make any external calls and just fetch a list of domains from local storage and does comparison.

What is the problem ?

Chrome try to proxy some urls that should not have been proxied leading to a ERR_TUNNEL_CONNECTION_FAILED because the proxy will allow only specific domains to be proxied.If i log getProxyConfig(d.url)output to the console for urls that are falling i see the mode as direct as expected.Note: An html page may contain both links that must/must not be proxied.

chrome.proxy.settings.set is asynchronous so i am thinking that maybe chrome.webRequest.onBeforeRequest is done executing before chrome.proxy.settings.set


Solution

  • You cannot modify proxy automatically while a request is being made. You have to Create a custom PAC script, where the script decides whether to proxy a URL or not:

    const config = {
      mode: "pac_script",
      pacScript: {
        data: "function FindProxyForURL(url, host) {\n" +
            "  if (host == 'foobar.com')\n" +
            "    return 'PROXY blackhole:80';\n" +
            "  return 'DIRECT';\n" +
            "}"
      }
    }
    chrome.proxy.settings.set(
      {value: config, scope: 'regular'},
      function() {}
    )
    

    Regarding, chrome.webRequest.onBeforeRequest , this is called AFTER the proxy been set, hence why you will get a isProxy attribute there.