Path: blob/trunk/rb/lib/selenium/webdriver/remote/http/default.rb
1990 views
# frozen_string_literal: true12# Licensed to the Software Freedom Conservancy (SFC) under one3# or more contributor license agreements. See the NOTICE file4# distributed with this work for additional information5# regarding copyright ownership. The SFC licenses this file6# to you under the Apache License, Version 2.0 (the7# "License"); you may not use this file except in compliance8# with the License. You may obtain a copy of the License at9#10# http://www.apache.org/licenses/LICENSE-2.011#12# Unless required by applicable law or agreed to in writing,13# software distributed under the License is distributed on an14# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY15# KIND, either express or implied. See the License for the16# specific language governing permissions and limitations17# under the License.18require 'ipaddr'1920module Selenium21module WebDriver22module Remote23module Http24# @api private25class Default < Common26attr_writer :proxy2728attr_accessor :open_timeout, :read_timeout2930# Initializes object.31# Warning: Setting {#open_timeout} to non-nil values will cause a separate thread to spawn.32# Debuggers that freeze the process will not be able to evaluate any operations if that happens.33# @param [Numeric] open_timeout - Open timeout to apply to HTTP client.34# @param [Numeric] read_timeout - Read timeout (seconds) to apply to HTTP client.35def initialize(open_timeout: nil, read_timeout: nil)36@open_timeout = open_timeout37@read_timeout = read_timeout38super()39end4041def close42@http&.finish43end4445private4647def http48@http ||= begin49http = new_http_client50if server_url.scheme == 'https'51http.use_ssl = true52http.verify_mode = OpenSSL::SSL::VERIFY_NONE53end5455http.open_timeout = open_timeout if open_timeout56http.read_timeout = read_timeout if read_timeout5758start(http)59http60end61end6263def start(http)64http.start65end6667MAX_RETRIES = 36869def request(verb, url, headers, payload, redirects = 0)70retries = 07172begin73request = new_request_for(verb, url, headers, payload)74response = response_for(request)75rescue Errno::ECONNABORTED, Errno::ECONNRESET, Errno::EADDRINUSE, Errno::EADDRNOTAVAIL76# a retry is sometimes needed:77# on Windows XP where we may quickly run out of ephemeral ports78# when the port becomes temporarily unavailable79#80# A more robust solution is bumping the MaxUserPort setting81# as described here:82#83# http://msdn.microsoft.com/en-us/library/aa560610%28v=bts.20%29.aspx84raise if retries >= MAX_RETRIES8586retries += 187sleep 288retry89rescue Errno::ECONNREFUSED => e90raise e.class, "using proxy: #{proxy.http}" if use_proxy?9192raise93end9495if response.is_a? Net::HTTPRedirection96WebDriver.logger.debug("Redirect to #{response['Location']}; times: #{redirects}")97raise Error::WebDriverError, 'too many redirects' if redirects >= MAX_REDIRECTS9899request(:get, URI.parse(response['Location']), DEFAULT_HEADERS.dup, nil, redirects + 1)100else101WebDriver.logger.debug(" <<< #{response.instance_variable_get(:@header).inspect}", id: :header)102create_response response.code, response.body, response.content_type103end104end105106def new_request_for(verb, url, headers, payload)107req = Net::HTTP.const_get(verb.to_s.capitalize).new(url.path, headers)108109req.basic_auth server_url.user, server_url.password if server_url.userinfo110111req.body = payload if payload112113req114end115116def response_for(request)117http.request request118end119120def new_http_client121if use_proxy?122url = @proxy.http123unless proxy.respond_to?(:http) && url124raise Error::WebDriverError,125"expected HTTP proxy, got #{@proxy.inspect}"126end127128proxy = URI.parse(url)129130Net::HTTP.new(server_url.host, server_url.port, proxy.host, proxy.port, proxy.user, proxy.password)131else132Net::HTTP.new server_url.host, server_url.port133end134end135136def proxy137@proxy ||= begin138proxy = ENV.fetch('http_proxy', nil) || ENV.fetch('HTTP_PROXY', nil)139no_proxy = ENV.fetch('no_proxy', nil) || ENV.fetch('NO_PROXY', nil)140141if proxy142proxy = "http://#{proxy}" unless proxy.start_with?('http://')143Proxy.new(http: proxy, no_proxy: no_proxy)144end145end146end147148def use_proxy?149return false if proxy.nil?150151if proxy.no_proxy152ignored = proxy.no_proxy.split(',').any? do |host|153host == '*' ||154host == server_url.host || (155begin156IPAddr.new(host).include?(server_url.host)157rescue ArgumentError158false159end160)161end162163!ignored164else165true166end167end168end # Default169end # Http170end # Remote171end # WebDriver172end # Selenium173174175