【问题标题】:How to send an http RequestHeader using Selenium 2?如何使用 Selenium 2 发送 http RequestHeader?
【发布时间】:2020-08-11 18:37:06
【问题描述】:

我需要发送一个带有一些修改过的标头的 Http 请求。经过几个小时试图为 Selenium 2 找到与 Selenium RC Selenium.addCustomRequestHeader 等效的方法后,我放弃并使用 JavaScript 来实现我的目的。我原以为这会容易得多!

有人知道更好的方法吗?

这就是我所做的:

javascript.js

var test = {
    "sendHttpHeaders": function(dst, header1Name, header1Val, header2Name, header2Val) {
        var http = new XMLHttpRequest();

        http.open("GET", dst, "false");
        http.setRequestHeader(header1Name,header1Val);
        http.setRequestHeader(header2Name,header2Val);
        http.send(null);
    }
}

MyTest.java

// ...

@Test
public void testFirstLogin() throws Exception {
    WebDriver driver = new FirefoxDriver();

    String url = System.getProperty(Constants.URL_PROPERTY_NAME);
    driver.get(url);

    // Using javascript to send http headers
    String scriptResource = this.getClass().getPackage().getName()
        .replace(".", "/") + "/javascript.js";

    String script = getFromResource(scriptResource)
            + "test.sendHttpHeaders(\"" + url + "\", \"" + h1Name
            + "\", \"" + h1Val + "\", \"" + h2Name + "\", \"" + h2Val + "\");";
    LOG.debug("script: " + script);

    ((JavascriptExecutor)driver).executeScript(loginScript);

    // ...
}

// I don't like mixing js with my code. I've written this utility method to get
// the js from the classpath
/**
 * @param src name of a resource that must be available from the classpath
 * @return new string with the contents of the resource
 * @throws IOException if resource not found
 */
public static String getFromResource(String src) throws IOException {
    InputStream is = Thread.currentThread().getContextClassLoader().
            getResourceAsStream(src);
    if (null == is) {
        throw new IOException("Resource " + src + " not found.");
    }
    InputStreamReader isr = new InputStreamReader(is);
    BufferedReader br = new BufferedReader(isr);
    StringWriter sw = new StringWriter();
    PrintWriter pw = new PrintWriter(sw);

    String line = null;
    int nLines = 0;
    while (null != (line = br.readLine())) {
        pw.println(line);
        nLines ++;
    }
    LOG.info("Resource " + src + " successfully copied into String (" + nLines + " lines copied).");
    return sw.toString();
}

// ...

注意:为了简化这篇文章,我编辑了我的原始代码。希望我没有引入任何错误!

【问题讨论】:

    标签: selenium selenium-webdriver selenium-rc


    【解决方案1】:

    很遗憾,您无法使用 Selenium 2 更改标题。这是团队部分的一个有意识的决定,因为我们正在尝试创建一个浏览器自动化框架来模拟用户可以做什么。

    【讨论】:

    • 谢谢!我明白...所以似乎 JavaScript 是执行此操作的适当(并且可能是唯一)方法...无论如何,在 Firefox 中使用插件仍然可以做到这一点(例如参见modify headers
    • 自动化测试仪;让您的测试工具模拟不同的状态而不实际创建它们怎么样?例如,通过在标头上发送凭据来验证请求,或模拟不同的源 URL - 我的开发团队实际上被阻止了,因为源 URL 检测是我们工作流程的重要组成部分,并且有可能在没有实际合理的情况下模拟它显然,可用的 URL 数量并不是 Selenium 2 团队认为我可能想做的事情。你知道我该如何请求改变团队的想法吗?
    【解决方案2】:

    根据 Alberto 的回答,如果您正在使用 Firefox 配置文件,您可以添加修改标头:

    FirefoxDriver createFirefoxDriver() throws URISyntaxException, IOException {
        FirefoxProfile profile = new FirefoxProfile();
        URL url = this.getClass().getResource("/modify_headers-0.7.1.1-fx.xpi");
        File modifyHeaders = modifyHeaders = new File(url.toURI());
    
        profile.setEnableNativeEvents(false);
        profile.addExtension(modifyHeaders);
    
        profile.setPreference("modifyheaders.headers.count", 1);
        profile.setPreference("modifyheaders.headers.action0", "Add");
        profile.setPreference("modifyheaders.headers.name0", SOME_HEADER);
        profile.setPreference("modifyheaders.headers.value0", "true");
        profile.setPreference("modifyheaders.headers.enabled0", true);
        profile.setPreference("modifyheaders.config.active", true);
        profile.setPreference("modifyheaders.config.alwaysOn", true);
    
        DesiredCapabilities capabilities = new DesiredCapabilities();
        capabilities.setBrowserName("firefox");
        capabilities.setPlatform(org.openqa.selenium.Platform.ANY);
        capabilities.setCapability(FirefoxDriver.PROFILE, profile);
        return new FirefoxDriver(capabilities);
    }
    

    【讨论】:

    • +1 不错的解决方法!不幸的是,仅适用于使用 Firefox 并且想要绑定 modify_headers 插件的情况。感觉正确答案还是AutomatedTester's answer
    【解决方案3】:

    我在 2 周前遇到了同样的问题。我尝试了 Carl 建议的方法,但实现这项任务似乎有点“开销”。

    最后,我使用了 fiddlerCore 库,以便在我的代码中托管代理服务器,并仅使用 Web 驱动程序 2 的内置代理功能。在我看来,它工作得很好,而且更加直观/稳定。此外,它适用于所有浏览器,并且您不依赖于需要在代码存储库中维护的二进制文件。

    这里是用 C# 为 Chrome 制作的示例(Firefox 和 IE 非常相似)

    // Check if the server is already running
    if (!FiddlerApplication.IsStarted())
    {
        // Append your delegate to the BeforeRequest event
        FiddlerApplication.BeforeRequest += delegate(Fiddler.Session oS)
        {
            // Make the modifications needed - change header, logging, ...
            oS.oRequest["SM_USER"] = SeleniumSettings.TestUser;
        };
        // Startup the proxy server
        FiddlerApplication.Startup(SeleniumSettings.ProxyPort, false, false);
    }
    
    // Create the proxy setting for the browser
    var proxy = new Proxy();
    proxy.HttpProxy = string.Format("localhost:{0}", SeleniumSettings.ProxyPort);
    
    // Create ChromeOptions object and add the setting
    var chromeOptions = new ChromeOptions();
    chromeOptions.Proxy = proxy;
    
    // Create the driver
    var Driver = new ChromeDriver(path, chromeOptions);
    
    // Afterwards shutdown the proxy server if it's running
    if (FiddlerApplication.IsStarted())
    {
        FiddlerApplication.Shutdown();
    }
    

    【讨论】:

      【解决方案4】:

      (此示例使用 Chrome 完成)

      这就是我解决问题的方法。希望对有类似设置的人有所帮助。

      1. 将 ModHeader 扩展添加到 chrome 浏览器

      如何下​​载 Modheader?链接

      ChromeOptions options = new ChromeOptions();
      options.addExtensions(new File(C://Downloads//modheader//modheader.crx));
      
      // Set the Desired capabilities 
      DesiredCapabilities capabilities = new DesiredCapabilities();
      capabilities.setCapability(ChromeOptions.CAPABILITY, options);
      
      // Instantiate the chrome driver with capabilities
      WebDriver driver = new RemoteWebDriver(new URL(YOUR_HUB_URL), options);
      
      1. 转到浏览器扩展并捕获 ModHeader 的本地存储上下文 ID

      1. 导航到 ModHeader 的 URL 以设置本地存储上下文

      .

      // set the context on the extension so the localStorage can be accessed
      driver.get("chrome-extension://idgpnmonknjnojddfkpgkljpfnnfcklj/_generated_background_page.html");
      
      Where `idgpnmonknjnojddfkpgkljpfnnfcklj` is the value captured from the Step# 2
      
      1. 现在使用Javascript将标头添加到请求中

      .

         ((Javascript)driver).executeScript(
               "localStorage.setItem('profiles', JSON.stringify([{  title: 'Selenium', hideComment: true, appendMode: '', 
                   headers: [                        
                     {enabled: true, name: 'token-1', value: 'value-1', comment: ''},
                     {enabled: true, name: 'token-2', value: 'value-2', comment: ''}
                   ],                          
                   respHeaders: [],
                   filters: []
                }]));");
      

      其中token-1value-1token-2value-2 是要添加的请求标头和值。

      1. 现在导航到所需的网络应用程序。

        driver.get("your-desired-website");

      【讨论】:

        猜你喜欢
        • 2016-07-25
        • 1970-01-01
        • 2020-01-06
        • 2012-05-07
        • 2020-10-31
        • 1970-01-01
        • 2021-12-29
        • 2016-05-12
        • 1970-01-01
        相关资源
        最近更新 更多