lib/httpx/options.rb in httpx-1.1.5 vs lib/httpx/options.rb in httpx-1.2.0

- old
+ new

@@ -9,10 +9,11 @@ BUFFER_SIZE = 1 << 14 WINDOW_SIZE = 1 << 14 # 16K MAX_BODY_THRESHOLD_SIZE = (1 << 10) * 112 # 112K KEEP_ALIVE_TIMEOUT = 20 SETTINGS_TIMEOUT = 10 + CLOSE_HANDSHAKE_TIMEOUT = 10 CONNECT_TIMEOUT = READ_TIMEOUT = WRITE_TIMEOUT = 60 REQUEST_TIMEOUT = OPERATION_TIMEOUT = nil # https://github.com/ruby/resolv/blob/095f1c003f6073730500f02acbdbc55f83d70987/lib/resolv.rb#L408 ip_address_families = begin @@ -37,10 +38,11 @@ :decompress_response_body => true, :compress_request_body => true, :timeout => { connect_timeout: CONNECT_TIMEOUT, settings_timeout: SETTINGS_TIMEOUT, + close_handshake_timeout: CLOSE_HANDSHAKE_TIMEOUT, operation_timeout: OPERATION_TIMEOUT, keep_alive_timeout: KEEP_ALIVE_TIMEOUT, read_timeout: READ_TIMEOUT, write_timeout: WRITE_TIMEOUT, request_timeout: REQUEST_TIMEOUT, @@ -224,59 +226,114 @@ class_eval(<<-OUT, __FILE__, __LINE__ + 1) def option_#{method_name}(v); v; end # def option_smth(v); v; end OUT end - REQUEST_IVARS = %i[@params @form @xml @json @body].freeze - private_constant :REQUEST_IVARS + REQUEST_BODY_IVARS = %i[@headers @params @form @xml @json @body].freeze def ==(other) - ivars = instance_variables | other.instance_variables + super || options_equals?(other) + end + + def options_equals?(other, ignore_ivars = REQUEST_BODY_IVARS) + # headers and other request options do not play a role, as they are + # relevant only for the request. + ivars = instance_variables - ignore_ivars + other_ivars = other.instance_variables - ignore_ivars + + return false if ivars.size != other_ivars.size + + return false if ivars.sort != other_ivars.sort + ivars.all? do |ivar| - case ivar - when :@headers - # currently, this is used to pick up an available matching connection. - # the headers do not play a role, as they are relevant only for the request. - true - when *REQUEST_IVARS - true - else - instance_variable_get(ivar) == other.instance_variable_get(ivar) - end + instance_variable_get(ivar) == other.instance_variable_get(ivar) end end + OTHER_LOOKUP = ->(obj, k, ivar_map) { + case obj + when Hash + obj[ivar_map[k]] + else + obj.instance_variable_get(k) + end + } def merge(other) - raise ArgumentError, "#{other} is not a valid set of options" unless other.respond_to?(:to_hash) + ivar_map = nil + other_ivars = case other + when Hash + ivar_map = other.keys.to_h { |k| [:"@#{k}", k] } + ivar_map.keys + else + other.instance_variables + end - h2 = other.to_hash - return self if h2.empty? + return self if other_ivars.empty? - h1 = to_hash + return self if other_ivars.all? { |ivar| instance_variable_get(ivar) == OTHER_LOOKUP[other, ivar, ivar_map] } - return self if h1 >= h2 + opts = dup - merged = h1.merge(h2) do |_k, v1, v2| - if v1.respond_to?(:merge) && v2.respond_to?(:merge) - v1.merge(v2) - else - v2 + other_ivars.each do |ivar| + v = OTHER_LOOKUP[other, ivar, ivar_map] + + unless v + opts.instance_variable_set(ivar, v) + next end + + v = opts.__send__(:"option_#{ivar[1..-1]}", v) + + orig_v = instance_variable_get(ivar) + + v = orig_v.merge(v) if orig_v.respond_to?(:merge) && v.respond_to?(:merge) + + opts.instance_variable_set(ivar, v) end - self.class.new(merged) + opts end def to_hash instance_variables.each_with_object({}) do |ivar, hs| hs[ivar[1..-1].to_sym] = instance_variable_get(ivar) end end - def initialize_dup(other) - instance_variables.each do |ivar| - instance_variable_set(ivar, other.instance_variable_get(ivar).dup) + def extend_with_plugin_classes(pl) + if defined?(pl::RequestMethods) || defined?(pl::RequestClassMethods) + @request_class = @request_class.dup + @request_class.__send__(:include, pl::RequestMethods) if defined?(pl::RequestMethods) + @request_class.extend(pl::RequestClassMethods) if defined?(pl::RequestClassMethods) end + if defined?(pl::ResponseMethods) || defined?(pl::ResponseClassMethods) + @response_class = @response_class.dup + @response_class.__send__(:include, pl::ResponseMethods) if defined?(pl::ResponseMethods) + @response_class.extend(pl::ResponseClassMethods) if defined?(pl::ResponseClassMethods) + end + if defined?(pl::HeadersMethods) || defined?(pl::HeadersClassMethods) + @headers_class = @headers_class.dup + @headers_class.__send__(:include, pl::HeadersMethods) if defined?(pl::HeadersMethods) + @headers_class.extend(pl::HeadersClassMethods) if defined?(pl::HeadersClassMethods) + end + if defined?(pl::RequestBodyMethods) || defined?(pl::RequestBodyClassMethods) + @request_body_class = @request_body_class.dup + @request_body_class.__send__(:include, pl::RequestBodyMethods) if defined?(pl::RequestBodyMethods) + @request_body_class.extend(pl::RequestBodyClassMethods) if defined?(pl::RequestBodyClassMethods) + end + if defined?(pl::ResponseBodyMethods) || defined?(pl::ResponseBodyClassMethods) + @response_body_class = @response_body_class.dup + @response_body_class.__send__(:include, pl::ResponseBodyMethods) if defined?(pl::ResponseBodyMethods) + @response_body_class.extend(pl::ResponseBodyClassMethods) if defined?(pl::ResponseBodyClassMethods) + end + if defined?(pl::ConnectionMethods) + @connection_class = @connection_class.dup + @connection_class.__send__(:include, pl::ConnectionMethods) + end + return unless defined?(pl::OptionsMethods) + + @options_class = @options_class.dup + @options_class.__send__(:include, pl::OptionsMethods) end private def do_initialize(options = {})