Class: HTTPX::Connection
- Inherits:
-
Object
- Object
- HTTPX::Connection
- Extended by:
- Forwardable
- Defined in:
- lib/httpx/connection.rb
Overview
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.
Defined Under Namespace
Constant Summary collapse
- BUFFER_SIZE =
1 << 14
Constants included from Loggable
Constants included from Registry
Instance Attribute Summary collapse
-
#options ⇒ Object
readonly
Returns the value of attribute options.
-
#origin ⇒ Object
readonly
Returns the value of attribute origin.
-
#pending ⇒ Object
readonly
Returns the value of attribute pending.
-
#state ⇒ Object
readonly
Returns the value of attribute state.
-
#timeout ⇒ Object
readonly
Returns the value of attribute timeout.
Instance Method Summary collapse
- #addresses ⇒ Object
-
#addresses=(addrs) ⇒ Object
this is a semi-private method, to be used by the resolver to initiate the io object.
- #call ⇒ Object
- #close ⇒ Object
-
#coalescable?(connection) ⇒ Boolean
coalescable connections need to be mergeable! but internally, #mergeable? is called before #coalescable?.
- #connecting? ⇒ Boolean
- #inflight? ⇒ Boolean
-
#initialize(type, uri, options) ⇒ Connection
constructor
A new instance of Connection.
- #interests ⇒ Object
- #match?(uri, options) ⇒ Boolean
-
#match_altsvcs?(uri) ⇒ Boolean
checks if this is connection is an alternative service of
uri. - #merge(connection) ⇒ Object
- #mergeable?(connection) ⇒ Boolean
- #purge_pending ⇒ Object
- #reset ⇒ Object
- #send(request) ⇒ Object
- #to_io ⇒ Object
- #unmerge(connection) ⇒ Object
Methods included from Callbacks
Methods included from Loggable
Methods included from Registry
Constructor Details
#initialize(type, uri, options) ⇒ Connection
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/httpx/connection.rb', line 51 def initialize(type, uri, ) @type = type @origins = [uri.origin] @origin = URI(uri.origin) = Options.new() @window_size = .window_size @read_buffer = Buffer.new(BUFFER_SIZE) @write_buffer = Buffer.new(BUFFER_SIZE) @pending = [] on(:error, &method(:on_error)) if .io # if there's an already open IO, get its # peer address, and force-initiate the parser transition(:already_open) @io = IO.registry(@type).new(@origin, nil, ) parser else transition(:idle) end end |
Instance Attribute Details
#options ⇒ Object (readonly)
Returns the value of attribute options.
47 48 49 |
# File 'lib/httpx/connection.rb', line 47 def end |
#origin ⇒ Object (readonly)
Returns the value of attribute origin.
47 48 49 |
# File 'lib/httpx/connection.rb', line 47 def origin @origin end |
#pending ⇒ Object (readonly)
Returns the value of attribute pending.
47 48 49 |
# File 'lib/httpx/connection.rb', line 47 def pending @pending end |
#state ⇒ Object (readonly)
Returns the value of attribute state.
47 48 49 |
# File 'lib/httpx/connection.rb', line 47 def state @state end |
#timeout ⇒ Object (readonly)
Returns the value of attribute timeout.
49 50 51 |
# File 'lib/httpx/connection.rb', line 49 def timeout @timeout end |
Instance Method Details
#addresses ⇒ Object
78 79 80 |
# File 'lib/httpx/connection.rb', line 78 def addresses @io && @io.addresses end |
#addresses=(addrs) ⇒ Object
this is a semi-private method, to be used by the resolver to initiate the io object.
74 75 76 |
# File 'lib/httpx/connection.rb', line 74 def addresses=(addrs) @io ||= IO.registry(@type).new(@origin, addrs, ) # rubocop:disable Naming/MemoizedInstanceVariableName end |
#call ⇒ Object
190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
# File 'lib/httpx/connection.rb', line 190 def call @timeout = @timeout_threshold case @state when :closed return when :closing dwrite transition(:closed) emit(:close) when :open consume end nil end |
#close ⇒ Object
168 169 170 171 |
# File 'lib/httpx/connection.rb', line 168 def close @parser.close if @parser transition(:closing) end |
#coalescable?(connection) ⇒ Boolean
coalescable connections need to be mergeable! but internally, #mergeable? is called before #coalescable?
96 97 98 99 100 101 102 |
# File 'lib/httpx/connection.rb', line 96 def coalescable?(connection) if @io.protocol == "h2" && @origin.scheme == "https" @io.verify_hostname(connection.origin.host) else @origin == connection.origin end end |
#connecting? ⇒ Boolean
140 141 142 |
# File 'lib/httpx/connection.rb', line 140 def connecting? @state == :idle end |
#inflight? ⇒ Boolean
144 145 146 |
# File 'lib/httpx/connection.rb', line 144 def inflight? @parser && !@parser.empty? && !@write_buffer.empty? end |
#interests ⇒ Object
148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/httpx/connection.rb', line 148 def interests return :w if @state == :idle readable = !@read_buffer.full? writable = !@write_buffer.empty? if readable writable ? :rw : :r else writable ? :w : :r end end |
#match?(uri, options) ⇒ Boolean
82 83 84 85 86 |
# File 'lib/httpx/connection.rb', line 82 def match?(uri, ) return false if @state == :closing || @state == :closed (@origins.include?(uri.origin) || match_altsvcs?(uri)) && == end |
#match_altsvcs?(uri) ⇒ Boolean
checks if this is connection is an alternative service of uri
133 134 135 136 137 138 |
# File 'lib/httpx/connection.rb', line 133 def match_altsvcs?(uri) AltSvc.cached_altsvc(@origin).any? do |altsvc| origin = altsvc["origin"] origin.altsvc_match?(uri.origin) end end |
#merge(connection) ⇒ Object
104 105 106 107 108 109 110 |
# File 'lib/httpx/connection.rb', line 104 def merge(connection) @origins += connection.instance_variable_get(:@origins) pending = connection.instance_variable_get(:@pending) pending.each do |req, args| send(req, args) end end |
#mergeable?(connection) ⇒ Boolean
88 89 90 91 92 |
# File 'lib/httpx/connection.rb', line 88 def mergeable?(connection) return false if @state == :closing || @state == :closed || !@io !(@io.addresses & connection.addresses).empty? && == connection. end |
#purge_pending ⇒ Object
123 124 125 126 127 128 129 |
# File 'lib/httpx/connection.rb', line 123 def purge_pending [@parser.pending, @pending].each do |pending| pending.reject! do |request, *args| yield(request, args) end end end |
#reset ⇒ Object
173 174 175 176 177 |
# File 'lib/httpx/connection.rb', line 173 def reset transition(:closing) transition(:closed) emit(:close) end |
#send(request) ⇒ Object
179 180 181 182 183 184 185 186 187 188 |
# File 'lib/httpx/connection.rb', line 179 def send(request) if @error_response emit(:response, request, @error_response) elsif @parser && !@write_buffer.full? request.headers["alt-used"] = @origin. if match_altsvcs?(request.uri) parser.send(request) else @pending << request end end |
#to_io ⇒ Object
160 161 162 163 164 165 166 |
# File 'lib/httpx/connection.rb', line 160 def to_io case @state when :idle transition(:open) end @io.to_io end |
#unmerge(connection) ⇒ Object
112 113 114 115 116 117 118 119 120 121 |
# File 'lib/httpx/connection.rb', line 112 def unmerge(connection) @origins -= connection.instance_variable_get(:@origins) purge_pending do |request| request.uri.origin == connection.origin && begin request.transition(:idle) connection.send(request) true end end end |