class HTTPX::Options

  1. lib/httpx/options.rb
  2. lib/httpx/plugins/stream.rb
  3. lib/httpx/transcoder/utils/deflater.rb
  4. show all
Superclass: Object

Contains a set of options which are passed and shared across from session to its requests or responses.

Constants

BUFFER_SIZE = 1 << 14  
CLOSE_HANDSHAKE_TIMEOUT = 10  
CONNECT_TIMEOUT = READ_TIMEOUT = WRITE_TIMEOUT = 60  
DEFAULT_OPTIONS = { :max_requests => Float::INFINITY, :debug => nil, :debug_level => (ENV["HTTPX_DEBUG"] || 1).to_i, :debug_redact => ENV.key?("HTTPX_DEBUG_REDACT"), :ssl => EMPTY_HASH, :http2_settings => { settings_enable_push: 0 }.freeze, :fallback_protocol => "http/1.1", :supported_compression_formats => %w[gzip deflate], :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, }.freeze, :headers_class => Class.new(Headers, &SET_TEMPORARY_NAME), :headers => EMPTY_HASH, :window_size => WINDOW_SIZE, :buffer_size => BUFFER_SIZE, :body_threshold_size => MAX_BODY_THRESHOLD_SIZE, :request_class => Class.new(Request, &SET_TEMPORARY_NAME), :response_class => Class.new(Response, &SET_TEMPORARY_NAME), :request_body_class => Class.new(Request::Body, &SET_TEMPORARY_NAME), :response_body_class => Class.new(Response::Body, &SET_TEMPORARY_NAME), :pool_class => Class.new(Pool, &SET_TEMPORARY_NAME), :connection_class => Class.new(Connection, &SET_TEMPORARY_NAME), :http1_class => Class.new(Connection::HTTP1, &SET_TEMPORARY_NAME), :http2_class => Class.new(Connection::HTTP2, &SET_TEMPORARY_NAME), :resolver_native_class => Class.new(Resolver::Native, &SET_TEMPORARY_NAME), :resolver_system_class => Class.new(Resolver::System, &SET_TEMPORARY_NAME), :resolver_https_class => Class.new(Resolver::HTTPS, &SET_TEMPORARY_NAME), :options_class => Class.new(self, &SET_TEMPORARY_NAME), :transport => nil, :addresses => nil, :persistent => false, :resolver_class => (ENV["HTTPX_RESOLVER"] || :native).to_sym, :resolver_cache => (ENV["HTTPX_RESOLVER_CACHE"] || :memory).to_sym, :resolver_options => { cache: true }.freeze, :pool_options => EMPTY_HASH, :ip_families => nil, :close_on_fork => false, }.each_value(&:freeze).freeze  
KEEP_ALIVE_TIMEOUT = 20  
MAX_BODY_THRESHOLD_SIZE = (1 << 10) * 112  
REQUEST_BODY_IVARS = %i[@headers].freeze  
REQUEST_TIMEOUT = OPERATION_TIMEOUT = nil  
RESOLVER_TYPES = %i[memory file].freeze  
SETTINGS_TIMEOUT = 10  
SET_TEMPORARY_NAME = ->(klass, pl = nil) do if klass.respond_to?(:set_temporary_name) # ruby 3.4 only name = klass.name || "#{klass.superclass.name}(plugin)" name = "#{name}/#{pl}" if pl klass.set_temporary_name(name) end end  

rubocop:disable Lint/UselessConstantScoping these really need to be defined at the end of the class

USER_AGENT = "httpx.rb/#{VERSION}".freeze  

default value used for “user-agent” header, when not overridden.

WINDOW_SIZE = 1 << 14  

Attributes

Public Class methods

freeze()
[show source]
   # File lib/httpx/options.rb
38 def freeze
39   @options_names.freeze
40   super
41 end
inherited(klass)
[show source]
   # File lib/httpx/options.rb
25 def inherited(klass)
26   super
27   klass.instance_variable_set(:@options_names, @options_names.dup)
28 end
method_added(meth)
[show source]
   # File lib/httpx/options.rb
43 def method_added(meth)
44   super
45 
46   return unless meth =~ /^option_(.+)$/
47 
48   optname = Regexp.last_match(1) #: String
49 
50   if optname =~ /^(.+[^_])_+with/
51     # ignore alias method chain generated methods.
52     # this is the case with RBS runtime tests.
53     # it relies on the "_with/_without" separator, which is the most used convention,
54     # however it shouldn't be used in practice in httpx given the plugin architecture
55     # as the main extension API.
56     orig_name = Regexp.last_match(1) #: String
57 
58     return if @options_names.include?(orig_name.to_sym)
59   end
60 
61   optname = optname.to_sym
62 
63   attr_reader(optname) unless method_defined?(optname)
64 
65   @options_names << optname unless @options_names.include?(optname)
66 end
new(options = {})
[show source]
   # File lib/httpx/options.rb
30 def new(options = {})
31   # let enhanced options go through
32   return options if self == Options && options.class < self
33   return options if options.is_a?(self)
34 
35   super
36 end
new(options = EMPTY_HASH)

creates a new options instance from a given hash, which optionally define the following:

:debug

an object which log messages are written to (must respond to <<)

:debug_level

the log level of messages (can be 1, 2, or 3).

:debug_redact

whether header/body payload should be redacted (defaults to false).

:ssl

a hash of options which can be set as params of OpenSSL::SSL::SSLContext (see HTTPX::SSL)

:http2_settings

a hash of options to be passed to a HTTP2::Connection (ex: { max_concurrent_streams: 2 })

:fallback_protocol

version of HTTP protocol to use by default in the absence of protocol negotiation like ALPN (defaults to "http/1.1")

:supported_compression_formats

list of compressions supported by the transcoder layer (defaults to %w[gzip deflate]).

:decompress_response_body

whether to auto-decompress response body (defaults to true).

:compress_request_body

whether to auto-decompress response body (defaults to true)

:timeout

hash of timeout configurations (supports :connect_timeout, :settings_timeout, :operation_timeout, :keep_alive_timeout, :read_timeout, :write_timeout and :request_timeout

:headers

hash of HTTP headers (ex: { "x-custom-foo" => "bar" })

:window_size

number of bytes to read from a socket

:buffer_size

internal read and write buffer size in bytes

:body_threshold_size

maximum size in bytes of response payload that is buffered in memory.

:request_class

class used to instantiate a request

:response_class

class used to instantiate a response

:headers_class

class used to instantiate headers

:request_body_class

class used to instantiate a request body

:response_body_class

class used to instantiate a response body

:connection_class

class used to instantiate connections

:http1_class

class used to manage HTTP1 sessions

:http2_class

class used to imanage HTTP2 sessions

:resolver_native_class

class used to resolve names using pure ruby DNS implementation

:resolver_system_class

class used to resolve names using system-based (getaddrinfo) name resolution

:resolver_https_class

class used to resolve names using DoH

:pool_class

class used to instantiate the session connection pool

:options_class

class used to instantiate options

:transport

type of transport to use (set to “unix” for UNIX sockets)

:addresses

bucket of peer addresses (can be a list of IP addresses, a hash of domain to list of adddresses; paths should be used for UNIX sockets instead)

:io

open socket, or domain/ip-to-socket hash, which requests should be sent to

:persistent

whether to persist connections in between requests (defaults to true)

:resolver_class

which resolver to use (defaults to :native, can also be :system<tt> for using getaddrinfo or <tt>:https for DoH resolver, or a custom class inheriting from HTTPX::Resolver::Resolver)

:resolver_cache

strategy to cache DNS results, ignored by the :system resolver, can be set to <tt>:memory<tt> or an instance of a custom class inheriting from HTTPX::Resolver::Cache::Base

:resolver_options

hash of options passed to the resolver. Accepted keys depend on the resolver type.

:pool_options

hash of options passed to the connection pool (See Pool#initialize).

:ip_families

which socket families are supported (system-dependent)

:origin

HTTP origin to set on requests with relative path (ex: “api.serv.com”)

:base_path

path to prefix given relative paths with (ex: “/v2”)

:max_concurrent_requests

max number of requests which can be set concurrently

:max_requests

max number of requests which can be made on socket before it reconnects.

:close_on_fork

whether the session automatically closes when the process is fork (defaults to false). it only works if the session is persistent (and ruby 3.1 or higher is used).

This list of options are enhanced with each loaded plugin, see the plugin docs for details.

[show source]
    # File lib/httpx/options.rb
122 def initialize(options = EMPTY_HASH)
123   options_names = self.class.options_names
124 
125   defaults =
126     case options
127     when Options
128       unknown_options = options.class.options_names - options_names
129 
130       raise Error, "unknown option: #{unknown_options.first}" unless unknown_options.empty?
131 
132       DEFAULT_OPTIONS.merge(options)
133     else
134       options.each_key do |k|
135         raise Error, "unknown option: #{k}" unless options_names.include?(k)
136       end
137 
138       options.empty? ? DEFAULT_OPTIONS : DEFAULT_OPTIONS.merge(options)
139     end
140 
141   options_names.each do |k|
142     v = defaults[k]
143 
144     if v.nil?
145       instance_variable_set(:"@#{k}", v)
146 
147       next
148     end
149 
150     value = __send__(:"option_#{k}", v)
151     instance_variable_set(:"@#{k}", value)
152   end
153 
154   do_initialize
155   freeze
156 end

Public Instance methods

==(other)
[show source]
    # File lib/httpx/options.rb
205 def ==(other)
206   super || options_equals?(other)
207 end
extend_with_plugin_classes(pl)
[show source]
    # File lib/httpx/options.rb
281 def extend_with_plugin_classes(pl)
282   # extend request class
283   if defined?(pl::RequestMethods) || defined?(pl::RequestClassMethods)
284     @request_class = @request_class.dup
285     SET_TEMPORARY_NAME[@request_class, pl]
286     @request_class.__send__(:include, pl::RequestMethods) if defined?(pl::RequestMethods)
287     @request_class.extend(pl::RequestClassMethods) if defined?(pl::RequestClassMethods)
288   end
289   # extend response class
290   if defined?(pl::ResponseMethods) || defined?(pl::ResponseClassMethods)
291     @response_class = @response_class.dup
292     SET_TEMPORARY_NAME[@response_class, pl]
293     @response_class.__send__(:include, pl::ResponseMethods) if defined?(pl::ResponseMethods)
294     @response_class.extend(pl::ResponseClassMethods) if defined?(pl::ResponseClassMethods)
295   end
296   # extend headers class
297   if defined?(pl::HeadersMethods) || defined?(pl::HeadersClassMethods)
298     @headers_class = @headers_class.dup
299     SET_TEMPORARY_NAME[@headers_class, pl]
300     @headers_class.__send__(:include, pl::HeadersMethods) if defined?(pl::HeadersMethods)
301     @headers_class.extend(pl::HeadersClassMethods) if defined?(pl::HeadersClassMethods)
302   end
303   # extend request body class
304   if defined?(pl::RequestBodyMethods) || defined?(pl::RequestBodyClassMethods)
305     @request_body_class = @request_body_class.dup
306     SET_TEMPORARY_NAME[@request_body_class, pl]
307     @request_body_class.__send__(:include, pl::RequestBodyMethods) if defined?(pl::RequestBodyMethods)
308     @request_body_class.extend(pl::RequestBodyClassMethods) if defined?(pl::RequestBodyClassMethods)
309   end
310   # extend response body class
311   if defined?(pl::ResponseBodyMethods) || defined?(pl::ResponseBodyClassMethods)
312     @response_body_class = @response_body_class.dup
313     SET_TEMPORARY_NAME[@response_body_class, pl]
314     @response_body_class.__send__(:include, pl::ResponseBodyMethods) if defined?(pl::ResponseBodyMethods)
315     @response_body_class.extend(pl::ResponseBodyClassMethods) if defined?(pl::ResponseBodyClassMethods)
316   end
317   # extend connection pool class
318   if defined?(pl::PoolMethods)
319     @pool_class = @pool_class.dup
320     SET_TEMPORARY_NAME[@pool_class, pl]
321     @pool_class.__send__(:include, pl::PoolMethods)
322   end
323   # extend connection class
324   if defined?(pl::ConnectionMethods)
325     @connection_class = @connection_class.dup
326     SET_TEMPORARY_NAME[@connection_class, pl]
327     @connection_class.__send__(:include, pl::ConnectionMethods)
328   end
329   # extend http1 class
330   if defined?(pl::HTTP1Methods)
331     @http1_class = @http1_class.dup
332     SET_TEMPORARY_NAME[@http1_class, pl]
333     @http1_class.__send__(:include, pl::HTTP1Methods)
334   end
335   # extend http2 class
336   if defined?(pl::HTTP2Methods)
337     @http2_class = @http2_class.dup
338     SET_TEMPORARY_NAME[@http2_class, pl]
339     @http2_class.__send__(:include, pl::HTTP2Methods)
340   end
341   # extend native resolver class
342   if defined?(pl::ResolverNativeMethods)
343     @resolver_native_class = @resolver_native_class.dup
344     SET_TEMPORARY_NAME[@resolver_native_class, pl]
345     @resolver_native_class.__send__(:include, pl::ResolverNativeMethods)
346   end
347   # extend system resolver class
348   if defined?(pl::ResolverSystemMethods)
349     @resolver_system_class = @resolver_system_class.dup
350     SET_TEMPORARY_NAME[@resolver_system_class, pl]
351     @resolver_system_class.__send__(:include, pl::ResolverSystemMethods)
352   end
353   # extend https resolver class
354   if defined?(pl::ResolverHTTPSMethods)
355     @resolver_https_class = @resolver_https_class.dup
356     SET_TEMPORARY_NAME[@resolver_https_class, pl]
357     @resolver_https_class.__send__(:include, pl::ResolverHTTPSMethods)
358   end
359 
360   return unless defined?(pl::OptionsMethods)
361 
362   # extend option class
363   # works around lack of initialize_dup callback
364   @options_class = @options_class.dup
365   # (self.class.options_names)
366   @options_class.__send__(:include, pl::OptionsMethods)
367 end
freeze()
[show source]
    # File lib/httpx/options.rb
188 def freeze
189   self.class.options_names.each do |ivar|
190     # avoid freezing debug option, as when it's set, it's usually an
191     # object which cannot be frozen, like stderr or stdout. It's a
192     # documented exception then, and still does not defeat the purpose
193     # here, which is to make option objects shareable across ractors,
194     # and in most cases debug should be nil, or one of the objects
195     # which will eventually be shareable, like STDOUT or STDERR.
196     next if ivar == :debug
197 
198     instance_variable_get(:"@#{ivar}").freeze
199   end
200   super
201 end
merge(other)

returns a HTTPX::Options instance resulting of the merging of other with self. it may return self if other is self or equal to self.

[show source]
    # File lib/httpx/options.rb
227 def merge(other)
228   if (is_options = other.is_a?(Options))
229 
230     return self if eql?(other)
231 
232     opts_names = other.class.options_names
233 
234     return self if opts_names.all? { |opt| public_send(opt) == other.public_send(opt) }
235 
236     other_opts = opts_names
237   else
238     other_opts = other # : Hash[Symbol, untyped]
239     other_opts = Hash[other] unless other.is_a?(Hash)
240 
241     return self if other_opts.empty?
242 
243     return self if other_opts.all? { |opt, v| !respond_to?(opt) || public_send(opt) == v }
244   end
245 
246   opts = dup
247 
248   other_opts.each do |opt, v|
249     next unless respond_to?(opt)
250 
251     v = other.public_send(opt) if is_options
252     ivar = :"@#{opt}"
253 
254     unless v
255       opts.instance_variable_set(ivar, v)
256       next
257     end
258 
259     v = opts.__send__(:"option_#{opt}", v)
260 
261     orig_v = public_send(opt)
262 
263     v = orig_v.merge(v) if orig_v.respond_to?(:merge) && v.respond_to?(:merge)
264 
265     opts.instance_variable_set(ivar, v)
266   end
267 
268   opts
269 end
options_equals?(other, ignore_ivars = REQUEST_BODY_IVARS)

checks whether other is equal by comparing the session options

[show source]
    # File lib/httpx/options.rb
210 def options_equals?(other, ignore_ivars = REQUEST_BODY_IVARS)
211   # headers and other request options do not play a role, as they are
212   # relevant only for the request.
213   ivars = instance_variables - ignore_ivars
214   other_ivars = other.instance_variables - ignore_ivars
215 
216   return false if ivars.size != other_ivars.size
217 
218   return false if ivars.sort != other_ivars.sort
219 
220   ivars.all? do |ivar|
221     instance_variable_get(ivar) == other.instance_variable_get(ivar)
222   end
223 end
resolver_cache()
[show source]
    # File lib/httpx/options.rb
168 def resolver_cache
169   cache_type = @resolver_cache
170 
171   case cache_type
172   when :memory
173     Resolver::Cache::Memory.cache(cache_type)
174   when :file
175     Resolver::Cache::File.cache(cache_type)
176   else
177     unless cache_type.respond_to?(:resolve) &&
178            cache_type.respond_to?(:get) &&
179            cache_type.respond_to?(:set) &&
180            cache_type.respond_to?(:evict)
181       raise TypeError, ":resolver_cache must be a compatible resolver cache and implement #get, #set and #evict"
182     end
183 
184     cache_type #: Object & Resolver::_Cache
185   end
186 end
resolver_class()

returns the class with which to instantiate the DNS resolver.

[show source]
    # File lib/httpx/options.rb
159 def resolver_class
160   case @resolver_class
161   when Symbol
162     public_send(:"resolver_#{@resolver_class}_class")
163   else
164     @resolver_class
165   end
166 end
to_hash()
[show source]
    # File lib/httpx/options.rb
271 def to_hash
272   instance_variables.each_with_object({}) do |ivar, hs|
273     val = instance_variable_get(ivar)
274 
275     next if val.nil?
276 
277     hs[ivar[1..-1].to_sym] = val
278   end
279 end