class HTTPX::Session

  1. lib/httpx/session.rb
Superclass: Object

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

Included modules

  1. Loggable
  2. Chainable

Public Instance Aliases

select_resolver -> select_connection

Public Class methods

new(options = EMPTY_HASH, &blk)

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.

[show source]
   # File lib/httpx/session.rb
16 def initialize(options = EMPTY_HASH, &blk)
17   @options = self.class.default_options.merge(options)
18   @responses = {}
19   @persistent = @options.persistent
20   @pool = @options.pool_class.new(@options.pool_options)
21   @wrapped = false
22   @closing = false
23   wrap(&blk) if blk
24 end

Public Instance methods

build_request(verb, uri, params = EMPTY_HASH, options = @options)

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)
[show source]
    # File lib/httpx/session.rb
120 def build_request(verb, uri, params = EMPTY_HASH, options = @options)
121   rklass = options.request_class
122   request = rklass.new(verb, uri, options, params)
123   request.persistent = @persistent
124   set_request_callbacks(request)
125   request
126 end
close(selector = Selector.new)

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.

[show source]
   # 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     connection.current_session = self
73     connection.current_selector = selector
74     select_connection(connection, selector)
75   end
76   begin
77     @closing = true
78     selector.terminate
79   ensure
80     @closing = false
81   end
82 end
deselect_connection(connection, selector, cloned = false)
[show source]
    # File lib/httpx/session.rb
134 def deselect_connection(connection, selector, cloned = false)
135   selector.deregister(connection)
136 
137   # when connections coalesce
138   return if connection.state == :idle
139 
140   return if cloned
141 
142   return if @closing && connection.state == :closed
143 
144   @pool.checkin_connection(connection)
145 end
deselect_resolver(resolver, selector)
[show source]
    # File lib/httpx/session.rb
147 def deselect_resolver(resolver, selector)
148   selector.deregister(resolver)
149 
150   return if @closing && resolver.closed?
151 
152   @pool.checkin_resolver(resolver)
153 end
find_connection(request_uri, selector, options)

returns the HTTPX::Connection through which the request should be sent through.

[show source]
    # File lib/httpx/session.rb
199 def find_connection(request_uri, selector, options)
200   if (connection = selector.find_connection(request_uri, options))
201     return connection
202   end
203 
204   connection = @pool.checkout_connection(request_uri, options)
205 
206   connection.current_session = self
207   connection.current_selector = selector
208 
209   case connection.state
210   when :idle
211     do_init_connection(connection, selector)
212   when :open
213     select_connection(connection, selector) if options.io
214   when :closed
215     connection.idling
216     select_connection(connection, selector)
217   when :closing
218     connection.once(:close) do
219       connection.idling
220       select_connection(connection, selector)
221     end
222   end
223 
224   connection
225 end
request(*args, **params)

performs one, or multple requests; it accepts:

  1. one or multiple HTTPX::Request objects;

  2. an HTTP verb, then a sequence of URIs or URI/options tuples;

  3. 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" })
[show source]
    # File lib/httpx/session.rb
104 def request(*args, **params)
105   raise ArgumentError, "must perform at least one request" if args.empty?
106 
107   requests = args.first.is_a?(Request) ? args : build_requests(*args, params)
108   responses = send_requests(*requests)
109   return responses.first if responses.size == 1
110 
111   responses
112 end
select_connection(connection, selector)
[show source]
    # File lib/httpx/session.rb
128 def select_connection(connection, selector)
129   selector.register(connection)
130 end
try_clone_connection(connection, selector, family)
[show source]
    # File lib/httpx/session.rb
155 def try_clone_connection(connection, selector, family)
156   connection.family ||= family
157 
158   return connection if connection.family == family
159 
160   new_connection = connection.class.new(connection.origin, connection.options)
161 
162   new_connection.family = family
163   new_connection.current_session = self
164   new_connection.current_selector = selector
165 
166   connection.once(:tcp_open) { new_connection.force_reset(true) }
167   connection.once(:connect_error) do |err|
168     if new_connection.connecting?
169       new_connection.merge(connection)
170       connection.emit(:cloned, new_connection)
171       connection.force_reset(true)
172     else
173       connection.__send__(:handle_error, err)
174     end
175   end
176 
177   new_connection.once(:tcp_open) do |new_conn|
178     if new_conn != connection
179       new_conn.merge(connection)
180       connection.force_reset(true)
181     end
182   end
183   new_connection.once(:connect_error) do |err|
184     if connection.connecting?
185       # main connection has the requests
186       connection.merge(new_connection)
187       new_connection.emit(:cloned, connection)
188       new_connection.force_reset(true)
189     else
190       new_connection.__send__(:handle_error, err)
191     end
192   end
193 
194   do_init_connection(new_connection, selector)
195   new_connection
196 end
wrap()

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
[show source]
   # 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