web-dev-qa-db-ja.com

セレンでリクエストヘッダーを設定する

別のサイトからのリクエストを偽装するようにリクエストヘッダー「Referer」を設定しようとしています。特定のリファラーを使用する能力テストが必要です。特定のリファラーを使用すると、特定のフォームがユーザーに返されます。

私はポルターガイスト内でこれを行うことができます:

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

しかし、セレンドライバの同等の機能は見つかりません。

Capybara Seleniumドライバーでリクエストヘッダーを設定するにはどうすればよいですか?

44
tamouse

Webdriverには、それを行うためのAPIが含まれていません。詳細については、 Seleniumトラッカーの問題141 を参照してください。問題のタイトルには、応答ヘッダーに関するものであると書かれていますが、Seleniumには、この問題の範囲内の要求ヘッダー用のAPIは含まれないことが決定されました。要求ヘッダーを設定するためのAPIの追加に関するいくつかの問題が重複としてマークされています: firstsecondthird

ここに私が提案できるいくつかの可能性があります:

  1. Seleniumの代わりに別のドライバー/ライブラリを使用します
  2. リクエストにヘッダーを追加できるブラウザ固有のプラグインを作成します(または既存のプラグインを見つけます)。
  3. browsermob-proxy または他のプロキシを使用します。

ほとんどの場合、オプション3を使用します。それは難しいことではありません。

GhostdriverにはAPIがあります ですが、他のドライバーではサポートされていないことに注意してください。

34
Andrei Botalov

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
10
Will Keeling

同じ問題がありました。 modify-headers firefoxアドオンをダウンロードし、Seleniumでアクティブ化することで解決しました。

pythonのコードは次のとおりです

fp = webdriver.FirefoxProfile()
path_modify_header = 'C:/xxxxxxx/modify_headers-0.7.1.1-fx.xpi'
fp.add_extension(path_modify_header)

fp.set_preference("modifyheaders.headers.count", 1)
fp.set_preference("modifyheaders.headers.action0", "Add")
fp.set_preference("modifyheaders.headers.name0", "Name_of_header") # Set here the name of the header
fp.set_preference("modifyheaders.headers.value0", "value_of_header") # Set here the value of the header
fp.set_preference("modifyheaders.headers.enabled0", True)
fp.set_preference("modifyheaders.config.active", True)
fp.set_preference("modifyheaders.config.alwaysOn", True)

driver = webdriver.Firefox(firefox_profile=fp)
8

今日、同じ問題を抱えていましたが、テストごとに異なるリファラーを設定する必要がありました。結局、ミドルウェアとクラスを使用してヘッダーを渡しました。私は共有するだろうと思った(または多分よりクリーンなソリューションがあるでしょうか?):

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以外ではテストしていませんが、要求が実際にアプリケーションにヒットする前にヘッダーインジェクションが行われるため、透過的でなければなりません。

5

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ブラウザーによって行われたすべての要求に含まれます。

1
John P

これをチェックしてください: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"')

問題が解決しました!

0
Jame

カスタムコードを1か所に置くだけで済むように、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}
0
Glenn

PhantomJSDriverでできます。

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

リクエストオブジェクトを使用して、リクエストごとにヘッダーが設定されないようにフィルタリングすることもできます。