mirror of
https://github.com/HoneyryderChuck/httpx.git
synced 2025-10-08 00:02:42 -04:00
137 lines
3.8 KiB
Ruby
137 lines
3.8 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module HTTPX
|
|
class Options
|
|
MAX_CONCURRENT_REQUESTS = 100
|
|
MAX_RETRIES = 3
|
|
WINDOW_SIZE = 1 << 14 # 16K
|
|
MAX_BODY_THRESHOLD_SIZE = (1 << 10) * 112 # 112K
|
|
|
|
class << self
|
|
def inherited(klass)
|
|
super
|
|
klass.instance_variable_set(:@defined_options, @defined_options.dup)
|
|
end
|
|
|
|
def new(options = {})
|
|
# let enhanced options go through
|
|
return options if self == Options && options.class > self
|
|
return options if options.is_a?(self)
|
|
super
|
|
end
|
|
|
|
def defined_options
|
|
@defined_options ||= []
|
|
end
|
|
|
|
def def_option(name, &interpreter)
|
|
defined_options << name.to_sym
|
|
interpreter ||= lambda { |v| v }
|
|
|
|
attr_accessor name
|
|
protected :"#{name}="
|
|
|
|
define_method(:"with_#{name}") do |value|
|
|
dup { |opts| opts.send(:"#{name}=", instance_exec(value, &interpreter)) }
|
|
end
|
|
end
|
|
end
|
|
|
|
def initialize(options = {})
|
|
defaults = {
|
|
:debug => ENV.key?("HTTPX_DEBUG") ? $stderr : nil,
|
|
:debug_level => (ENV["HTTPX_DEBUG"] || 1).to_i,
|
|
:ssl => { alpn_protocols: %w[h2 http/1.1] },
|
|
:http2_settings => { settings_enable_push: 0 },
|
|
:fallback_protocol => "http/1.1",
|
|
:timeout => Timeout.by(:per_operation),
|
|
:headers => {},
|
|
:max_concurrent_requests => MAX_CONCURRENT_REQUESTS,
|
|
:max_retries => MAX_RETRIES,
|
|
:window_size => WINDOW_SIZE,
|
|
:body_threshold_size => MAX_BODY_THRESHOLD_SIZE,
|
|
:request_class => Class.new(Request),
|
|
:response_class => Class.new(Response),
|
|
:headers_class => Class.new(Headers),
|
|
:response_body_class => Class.new(Response::Body),
|
|
}
|
|
|
|
defaults.merge!(options)
|
|
defaults[:headers] = Headers.new(defaults[:headers])
|
|
defaults.each { |(k, v)| self[k] = v }
|
|
end
|
|
|
|
def_option(:headers) do |headers|
|
|
self.headers.merge(headers)
|
|
end
|
|
|
|
def_option(:timeout) do |type, opts|
|
|
self.timeout = Timeout.by(type, opts)
|
|
end
|
|
|
|
def_option(:max_concurrent_requests) do |num|
|
|
max = Integer(num)
|
|
raise Error, ":max_concurrent_requests must be positive" unless max.positive?
|
|
self.max_concurrent_requests = max
|
|
end
|
|
|
|
def_option(:window_size) do |num|
|
|
self.window_size = Integer(num)
|
|
end
|
|
|
|
def_option(:body_threshold_size) do |num|
|
|
self.body_threshold_size = Integer(num)
|
|
end
|
|
|
|
%w[
|
|
params form json body
|
|
follow ssl http2_settings max_retries
|
|
request_class response_class headers_class response_body_class
|
|
io fallback_protocol debug debug_level
|
|
].each do |method_name|
|
|
def_option(method_name)
|
|
end
|
|
|
|
def merge(other)
|
|
h1 = to_hash
|
|
h2 = other.to_hash
|
|
|
|
merged = h1.merge(h2) do |k, v1, v2|
|
|
case k
|
|
when :headers, :ssl, :http2_settings
|
|
v1.merge(v2)
|
|
else
|
|
v2
|
|
end
|
|
end
|
|
|
|
self.class.new(merged)
|
|
end
|
|
|
|
def to_hash
|
|
hash_pairs = self.class.
|
|
defined_options.
|
|
flat_map { |opt_name| [opt_name, send(opt_name)] }
|
|
Hash[*hash_pairs]
|
|
end
|
|
|
|
def dup
|
|
dupped = super
|
|
dupped.headers = headers.dup
|
|
dupped.ssl = ssl.dup
|
|
dupped.request_class = request_class.dup
|
|
dupped.response_class = response_class.dup
|
|
dupped.headers_class = headers_class.dup
|
|
dupped.response_body_class = response_body_class.dup
|
|
yield(dupped) if block_given?
|
|
dupped
|
|
end
|
|
|
|
protected
|
|
|
|
def []=(option, val)
|
|
send(:"#{option}=", val)
|
|
end
|
|
end
|
|
end
|