class HTTPX::Connection

  1. lib/httpx/connection.rb
  2. lib/httpx/connection/http1.rb
  3. lib/httpx/connection/http2.rb
  4. show all
Superclass: Object

The Connection can be watched for IO events.

It contains the io object to read/write from, and knows what to do when it can.

It defers connecting until absolutely necessary. Connection should be triggered from the IO selector (until then, any request will be queued).

A connection boots up its parser after connection is established. All pending requests will be redirected there after connection.

A connection can be prevented from closing by the parser, that is, if there are pending requests. This will signal that the connection was prematurely closed, due to a possible number of conditions:

  • Remote peer closed the connection (“Connection: close”);

  • Remote peer doesn't support pipelining;

A connection may also route requests for a different host for which the io was connected to, provided that the IP is the same and the port and scheme as well. This will allow to share the same socket to send HTTP/2 requests to different hosts.

Included modules

  1. Registry
  2. Loggable
  3. Callbacks

Constants

BUFFER_SIZE = 1 << 14  

Attributes

options [R]
origin [R]
pending [R]
state [R]
timers [W]

Public Class methods

new (type, uri, options)
[show source]
   # File lib/httpx/connection.rb
51 def initialize(type, uri, options)
52   @type = type
53   @origins = [uri.origin]
54   @origin = URI(uri.origin)
55   @options = Options.new(options)
56   @window_size = @options.window_size
57   @read_buffer = Buffer.new(BUFFER_SIZE)
58   @write_buffer = Buffer.new(BUFFER_SIZE)
59   @pending = []
60   on(:error, &method(:on_error))
61   if @options.io
62     # if there's an already open IO, get its
63     # peer address, and force-initiate the parser
64     transition(:already_open)
65     @io = IO.registry(@type).new(@origin, nil, @options)
66     parser
67   else
68     transition(:idle)
69   end
70 end

Public Instance methods

addresses ()
[show source]
   # File lib/httpx/connection.rb
78 def addresses
79   @io && @io.addresses
80 end
addresses= (addrs)

this is a semi-private method, to be used by the resolver to initiate the io object.

[show source]
   # File lib/httpx/connection.rb
74 def addresses=(addrs)
75   @io ||= IO.registry(@type).new(@origin, addrs, @options) # rubocop:disable Naming/MemoizedInstanceVariableName
76 end
call ()
[show source]
    # File lib/httpx/connection.rb
204 def call
205   case @state
206   when :closed
207     return
208   when :closing
209     dwrite
210     transition(:closed)
211     emit(:close)
212   when :open
213     consume
214   end
215   nil
216 end
close ()
[show source]
    # File lib/httpx/connection.rb
184 def close
185   @parser.close if @parser
186   transition(:closing)
187 end
coalescable? (connection)

coalescable connections need to be mergeable! but internally, mergeable? is called before coalescable?

[show source]
    # File lib/httpx/connection.rb
109 def coalescable?(connection)
110   if @io.protocol == "h2" &&
111      @origin.scheme == "https" &&
112      connection.origin.scheme == "https"
113     @io.verify_hostname(connection.origin.host)
114   else
115     @origin == connection.origin
116   end
117 end
connecting? ()
[show source]
    # File lib/httpx/connection.rb
162 def connecting?
163   @state == :idle
164 end
create_idle ()
[show source]
    # File lib/httpx/connection.rb
119 def create_idle
120   self.class.new(@type, @origin, @options)
121 end
inflight? ()
[show source]
    # File lib/httpx/connection.rb
166 def inflight?
167   @parser && !@parser.empty? && !@write_buffer.empty?
168 end
interests ()
[show source]
    # File lib/httpx/connection.rb
170 def interests
171   return :w if @state == :idle
172 
173   :rw
174 end
match? (uri, options)
[show source]
   # File lib/httpx/connection.rb
82 def match?(uri, options)
83   return false if @state == :closing || @state == :closed
84 
85   return false if exhausted?
86 
87   (
88     (
89       @origins.include?(uri.origin) &&
90       # if there is more than one origin to match, it means that this connection
91       # was the result of coalescing. To prevent blind trust in the case where the
92       # origin came from an ORIGIN frame, we're going to verify the hostname with the
93       # SSL certificate
94       (@origins.size == 1 || @origin == uri.origin || (@io && @io.verify_hostname(uri.host)))
95     ) || match_altsvcs?(uri)
96   ) && @options == options
97 end
match_altsvcs? (uri)

checks if this is connection is an alternative service of uri

[show source]
    # File lib/httpx/connection.rb
154 def match_altsvcs?(uri)
155   @origins.any? { |origin| uri.altsvc_match?(origin) } ||
156     AltSvc.cached_altsvc(@origin).any? do |altsvc|
157       origin = altsvc["origin"]
158       origin.altsvc_match?(uri.origin)
159     end
160 end
merge (connection)
[show source]
    # File lib/httpx/connection.rb
123 def merge(connection)
124   @origins += connection.instance_variable_get(:@origins)
125   connection.purge_pending do |req|
126     send(req)
127   end
128 end
mergeable? (connection)
[show source]
    # File lib/httpx/connection.rb
 99 def mergeable?(connection)
100   return false if @state == :closing || @state == :closed || !@io
101 
102   return false if exhausted?
103 
104   !(@io.addresses & connection.addresses).empty? && @options == connection.options
105 end
purge_pending ()
[show source]
    # File lib/httpx/connection.rb
141 def purge_pending
142   pendings = []
143   pendings << @parser.pending if @parser
144   pendings << @pending
145   pendings.each do |pending|
146     pending.reject! do |request|
147       yield request
148     end
149   end
150 end
reset ()
[show source]
    # File lib/httpx/connection.rb
189 def reset
190   transition(:closing)
191   transition(:closed)
192   emit(:close)
193 end
send (request)
[show source]
    # File lib/httpx/connection.rb
195 def send(request)
196   if @parser && !@write_buffer.full?
197     request.headers["alt-used"] = @origin.authority if match_altsvcs?(request.uri)
198     parser.send(request)
199   else
200     @pending << request
201   end
202 end
timeout ()
[show source]
    # File lib/httpx/connection.rb
218 def timeout
219   return @timeout if defined?(@timeout)
220 
221   return @options.timeout.connect_timeout if @state == :idle
222 
223   @options.timeout.operation_timeout
224 end
to_io ()
[show source]
    # File lib/httpx/connection.rb
176 def to_io
177   case @state
178   when :idle
179     transition(:open)
180   end
181   @io.to_io
182 end
unmerge (connection)
[show source]
    # File lib/httpx/connection.rb
130 def unmerge(connection)
131   @origins -= connection.instance_variable_get(:@origins)
132   purge_pending do |request|
133     request.uri.origin == connection.origin && begin
134       request.transition(:idle)
135       connection.send(request)
136       true
137     end
138   end
139 end