J'essaie de définir l'en-tête de requête 'Référant' pour falsifier une requête provenant d'un autre site. Nous avons besoin du test de capacité selon lequel un référent spécifique est utilisé, qui renvoie un formulaire spécifique à l'utilisateur, sinon un formulaire alternatif est fourni.
Je peux le faire dans poltergeist en:
page.driver.headers = {"Referer" => referer_string}
mais je ne trouve pas la fonctionnalité équivalente pour le pilote selemium.
Comment définir des en-têtes de requête dans le pilote capybara Selenium?
Webdriver ne contient pas d'API pour le faire. Voir numéro 141 de Selenium Tracker pour plus d'informations. Le titre du problème indique qu'il s'agit d'en-têtes de réponse, mais il a été décidé que Selenium ne contiendrait pas d'API pour les en-têtes de demande dans le cadre de ce problème. Plusieurs problèmes liés à l'ajout d'API dans les en-têtes de requête ont été signalés comme des doublons: first , second , third .
Voici quelques possibilités que je peux proposer:
J'irais avec l'option 3 dans la plupart des cas. C'est pas difficile.
Notez que Ghostdriver dispose d’une API mais elle n’est pas prise en charge par les autres pilotes.
J'ai eu le même problème. Je l'ai résolu en téléchargeant le module complémentaire firefox de modify-headers et en l'activant avec Selenium.
Le code en python est le suivant
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)
Avait le même problème aujourd'hui, sauf que je devais définir un référent différent pour chaque test. J'ai fini par utiliser un middleware et une classe pour y passer des en-têtes. Je pensais partager (ou peut-être une solution plus propre?):
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
Ensuite, je peux inclure le contexte partagé où j'en ai besoin ou passer différents en-têtes dans un autre bloc before
. Je ne l'ai pas testé avec autre chose que Selenium et RackTest, mais il devrait être transparent, car l'injection d'en-tête est effectuée avant que la demande ne frappe réellement l'application.
Si vous utilisez Python, vous pouvez utiliser Selenium Wire , qui permet de définir des en-têtes de requête et de vous permettre d’inspecter les requêtes et les réponses.
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
Si vous utilisez la variable HtmlUnitDriver
, vous pouvez définir les en-têtes de requête en modifiant la variable WebClient
, comme suit:
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
}
}
Les en-têtes seront alors sur toutes les demandes faites par le navigateur Web.
Vous pouvez le faire avec PhantomJSDriver.
PhantomJSDriver pd = ((PhantomJSDriver) ((WebDriverFacade) getDriver()).getProxiedDriver());
pd.executePhantomJS(
"this.onResourceRequested = function(request, net) {" +
" net.setHeader('header-name', 'header-value')" +
"};");
À l'aide de l'objet de requête, vous pouvez également filtrer pour que l'en-tête ne soit pas défini pour chaque requête.