在selenium中设置请求标头

时间:2013-03-26 18:51:10

标签: webdriver capybara selenium-webdriver

我正在尝试将请求标头“Referer”设置为欺骗来自其他网站的请求。我们需要使用特定引用者的能力测试,它将特定表单返回给用户,否则会给出替代表单。

我可以通过以下方式在恶作剧中做到这一点:

page.driver.headers = {"Referer" => referer_string}

但我找不到selemium驱动程序的等效功能。

如何在capybara selenium驱动程序中设置请求标头?

10 个答案:

答案 0 :(得分:31)

Webdriver不包含API来执行此操作。有关详细信息,请参阅issue 141 from Selenium tracker。该问题的标题说它是关于响应标头但是决定Selenium在此问题的范围内不包含请求标头的API。有关添加API以设置请求标头的几个问题已标记为重复:firstsecondthird

我可以提出以下几种可能性:

  1. 使用其他驱动程序/库而不是selenium
  2. 编写一个特定于浏览器的插件(或查找现有的插件),允许您为请求添加标题。
  3. 使用browsermob-proxy或其他代理。
  4. 在大多数情况下,我会选择选项3。这并不难。

    请注意Ghostdriver has an API for it,但其他驱动程序不支持。

答案 1 :(得分:8)

我有同样的问题。我解决了下载modify-headers firefox附加组件并使用selenium激活它。

python中的代码如下

li = [1,2,3,4]
max_time = [0,0,0,0]
li.sort()

if 2 in li:
    pos2 = li.index(2)
    max_time[0] = 2
    while(pos2<4 and li.index(2) != 3):
        if(li[pos2+1] == 3):
            max_time[1] = li[pos2+1]
            pos2 += 1
            continue
        elif(li[pos2+1] == 4 or li[pos2+1] == 5):
            max_time[2] = li[pos2+1]
            pos2 += 1
            continue
        else:
            max_time[3] = li[pos2+1]
            pos2 += 1
            continue 

答案 2 :(得分:8)

对于那些使用Python的人,您可以考虑使用Selenium Wire,它可以设置请求标头,并为您提供检查请求和响应的功能。

from seleniumwire import webdriver  # Import from seleniumwire

# Create a new instance of the Firefox driver
driver = webdriver.Firefox()

driver.header_overrides = {
    'Referer': 'referer_string',
}

# All subsequent requests will now contain the Referer

答案 3 :(得分:5)

今天有同样的问题,除了我需要为每个测试设置不同的引用。我最终使用中间件和类将标头传递给它。以为我会分享(或者可能有更清洁的解决方案?):

lib/request_headers.rb:

class CustomHeadersHelper
  cattr_accessor :headers
end

class RequestHeaders
  def initialize(app, helper = nil)
    @app, @helper = app, helper
  end

  def call(env)
    if @helper
      headers = @helper.headers

      if headers.is_a?(Hash)
        headers.each do |k,v|
          env["HTTP_#{k.upcase.gsub("-", "_")}"] = v
        end
      end
    end

    @app.call(env)
  end
end

config/initializers/middleware.rb

require 'request_headers'

if %w(test cucumber).include?(Rails.env)
  Rails.application.config.middleware.insert_before Rack::Lock, "RequestHeaders", CustomHeadersHelper
end

spec/support/capybara_headers.rb

require 'request_headers'

module CapybaraHeaderHelpers
  shared_context "navigating within the site" do
    before(:each) { add_headers("Referer" => Capybara.app_host + "/") }
  end

  def add_headers(custom_headers)
    if Capybara.current_driver == :rack_test
      custom_headers.each do |name, value|
        page.driver.browser.header(name, value)
      end
    else
      CustomHeadersHelper.headers = custom_headers
    end
  end
end

spec/spec_helper.rb

...
config.include CapybaraHeaderHelpers

然后我可以在任何需要的地方包含共享上下文,或者在另一个before块中传递不同的头。我没有用Selenium和RackTest以外的任何东西测试它,但它应该是透明的,因为在请求实际到达应用程序之前完成了头文件注入。

答案 4 :(得分:1)

如果您使用HtmlUnitDriver,则可以通过修改WebClient来设置请求标头,如下所示:

final case class Header(name: String, value: String)

final class HtmlUnitDriverWithHeaders(headers: Seq[Header]) extends HtmlUnitDriver {
  super.modifyWebClient {
    val client = super.getWebClient
    headers.foreach(h => client.addRequestHeader(h.name, h.value))
    client
  }
}

然后,标题将出现在Web浏览器发出的所有请求中。

答案 5 :(得分:1)

检查一下: chrome_options = Options()

chrome_options.add_argument('--headless')
chrome_options.add_argument('user-agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36"')

问题解决了!

答案 6 :(得分:1)

使用上面已经讨论的解决方案,最可靠的解决方案是使用Browsermob-Proxy

但是在使用远程网格计算机时,Browsermob-proxy并没有真正的帮助。

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

  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

Capture ID from ModHeader

  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
  2. 将标头添加到请求中

   ((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. 现在导航到所需的Web应用程序。

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

答案 7 :(得分:0)

你可以使用PhantomJSDriver。

PhantomJSDriver pd = ((PhantomJSDriver) ((WebDriverFacade) getDriver()).getProxiedDriver());
pd.executePhantomJS(
            "this.onResourceRequested = function(request, net) {" +
            "   net.setHeader('header-name', 'header-value')" +
            "};");

使用请求对象,您也可以进行过滤,这样就不会为每个请求设置标头。

答案 8 :(得分:0)

我想让RSpec / Ruby稍微苗条一些,以便自定义代码只能放在一个地方。这是我的解决方案:

/spec/support/selenium.rb
...
RSpec.configure do |config|
  config.after(:suite) do
    $custom_headers = nil
  end
end

module RequestWithExtraHeaders
  def headers
    $custom_headers.each do |key, value|
      self.set_header "HTTP_#{key}", value
    end if $custom_headers

    super
  end
end
class ActionDispatch::Request
  prepend RequestWithExtraHeaders
end

然后在我的规格中:

/specs/features/something_spec.rb
...
$custom_headers = {"Referer" => referer_string}

答案 9 :(得分:0)

如果您正在使用 javacsript 并且只想在 chrome 上实现,那么 Puppeteer 是最好的选择,因为它具有修改标头的本机支持。 看看这个:https://pptr.dev/#?product=Puppeteer&version=v10.1.0&show=api-pagesetextrahttpheadersheaders

尽管要跨浏览器使用,您可以查看 @requestly/selenium npm 包。它是 requestly 扩展的包装器,可以轻松集成到 selenium-webdriver 中。扩展可以修改标头。 退房:https://www.npmjs.com/package/@requestly/selenium