настройка заголовков запросов в селене

Я пытаюсь установить заголовок запроса «Referer», чтобы подделать запрос, поступающий с другого сайта. Нам нужна проверка способности, что используется конкретный реферер, который возвращает пользователю конкретную форму, в противном случае дается альтернативная форма.

Я могу сделать это в полтергейсте:

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

но я не могу найти эквивалентную функциональность для драйвера selemium.

Как я могу установить заголовки запросов в драйвере селена капибары?


person tamouse    schedule 26.03.2013    source источник
comment
Возможные дубликаты: Заголовки и Selenium Webdriver 2, Как отправить HTTP RequestHeader с помощью Selenium 2?   -  person Andrei Botalov    schedule 27.03.2013
comment
Другой возможный дубликат: Как добавить заголовки или параметры в HTTP-запрос, обрабатываемый с помощью Selenium Webdriver?   -  person Andrei Botalov    schedule 27.03.2013
comment
Спасибо, Андрей. Интересно, почему они не были предложены, когда я искал...   -  person tamouse    schedule 28.03.2013


Ответы (10)


Webdriver не содержит API для этого. Дополнительную информацию см. в выпуске 141 из средства отслеживания Selenium. В названии проблемы сказано, что речь идет о заголовках ответов, но было решено, что Selenium не будет содержать API для заголовков запросов в рамках этой проблемы. Несколько проблем с добавлением API для установки заголовков запросов были отмечены как повторяющиеся: first, секунды, третий.

Вот несколько вариантов, которые я могу предложить:

  1. Используйте другой драйвер/библиотеку вместо селена
  2. Напишите плагин для браузера (или найдите существующий), который позволит вам добавить заголовок для запроса.
  3. Используйте browsermob-proxy или другой прокси.

Я бы выбрал вариант 3 в большинстве случаев. Это не сложно.

Обратите внимание, что у Ghostdriver есть API для этого, но он не поддерживается другими драйверами.

person Andrei Botalov    schedule 26.03.2013
comment
Я использую полтергейст для установки реферера, который достигает цели тестирования. Я также хотел использовать селен с головой, чтобы показать, что он работает для тех, кто заинтересован. - person tamouse; 28.03.2013
comment
Я бы выбрал [browsermob-proxy], это не сложно. – Мне это кажется довольно загадочным! Кроме того, с моей точки зрения, это выглядит как очень большой инструмент для очень маленькой проблемы. - person chadoh; 30.04.2014
comment
Если вы создаете или используете специальный подключаемый модуль браузера для добавления заголовков запросов, вы можете автоматизировать тестирование подключаемого модуля, как указано здесь — blazemeter.com/blog/. Таким образом, вы можете автоматизировать настройку плагина с помощью заголовков до того, как начнется ваш тестовый код. Однако этот подход не кажется простым. - person MasterJoe; 08.04.2017
comment
Это: Webdriver не содержит API для этого. - person maaw; 09.05.2017
comment
пробовал браузермоб-прокси, это совсем не сложно. К сожалению, мне удалось заставить его работать только с HtmlUnit, а не с Firefox или Chrome. Вернемся к квадрату 1. - person Florian Wicher; 11.01.2020
comment
@FlorianWicher, пожалуйста, проверьте это: sqa.stackexchange.com/questions/37227/ - person Pawel Nieradka; 09.04.2020

Для тех, кто использует Python, вы можете рассмотреть возможность использования Selenium Wire, который может устанавливать заголовки запросов, а также предоставить вам возможность проверять запросы и ответы.

from seleniumwire import webdriver  # Import from seleniumwire

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

# Create a request interceptor
def interceptor(request):
    del request.headers['Referer']  # Delete the header first
    request.headers['Referer'] = 'some_referer'

# Set the interceptor on the driver
driver.request_interceptor = interceptor

# All requests will now use 'some_referer' for the referer
driver.get('https://mysite')
person Will Keeling    schedule 19.08.2018
comment
Мне пришлось использовать driver._client.set_header_overrides(headers=dict_headers) для решения моей проблемы. - person Kartikey Singh; 01.02.2019

Я была такая же проблема. Я решил это, загрузив надстройку Firefox для модификации заголовков и активировав ее с помощью селена.

Код в питоне следующий

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)
person Fernando Marengo    schedule 06.01.2017
comment
Однако это не работает с Firefox Quantum (57.+). - person Dio; 02.08.2018
comment
это расширение должно быть обновлено в соответствии с новым манифестом для работы с 57+ fox - person d-d; 05.04.2019

Сегодня была такая же проблема, за исключением того, что мне нужно было установить разные рефереры для каждого теста. В итоге я использовал промежуточное ПО и класс для передачи ему заголовков. Думал, что поделюсь (или, может быть, есть более чистое решение?):

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, но он должен быть прозрачным, так как внедрение заголовка выполняется до того, как запрос действительно попадет в приложение.

person HargrimmTheBleak    schedule 19.06.2013
comment
Остерегайтесь cattr_accessor :headers — он будет сохранять заголовки между тестами, поэтому вам может понадобиться сбросить его в промежуточном программном обеспечении: @helper.heades = nil, в противном случае будьте готовы позже повеселиться, отлаживая ненадежные тесты. - person Yuriy Kharchenko; 15.10.2019

Если вы используете 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
  }
}

Заголовки будут отображаться во всех запросах, сделанных веб-браузером.

person John P    schedule 23.03.2017

Я хотел что-то более тонкое для 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}
person Glenn    schedule 04.06.2019

С решениями, уже обсужденными выше, наиболее надежным является использование Browsermob-Proxy

Но при работе с удаленной сетевой машиной Browsermob-proxy не очень помогает.

Вот как я решил проблему в моем случае. Надеюсь, может быть полезно для тех, у кого аналогичная настройка.

  1. Добавьте расширение ModHeader в браузер Chrome.

Как скачать модхедер? Ссылка на сайт

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.

Захват идентификатора из ModHeader

  1. Перейдите к URL-адресу ModHeader, чтобы установить контекст локального хранилища.

.

// 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-1, value-1, token-2, value-2 — заголовки запроса и значения, которые необходимо добавить.

  1. Теперь перейдите к нужному веб-приложению.

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

person Praveen    schedule 17.06.2020
comment
Привет, звучит здорово, но я получаю эту ошибку: org.openqa.selenium.WebDriverException: <unknown>: Failed to read the 'localStorage' property from 'Window': Access is denied for this document. - person Y-B Cause; 26.03.2021

Если вы используете 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

person Nafees Nehar    schedule 24.07.2021

Вы можете сделать это с помощью PhantomJSDriver.

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

Используя объект запроса, вы также можете фильтровать, чтобы заголовок не устанавливался для каждого запроса.

person stijn van crombrugge    schedule 22.12.2017

проверьте это: 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"')

Проблема решена!

person Jame    schedule 04.05.2019
comment
это не решает проблему и не отвечает на вопрос вообще. - person Corey Goldberg; 31.05.2019
comment
Я не знаю, ответил ли он на заданные вопросы или нет. Но это решило мою проблему передачи пользовательского агента в заголовке при использовании безголового драйвера. Я предполагаю, что это необходимо на некоторых сайтах, которым требуется такой заголовок, чтобы остановить удаление данных. - person user3046442; 11.04.2020
comment
Большое спасибо! Это заставляет сайт думать, что безголовый браузер на самом деле является обычным браузером с заголовком. Это решает мою проблему! - person Mihir Verma; 04.03.2021