0

I'm trying to use a proxy server to launch the Selenium Chrome driver. The only solution so far that I found was to use a sort of plugin for Chrome to authenticate, but it's not very reliable, so I was wondering if there is any other option.

Here is what I use now

    manifest_json = """
    {
    "version": "1.0.0",
    "manifest_version": 2,
    "name": "Chrome Proxy",
    "permissions": [
    "proxy",
    "tabs",
    "unlimitedStorage",
    "storage",
    "<all_urls>",
    "webRequest",
    "webRequestBlocking"
    ],
    "background": {
    "scripts": ["background.js"]
    },
    "minimum_chrome_version":"22.0.0"
    }
    """

background_js = """
    var config = {
    mode: "fixed_servers",
    rules: {
    singleProxy: {
    scheme: "http",
    host: "",
    port: parseInt(6060)
    },
    bypassList: ["foobar.com"]
    }
    };

    chrome.proxy.settings.set({value: config, scope: "regular"}, function() {});

    function callbackFn(details) {
    return {
    authCredentials: {
    username: "",
    password: ""
    }
    };
    }

    chrome.webRequest.onAuthRequired.addListener(
    callbackFn,
    {urls: ["<all_urls>"]},
    ['blocking']
    );
    """


pluginfile = 'proxy_auth_plugin.zip'

with zipfile.ZipFile(pluginfile, 'w') as zp:
    zp.writestr("manifest.json", manifest_json)
    zp.writestr("background.js", background_js)

co = Options()
co.add_argument("--start-maximized")
co.add_extension(pluginfile)


driver = webdriver.Chrome(executable_path='/usr/local/bin/chromedriver')
Christian
  • 25
  • 1
  • 7

1 Answers1

0

I don't think plugins are a very good solution, certainly not when there are pure HTTP solutions that work the same across all browsers, versions, and operating systems.

You could use this Python wrapper for Browsermob, which is a very well-known standalone or embedded proxy server written in Java.

The code shows how the headers() Python method can be used to add headers, without the need to POST to the REST API. The tests have some examples of it in use, e.g.:

self.client = Client("localhost:9090")
self.client.headers({'User-Agent': 'rubber ducks floating in a row'})
self.client.headers({'Authorization': 'Basic dXNlcjpwYXNz'})  # User 'user', password 'pass'

Update:

Just to clarify how the WebDriver and the proxy fit together:

  • Start your proxy server first, and wait until it's ready. You can do that externally and pass host:port to WebDriver, or start it embedded in your application then pass WebDriver a proxy object.
  • This example demonstrates the second approach, using Firefox profiles and Chrome options.
  • Alternatively, start the proxy embedded, use it to obtain a Proxy object, which represents a Selenium proxy server, then add it to your DesiredCapabilities object, and create your driver that way, as per this example.

From that point on, the proxy-listening is automatic, and you can start to create your HAR files.


Alternatively, you could see this answer for a custom Python proxy server using Twisted.

I have a longer answer about Selenium proxies in Python here.

Community
  • 1
  • 1
Andrew Regan
  • 5,087
  • 6
  • 37
  • 73
  • Sorry, I missed out the link. Fixed in the answer now. https://github.com/AutomatedTester/browsermob-proxy-py – Andrew Regan Mar 15 '16 at 00:45
  • thx again. So this is the code for Chrome for example from `browsermobproxy import Server server = Server("path/to/browsermob-proxy") server.start() proxy = server.create_proxy() chrome_options = webdriver.ChromeOptions() chrome_options.add_argument("--proxy-server={0}".format(proxy.proxy)) browser = webdriver.Chrome(chrome_options = chrome_options)` – Christian Mar 15 '16 at 00:56
  • does it also let you use a username and password? Thanks – Christian Mar 15 '16 at 01:15
  • Only time for a quick answer, but if you mean using a user/pass for basic authentication dialogs, yes. I cover that here: http://stackoverflow.com/q/35004026/954442 – Andrew Regan Mar 15 '16 at 01:21
  • thanks. Trying to figure out now how to implement that POST call in Python. – Christian Mar 15 '16 at 20:28
  • Actually you don't need to use the REST API at all. I've updated my answer with an example of the Python `headers()` method. – Andrew Regan Mar 15 '16 at 23:42
  • thank you once again. So basically now I just need to figure out how to pass basic auth - server, pass and username - through headers. – Christian Mar 16 '16 at 01:07
  • One more edit ^^ Just Base64 ':' , prefix with 'Basic '. See: https://en.wikipedia.org/wiki/Basic_access_authentication#Client_side, see also: https://www.base64encode.org/ – Andrew Regan Mar 16 '16 at 01:13