module Selenium::WebDriver::DriverExtensions::HasNetworkInterception
Public Instance Methods
intercept(&block)
click to toggle source
Intercepts requests coming from browser allowing to either pass them through like proxy or provide a stubbed response instead.
@example Log requests and pass through
driver.intercept do |request, &continue| puts "#{request.method} #{request.url}" continue.call(request) end
@example Stub requests for images
driver.intercept do |request, &continue| if request.url.match?(/\.png$/) request.url = 'https://upload.wikimedia.org/wikipedia/commons/d/d5/Selenium_Logo.png' end continue.call(request) end
@example Log responses and pass through
driver.intercept do |request, &continue| continue.call(request) do |response| puts "#{response.code} #{response.body}" end end
@example Mutate specific response
driver.intercept do |request, &continue| continue.call(request) do |response| response.body << 'Added by Selenium!' if request.url.include?('/myurl') end end
@param [Proc] block which is called when request is intercepted @yieldparam [DevTools::Request] request @yieldparam [Proc] continue block which proceeds with the request and optionally yields response
# File lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb, line 63 def intercept(&block) devtools.network.set_cache_disabled(cache_disabled: true) devtools.fetch.on(:request_paused) do |params| id = params['requestId'] if params.key?('responseStatusCode') || params.key?('responseErrorReason') intercept_response(id, params, &pending_response_requests.delete(id)) else intercept_request(id, params, &block) end end devtools.fetch.enable(patterns: [{requestStage: 'Request'}, {requestStage: 'Response'}]) end
Private Instance Methods
fetch_response_body(id)
click to toggle source
# File lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb, line 127 def fetch_response_body(id) devtools.fetch.get_response_body(request_id: id).dig('result', 'body') rescue Error::WebDriverError # CDP fails to get body on certain responses (301) and raises: # Can only get response body on requests captured after headers received. end
intercept_request(id, params, &block)
click to toggle source
# File lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb, line 82 def intercept_request(id, params, &block) original = DevTools::Request.from(id, params) mutable = DevTools::Request.from(id, params) block.call(mutable) do |&continue| # rubocop:disable Performance/RedundantBlockCall pending_response_requests[id] = continue if original == mutable devtools.fetch.continue_request(request_id: id) else devtools.fetch.continue_request( request_id: id, url: mutable.url, method: mutable.method, post_data: mutable.post_data, headers: mutable.headers.map do |k, v| {name: k, value: v} end ) end end end
intercept_response(id, params) { |mutable| ... }
click to toggle source
# File lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb, line 105 def intercept_response(id, params) return devtools.fetch.continue_request(request_id: id) unless block_given? body = fetch_response_body(id) original = DevTools::Response.from(id, body, params) mutable = DevTools::Response.from(id, body, params) yield mutable if original == mutable devtools.fetch.continue_request(request_id: id) else devtools.fetch.fulfill_request( request_id: id, body: (Base64.strict_encode64(mutable.body) if mutable.body), response_code: mutable.code, response_headers: mutable.headers.map do |k, v| {name: k, value: v} end ) end end
pending_response_requests()
click to toggle source
# File lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb, line 78 def pending_response_requests @pending_response_requests ||= {} end