別のサイトからのリクエストを偽装するようにリクエストヘッダー「Referer」を設定しようとしています。特定のリファラーを使用する能力テストが必要です。特定のリファラーを使用すると、特定のフォームがユーザーに返されます。
私はポルターガイスト内でこれを行うことができます:
page.driver.headers = {"Referer" => referer_string}
しかし、セレンドライバの同等の機能は見つかりません。
Capybara Seleniumドライバーでリクエストヘッダーを設定するにはどうすればよいですか?
Webdriverには、それを行うためのAPIが含まれていません。詳細については、 Seleniumトラッカーの問題141 を参照してください。問題のタイトルには、応答ヘッダーに関するものであると書かれていますが、Seleniumには、この問題の範囲内の要求ヘッダー用のAPIは含まれないことが決定されました。要求ヘッダーを設定するためのAPIの追加に関するいくつかの問題が重複としてマークされています: first 、 second 、 third 。
ここに私が提案できるいくつかの可能性があります:
ほとんどの場合、オプション3を使用します。それは難しいことではありません。
GhostdriverにはAPIがあります ですが、他のドライバーではサポートされていないことに注意してください。
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
同じ問題がありました。 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)
今日、同じ問題を抱えていましたが、テストごとに異なるリファラーを設定する必要がありました。結局、ミドルウェアとクラスを使用してヘッダーを渡しました。私は共有するだろうと思った(または多分よりクリーンなソリューションがあるでしょうか?):
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以外ではテストしていませんが、要求が実際にアプリケーションにヒットする前にヘッダーインジェクションが行われるため、透過的でなければなりません。
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ブラウザーによって行われたすべての要求に含まれます。
これをチェックしてください: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"')
問題が解決しました!
カスタムコードを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}
PhantomJSDriverでできます。
PhantomJSDriver pd = ((PhantomJSDriver) ((WebDriverFacade) getDriver()).getProxiedDriver());
pd.executePhantomJS(
"this.onResourceRequested = function(request, net) {" +
" net.setHeader('header-name', 'header-value')" +
"};");
リクエストオブジェクトを使用して、リクエストごとにヘッダーが設定されないようにフィルタリングすることもできます。