Class implementing the APIs being used publicly.
HTTPX.get(..) #=> delegating to an internal HTTPX::Session object. HTTPX.plugin(..).get(..) #=> creating an intermediate HTTPX::Session with plugin, then sending the GET request
Methods
Public Class
Public Instance
Constants
INSTANCES | = | ObjectSpace::WeakMap.new |
Public Instance Aliases
select_resolver | -> | select_connection |
Attributes
default_options | [R] |
Public Class methods
# File lib/httpx/session.rb 523 def self.after_fork 524 INSTANCES.each_value(&:close) 525 nil 526 end
# File lib/httpx/session.rb 436 def inherited(klass) 437 super 438 klass.instance_variable_set(:@default_options, @default_options) 439 klass.instance_variable_set(:@plugins, @plugins.dup) 440 klass.instance_variable_set(:@callbacks, @callbacks.dup) 441 end
initializes the session with a set of options
, which will be shared by all requests sent from it.
When pass a block, it’ll yield itself to it, then closes after the block is evaluated.
# File lib/httpx/session.rb 16 def initialize(options = EMPTY_HASH, &blk) 17 @options = self.class.default_options.merge(options) 18 @persistent = @options.persistent 19 @pool = @options.pool_class.new(@options.pool_options) 20 @wrapped = false 21 @closing = false 22 INSTANCES[self] = self if @persistent && @options.close_on_fork && INSTANCES 23 wrap(&blk) if blk 24 end
returns a new HTTPX::Session
instance, with the plugin pointed by pl
loaded.
session_with_retries = session.plugin(:retries) session_with_custom = session.plugin(CustomPlugin)
# File lib/httpx/session.rb 448 def plugin(pl, options = nil, &block) 449 label = pl 450 # raise Error, "Cannot add a plugin to a frozen config" if frozen? 451 pl = Plugins.load_plugin(pl) if pl.is_a?(Symbol) 452 if !@plugins.include?(pl) 453 @plugins << pl 454 pl.load_dependencies(self, &block) if pl.respond_to?(:load_dependencies) 455 456 @default_options = @default_options.dup 457 458 include(pl::InstanceMethods) if defined?(pl::InstanceMethods) 459 extend(pl::ClassMethods) if defined?(pl::ClassMethods) 460 461 opts = @default_options 462 opts.extend_with_plugin_classes(pl) 463 if defined?(pl::OptionsMethods) 464 465 (pl::OptionsMethods.instance_methods - Object.instance_methods).each do |meth| 466 opts.options_class.method_added(meth) 467 end 468 @default_options = opts.options_class.new(opts) 469 end 470 471 @default_options = pl.extra_options(@default_options) if pl.respond_to?(:extra_options) 472 @default_options = @default_options.merge(options) if options 473 474 if pl.respond_to?(:subplugins) 475 pl.subplugins.transform_keys(&Plugins.method(:load_plugin)).each do |main_pl, sub_pl| 476 # in case the main plugin has already been loaded, then apply subplugin functionality 477 # immediately 478 next unless @plugins.include?(main_pl) 479 480 plugin(sub_pl, options, &block) 481 end 482 end 483 484 pl.configure(self, &block) if pl.respond_to?(:configure) 485 486 if label.is_a?(Symbol) 487 # in case an already-loaded plugin complements functionality of 488 # the plugin currently being loaded, loaded it now 489 @plugins.each do |registered_pl| 490 next if registered_pl == pl 491 492 next unless registered_pl.respond_to?(:subplugins) 493 494 sub_pl = registered_pl.subplugins[label] 495 496 next unless sub_pl 497 498 plugin(sub_pl, options, &block) 499 end 500 end 501 502 @default_options.freeze 503 set_temporary_name("#{superclass}/#{pl}") if respond_to?(:set_temporary_name) # ruby 3.4 only 504 elsif options 505 # this can happen when two plugins are loaded, an one of them calls the other under the hood, 506 # albeit changing some default. 507 @default_options = pl.extra_options(@default_options) if pl.respond_to?(:extra_options) 508 @default_options = @default_options.merge(options) if options 509 510 @default_options.freeze 511 end 512 513 self 514 end
Public Instance methods
returns a HTTP::Request instance built from the HTTP verb
, the request uri
, and the optional set of request-specific options
. This request must be sent through the same session it was built from.
req = session.build_request("GET", "https://server.com") resp = session.request(req)
# File lib/httpx/session.rb 118 def build_request(verb, uri, params = EMPTY_HASH, options = @options) 119 rklass = options.request_class 120 request = rklass.new(verb, uri, options, params) 121 request.persistent = @persistent 122 set_request_callbacks(request) 123 request 124 end
closes all the active connections from the session.
when called directly without specifying selector
, all available connections will be picked up from the connection pool and closed. Connections in use by other sessions, or same session in a different thread, will not be reaped.
# File lib/httpx/session.rb 64 def close(selector = Selector.new) 65 # throw resolvers away from the pool 66 @pool.reset_resolvers 67 68 # preparing to throw away connections 69 while (connection = @pool.pop_connection) 70 next if connection.state == :closed 71 72 select_connection(connection, selector) 73 end 74 begin 75 @closing = true 76 selector.terminate 77 ensure 78 @closing = false 79 end 80 end
# File lib/httpx/session.rb 138 def deselect_connection(connection, selector, cloned = false) 139 selector.deregister(connection) 140 141 # when connections coalesce 142 return if connection.state == :idle 143 144 return if cloned 145 146 return if @closing && connection.state == :closed 147 148 @pool.checkin_connection(connection) 149 end
# File lib/httpx/session.rb 151 def deselect_resolver(resolver, selector) 152 selector.deregister(resolver) 153 154 return if @closing && resolver.closed? 155 156 @pool.checkin_resolver(resolver) 157 end
returns the HTTPX::Connection
through which the request
should be sent through.
# File lib/httpx/session.rb 175 def find_connection(request_uri, selector, options) 176 if (connection = selector.find_connection(request_uri, options)) 177 return connection 178 end 179 180 connection = @pool.checkout_connection(request_uri, options) 181 182 case connection.state 183 when :idle 184 do_init_connection(connection, selector) 185 when :open 186 if options.io 187 select_connection(connection, selector) 188 else 189 pin_connection(connection, selector) 190 end 191 when :closing, :closed 192 connection.idling 193 select_connection(connection, selector) 194 else 195 pin_connection(connection, selector) 196 end 197 198 connection 199 end
# File lib/httpx/session.rb 131 def pin_connection(connection, selector) 132 connection.current_session = self 133 connection.current_selector = selector 134 end
performs one, or multple requests; it accepts:
-
one or multiple
HTTPX::Request
objects; -
an HTTP verb, then a sequence of URIs or URI/options tuples;
-
one or multiple HTTP verb / uri / (optional) options tuples;
when present, the set of options
kwargs is applied to all of the sent requests.
respectively returns a single HTTPX::Response
response, or all of them in an Array, in the same order.
resp1 = session.request(req1) resp1, resp2 = session.request(req1, req2) resp1 = session.request("GET", "https://server.org/a") resp1, resp2 = session.request("GET", ["https://server.org/a", "https://server.org/b"]) resp1, resp2 = session.request(["GET", "https://server.org/a"], ["GET", "https://server.org/b"]) resp1 = session.request("POST", "https://server.org/a", form: { "foo" => "bar" }) resp1, resp2 = session.request(["POST", "https://server.org/a", form: { "foo" => "bar" }], ["GET", "https://server.org/b"]) resp1, resp2 = session.request("GET", ["https://server.org/a", "https://server.org/b"], headers: { "x-api-token" => "TOKEN" })
# File lib/httpx/session.rb 102 def request(*args, **params) 103 raise ArgumentError, "must perform at least one request" if args.empty? 104 105 requests = args.first.is_a?(Request) ? args : build_requests(*args, params) 106 responses = send_requests(*requests) 107 return responses.first if responses.size == 1 108 109 responses 110 end
# File lib/httpx/session.rb 126 def select_connection(connection, selector) 127 pin_connection(connection, selector) 128 selector.register(connection) 129 end
# File lib/httpx/session.rb 159 def try_clone_connection(connection, selector, family) 160 connection.family ||= family 161 162 return connection if connection.family == family 163 164 new_connection = connection.class.new(connection.origin, connection.options) 165 166 new_connection.family = family 167 168 connection.sibling = new_connection 169 170 do_init_connection(new_connection, selector) 171 new_connection 172 end
Yields itself the block, then closes it after the block is evaluated.
session.wrap do |http| http.get("https://wikipedia.com") end # wikipedia connection closes here
# File lib/httpx/session.rb 31 def wrap 32 prev_wrapped = @wrapped 33 @wrapped = true 34 was_initialized = false 35 current_selector = get_current_selector do 36 selector = Selector.new 37 38 set_current_selector(selector) 39 40 was_initialized = true 41 42 selector 43 end 44 begin 45 yield self 46 ensure 47 unless prev_wrapped 48 if @persistent 49 deactivate(current_selector) 50 else 51 close(current_selector) 52 end 53 end 54 @wrapped = prev_wrapped 55 set_current_selector(nil) if was_initialized 56 end 57 end