Установка заголовков запросов в селене
Я пытаюсь установить заголовок запроса 'Referer', чтобы обмануть запрос, поступающий с другого сайта. Нам нужен тест способности, который использует конкретный реферер, который возвращает конкретную форму пользователю, в противном случае предоставляется альтернативная форма.
Я могу сделать это в полтергейсте:
page.driver.headers = {"Referer" => referer_string}
но я не могу найти эквивалентную функциональность для драйвера селемиума.
Как настроить заголовки запросов в драйвере capybara selenium?
Ответы
Ответ 1
Webdriver не содержит API для этого. Для получения дополнительной информации см. вопрос 141 из Selenium tracker. Название проблемы говорит о том, что это касается заголовков ответов, но было решено, что Selenium не будет содержать API для заголовков запросов в рамках этой проблемы. Несколько вопросов о добавлении API для установки заголовков запросов были отмечены как дубликаты: first, второй, третий.
Вот несколько возможностей, которые я могу предложить:
- Используйте другой драйвер/библиотеку вместо селена
- Записать плагин, специфичный для браузера (или найти существующий), который позволяет добавлять заголовок для запроса.
- Используйте browsermob-proxy или какой-либо другой прокси.
В большинстве случаев я бы выбрал вариант 3. Это не сложно.
Обратите внимание, что Ghostdriver имеет API для него, но он не поддерживается другими драйверами.
Ответ 2
У меня была такая же проблема. Я решил, что загружаю надстройку firefox add-on и активирую его с помощью селена.
Код в 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)
Ответ 3
Для тех, кто использует 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
Ответ 4
Имел ту же самую проблему сегодня, за исключением того, что мне нужно было установить другой референт на тест. Я закончил использование промежуточного программного обеспечения и класса, чтобы передать ему заголовки. Думал, что я поделюсь (или, может быть, там более чистое решение?):
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
}
}
Затем заголовки будут отображаться во всех запросах, сделанных веб-браузером.
Ответ 6
проверить это: 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"')
Задача решена!
Ответ 7
Вы можете сделать это с помощью PhantomJSDriver.
PhantomJSDriver pd = ((PhantomJSDriver) ((WebDriverFacade) getDriver()).getProxiedDriver());
pd.executePhantomJS(
"this.onResourceRequested = function(request, net) {" +
" net.setHeader('header-name', 'header-value')" +
"};");
Используя объект запроса, вы также можете фильтровать так, чтобы заголовок не был установлен для каждого запроса.
Ответ 8
Я хотел что-то более тонкое для 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}