httpx 0.12.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/doc/release_notes/0_13_0.md +58 -0
- data/lib/httpx/chainable.rb +2 -2
- data/lib/httpx/connection.rb +17 -13
- data/lib/httpx/connection/http1.rb +4 -2
- data/lib/httpx/connection/http2.rb +1 -1
- data/lib/httpx/io/ssl.rb +30 -17
- data/lib/httpx/io/tcp.rb +45 -26
- data/lib/httpx/io/unix.rb +27 -12
- data/lib/httpx/options.rb +11 -23
- data/lib/httpx/plugins/compression.rb +20 -8
- data/lib/httpx/plugins/compression/brotli.rb +8 -6
- data/lib/httpx/plugins/compression/deflate.rb +2 -2
- data/lib/httpx/plugins/compression/gzip.rb +2 -2
- data/lib/httpx/plugins/digest_authentication.rb +1 -1
- data/lib/httpx/plugins/follow_redirects.rb +1 -1
- data/lib/httpx/plugins/h2c.rb +43 -58
- data/lib/httpx/plugins/internal_telemetry.rb +1 -1
- data/lib/httpx/plugins/retries.rb +1 -1
- data/lib/httpx/plugins/stream.rb +3 -1
- data/lib/httpx/plugins/upgrade.rb +83 -0
- data/lib/httpx/plugins/upgrade/h2.rb +54 -0
- data/lib/httpx/pool.rb +14 -5
- data/lib/httpx/response.rb +5 -5
- data/lib/httpx/version.rb +1 -1
- data/sig/chainable.rbs +2 -1
- data/sig/connection/http1.rbs +1 -0
- data/sig/options.rbs +7 -20
- data/sig/plugins/aws_sigv4.rbs +0 -1
- data/sig/plugins/compression.rbs +5 -3
- data/sig/plugins/compression/brotli.rbs +1 -1
- data/sig/plugins/compression/deflate.rbs +1 -1
- data/sig/plugins/compression/gzip.rbs +1 -1
- data/sig/plugins/cookies.rbs +0 -1
- data/sig/plugins/digest_authentication.rbs +0 -1
- data/sig/plugins/expect.rbs +0 -2
- data/sig/plugins/follow_redirects.rbs +0 -2
- data/sig/plugins/h2c.rbs +5 -10
- data/sig/plugins/persistent.rbs +0 -1
- data/sig/plugins/proxy.rbs +0 -1
- data/sig/plugins/retries.rbs +0 -4
- data/sig/plugins/upgrade.rbs +23 -0
- data/sig/response.rbs +3 -1
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ecaac1dac4ce953ba1585a418432d9bf635aea581a6d81acb32778ff947f486b
|
4
|
+
data.tar.gz: 32d9c5f65bd18ceeab524c6734081740ea2a3cbe526d3a6a71e079846f047644
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 204b0aea0e3bc09eccd31c9b93c79de866cff737801bca75096a61ea3ff45e62d44b2e9d39e26e3fb34d261dc518e17766080549f55b1cf0e16cfcd55565ddb4
|
7
|
+
data.tar.gz: ffc06e694b6afd9e29d48857c0251b75829d41637583f45243dd7b30931f0b9a4f8bf06d13421e94dc5f07bf5113ff0f9f2c888be6313c9506e6da05659392a1
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# 0.13.0
|
2
|
+
|
3
|
+
## Features
|
4
|
+
|
5
|
+
### Upgrade plugin
|
6
|
+
|
7
|
+
A new plugin, `:upgrade`, is now available. This plugin allows one to "hook" on HTTP/1.1's protocol upgrade mechanism (see: https://developer.mozilla.org/en-US/docs/Web/HTTP/Protocol_upgrade_mechanism), which is the mechanism that browsers use to initiate websockets (there is an example of how to use `httpx` to start a websocket client connection [in the tests](https://gitlab.com/honeyryderchuck/httpx/-/blob/master/test/support/requests/plugins/upgrade.rb))
|
8
|
+
|
9
|
+
You can read more about the `:upgrade` plugin in the [wiki](https://honeyryderchuck.gitlab.io/httpx/wiki/Connection-Upgrade).
|
10
|
+
|
11
|
+
It's the basis of two plugins:
|
12
|
+
|
13
|
+
#### `:h2c`
|
14
|
+
|
15
|
+
This plugin was been rewritten on top of the `:upgrade` plugin, and handles upgrading a plaintext (non-"https") HTTP/1.1 connection, into an HTTP/2 connection.
|
16
|
+
|
17
|
+
https://honeyryderchuck.gitlab.io/httpx/wiki/Connection-Upgrade#h2c
|
18
|
+
|
19
|
+
#### `:upgrade/h2`
|
20
|
+
|
21
|
+
This plugin handles when a server responds to a request with an `Upgrade: h2` header, does the following requests to the same origin via HTTP/2 prior knowledge (bypassing the necessity for ALPN negotiation, which is the whole point of the feature).
|
22
|
+
|
23
|
+
https://honeyryderchuck.gitlab.io/httpx/wiki/Connection-Upgrade#h2
|
24
|
+
|
25
|
+
### `:addresses` option
|
26
|
+
|
27
|
+
The `:addresses` option is now available. You can use it to pass a list of IPs to connect to:
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
# will not resolve example.com, and instead connect to one of the IPs passed.
|
31
|
+
HTTPX.get("http://example.com", addresses: %w[172.5.3.1 172.5.3.2]))
|
32
|
+
```
|
33
|
+
|
34
|
+
You should also use it to connect to HTTP servers bound to a UNIX socket, in which case you'll have to provide a path:
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
HTTPX.get("http://example.com", addresses: %w[/path/to/usocket]))
|
38
|
+
```
|
39
|
+
|
40
|
+
The `:transport_options` are therefore deprecated, and will be moved in a major version.
|
41
|
+
|
42
|
+
## Improvements
|
43
|
+
|
44
|
+
Some internal improvements that allow certainn plugins not to "leak" globally, such as the `:compression` plugin, which used to enable compression for all the `httpx` sessions from the same process. It doesn't anymore.
|
45
|
+
|
46
|
+
Using exceptionless nonblocking connect calls in the supported rubies.
|
47
|
+
|
48
|
+
Removed unneeded APIs around the Options object (`with_` methods, or the defined options list).
|
49
|
+
|
50
|
+
## Bugfixes
|
51
|
+
|
52
|
+
HTTP/1.1 persistent connections were closing after each request after the max requests was reached. It's fixed, and the new connection will also be persistent.
|
53
|
+
|
54
|
+
When passing open IO objects for origins (the `:io` option), `httpx` was still trying to resolve the origin's domain. This not only didn't make sense, it broke if the domain is unresolvable. It has been fixed.
|
55
|
+
|
56
|
+
Fixed usage of `:io` option when passed an "authority/io" hash.
|
57
|
+
|
58
|
+
Fixing some issues around trying to connnect to the next available IPAddress when the previous one was unreachable or ETIMEDOUT.
|
data/lib/httpx/chainable.rb
CHANGED
@@ -17,12 +17,12 @@ module HTTPX
|
|
17
17
|
# :nocov:
|
18
18
|
def timeout(**args)
|
19
19
|
warn ":#{__method__} is deprecated, use :with_timeout instead"
|
20
|
-
|
20
|
+
with(timeout: args)
|
21
21
|
end
|
22
22
|
|
23
23
|
def headers(headers)
|
24
24
|
warn ":#{__method__} is deprecated, use :with_headers instead"
|
25
|
-
|
25
|
+
with(headers: headers)
|
26
26
|
end
|
27
27
|
# :nocov:
|
28
28
|
|
data/lib/httpx/connection.rb
CHANGED
@@ -71,6 +71,8 @@ module HTTPX
|
|
71
71
|
@inflight = 0
|
72
72
|
@keep_alive_timeout = options.timeout.keep_alive_timeout
|
73
73
|
@keep_alive_timer = nil
|
74
|
+
|
75
|
+
self.addresses = options.addresses if options.addresses
|
74
76
|
end
|
75
77
|
|
76
78
|
# this is a semi-private method, to be used by the resolver
|
@@ -105,6 +107,8 @@ module HTTPX
|
|
105
107
|
|
106
108
|
return false if exhausted?
|
107
109
|
|
110
|
+
return false unless connection.addresses
|
111
|
+
|
108
112
|
!(@io.addresses & connection.addresses).empty? && @options == connection.options
|
109
113
|
end
|
110
114
|
|
@@ -472,26 +476,15 @@ module HTTPX
|
|
472
476
|
remove_instance_variable(:@total_timeout)
|
473
477
|
end
|
474
478
|
|
475
|
-
|
476
|
-
@read_buffer.clear
|
477
|
-
if @keep_alive_timer
|
478
|
-
@keep_alive_timer.cancel
|
479
|
-
remove_instance_variable(:@keep_alive_timer)
|
480
|
-
end
|
481
|
-
|
482
|
-
remove_instance_variable(:@timeout) if defined?(@timeout)
|
479
|
+
purge_after_closed
|
483
480
|
when :already_open
|
484
481
|
nextstate = :open
|
485
482
|
send_pending
|
486
483
|
end
|
487
484
|
@state = nextstate
|
488
|
-
rescue Errno::EHOSTUNREACH
|
489
|
-
# at this point, all addresses from the IO object have failed
|
490
|
-
reset
|
491
|
-
emit(:unreachable)
|
492
|
-
throw(:jump_tick)
|
493
485
|
rescue Errno::ECONNREFUSED,
|
494
486
|
Errno::EADDRNOTAVAIL,
|
487
|
+
Errno::EHOSTUNREACH,
|
495
488
|
TLSError => e
|
496
489
|
# connect errors, exit gracefully
|
497
490
|
handle_error(e)
|
@@ -499,6 +492,17 @@ module HTTPX
|
|
499
492
|
emit(:close)
|
500
493
|
end
|
501
494
|
|
495
|
+
def purge_after_closed
|
496
|
+
@io.close if @io
|
497
|
+
@read_buffer.clear
|
498
|
+
if @keep_alive_timer
|
499
|
+
@keep_alive_timer.cancel
|
500
|
+
remove_instance_variable(:@keep_alive_timer)
|
501
|
+
end
|
502
|
+
|
503
|
+
remove_instance_variable(:@timeout) if defined?(@timeout)
|
504
|
+
end
|
505
|
+
|
502
506
|
def handle_response
|
503
507
|
@inflight -= 1
|
504
508
|
return unless @inflight.zero?
|
@@ -10,7 +10,7 @@ module HTTPX
|
|
10
10
|
MAX_REQUESTS = 100
|
11
11
|
CRLF = "\r\n"
|
12
12
|
|
13
|
-
attr_reader :pending
|
13
|
+
attr_reader :pending, :requests
|
14
14
|
|
15
15
|
def initialize(buffer, options)
|
16
16
|
@options = Options.new(options)
|
@@ -69,7 +69,6 @@ module HTTPX
|
|
69
69
|
|
70
70
|
return if @requests.include?(request)
|
71
71
|
|
72
|
-
request.once(:headers, &method(:set_protocol_headers))
|
73
72
|
@requests << request
|
74
73
|
@pipelining = true if @requests.size > 1
|
75
74
|
end
|
@@ -236,6 +235,8 @@ module HTTPX
|
|
236
235
|
|
237
236
|
def disable_pipelining
|
238
237
|
return if @requests.empty?
|
238
|
+
# do not disable pipelining if already set to 1 request at a time
|
239
|
+
return if @max_concurrent_requests == 1
|
239
240
|
|
240
241
|
@requests.each do |r|
|
241
242
|
r.transition(:idle)
|
@@ -281,6 +282,7 @@ module HTTPX
|
|
281
282
|
log(color: :yellow) { "<- HEADLINE: #{buffer.chomp.inspect}" }
|
282
283
|
@buffer << buffer
|
283
284
|
buffer.clear
|
285
|
+
set_protocol_headers(request)
|
284
286
|
request.headers.each do |field, value|
|
285
287
|
buffer << "#{capitalized(field)}: #{value}" << CRLF
|
286
288
|
log(color: :yellow) { "<- HEADER: #{buffer.chomp}" }
|
@@ -91,7 +91,6 @@ module HTTPX
|
|
91
91
|
@streams[request] = stream
|
92
92
|
@max_requests -= 1
|
93
93
|
end
|
94
|
-
request.once(:headers, &method(:set_protocol_headers))
|
95
94
|
handle(request, stream)
|
96
95
|
true
|
97
96
|
rescue HTTP2Next::Error::StreamLimitExceeded
|
@@ -187,6 +186,7 @@ module HTTPX
|
|
187
186
|
end
|
188
187
|
|
189
188
|
def join_headers(stream, request)
|
189
|
+
set_protocol_headers(request)
|
190
190
|
log(level: 1, color: :yellow) do
|
191
191
|
request.headers.each.map { |k, v| "#{stream.id}: -> HEADER: #{k}: #{v}" }.join("\n")
|
192
192
|
end
|
data/lib/httpx/io/ssl.rb
CHANGED
@@ -47,10 +47,6 @@ module HTTPX
|
|
47
47
|
|
48
48
|
def connect
|
49
49
|
super
|
50
|
-
if @keep_open
|
51
|
-
@state = :negotiated
|
52
|
-
return
|
53
|
-
end
|
54
50
|
return if @state == :negotiated ||
|
55
51
|
@state != :connected
|
56
52
|
|
@@ -59,17 +55,22 @@ module HTTPX
|
|
59
55
|
@io.hostname = @sni_hostname
|
60
56
|
@io.sync_close = true
|
61
57
|
end
|
62
|
-
|
63
|
-
@io.post_connection_check(@sni_hostname) if @ctx.verify_mode != OpenSSL::SSL::VERIFY_NONE
|
64
|
-
transition(:negotiated)
|
65
|
-
@interests = :w
|
66
|
-
rescue ::IO::WaitReadable
|
67
|
-
@interests = :r
|
68
|
-
rescue ::IO::WaitWritable
|
69
|
-
@interests = :w
|
58
|
+
try_ssl_connect
|
70
59
|
end
|
71
60
|
|
72
61
|
if RUBY_VERSION < "2.3"
|
62
|
+
# :nocov:
|
63
|
+
def try_ssl_connect
|
64
|
+
@io.connect_nonblock
|
65
|
+
@io.post_connection_check(@sni_hostname) if @ctx.verify_mode != OpenSSL::SSL::VERIFY_NONE
|
66
|
+
transition(:negotiated)
|
67
|
+
@interests = :w
|
68
|
+
rescue ::IO::WaitReadable
|
69
|
+
@interests = :r
|
70
|
+
rescue ::IO::WaitWritable
|
71
|
+
@interests = :w
|
72
|
+
end
|
73
|
+
|
73
74
|
def read(_, buffer)
|
74
75
|
super
|
75
76
|
rescue ::IO::WaitWritable
|
@@ -82,7 +83,23 @@ module HTTPX
|
|
82
83
|
rescue ::IO::WaitReadable
|
83
84
|
0
|
84
85
|
end
|
86
|
+
# :nocov:
|
85
87
|
else
|
88
|
+
def try_ssl_connect
|
89
|
+
case @io.connect_nonblock(exception: false)
|
90
|
+
when :wait_readable
|
91
|
+
@interests = :r
|
92
|
+
return
|
93
|
+
when :wait_writable
|
94
|
+
@interests = :w
|
95
|
+
return
|
96
|
+
end
|
97
|
+
@io.post_connection_check(@sni_hostname) if @ctx.verify_mode != OpenSSL::SSL::VERIFY_NONE
|
98
|
+
transition(:negotiated)
|
99
|
+
@interests = :w
|
100
|
+
end
|
101
|
+
|
102
|
+
# :nocov:
|
86
103
|
if OpenSSL::VERSION < "2.0.6"
|
87
104
|
def read(size, buffer)
|
88
105
|
@io.read_nonblock(size, buffer)
|
@@ -95,11 +112,7 @@ module HTTPX
|
|
95
112
|
nil
|
96
113
|
end
|
97
114
|
end
|
98
|
-
|
99
|
-
|
100
|
-
def inspect
|
101
|
-
id = @io.closed? ? "closed" : @io.to_io.fileno
|
102
|
-
"#<SSL(fd: #{id}): #{@ip}:#{@port} state: #{@state}>"
|
115
|
+
# :nocov:
|
103
116
|
end
|
104
117
|
|
105
118
|
private
|
data/lib/httpx/io/tcp.rb
CHANGED
@@ -7,6 +7,8 @@ module HTTPX
|
|
7
7
|
class TCP
|
8
8
|
include Loggable
|
9
9
|
|
10
|
+
using URIExtensions
|
11
|
+
|
10
12
|
attr_reader :ip, :port, :addresses, :state, :interests
|
11
13
|
|
12
14
|
alias_method :host, :ip
|
@@ -14,7 +16,6 @@ module HTTPX
|
|
14
16
|
def initialize(origin, addresses, options)
|
15
17
|
@state = :idle
|
16
18
|
@hostname = origin.host
|
17
|
-
@addresses = addresses
|
18
19
|
@options = Options.new(options)
|
19
20
|
@fallback_protocol = @options.fallback_protocol
|
20
21
|
@port = origin.port
|
@@ -26,17 +27,17 @@ module HTTPX
|
|
26
27
|
else
|
27
28
|
@options.io
|
28
29
|
end
|
30
|
+
raise Error, "Given IO objects do not match the request authority" unless @io
|
31
|
+
|
29
32
|
_, _, _, @ip = @io.addr
|
30
33
|
@addresses ||= [@ip]
|
31
34
|
@ip_index = @addresses.size - 1
|
32
|
-
|
33
|
-
|
34
|
-
@state = :connected
|
35
|
-
end
|
35
|
+
@keep_open = true
|
36
|
+
@state = :connected
|
36
37
|
else
|
37
|
-
@
|
38
|
-
@ip = @addresses[@ip_index]
|
38
|
+
@addresses = addresses.map { |addr| addr.is_a?(IPAddr) ? addr : IPAddr.new(addr) }
|
39
39
|
end
|
40
|
+
@ip_index = @addresses.size - 1
|
40
41
|
@io ||= build_socket
|
41
42
|
end
|
42
43
|
|
@@ -51,17 +52,11 @@ module HTTPX
|
|
51
52
|
def connect
|
52
53
|
return unless closed?
|
53
54
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
@io = build_socket
|
58
|
-
end
|
59
|
-
@io.connect_nonblock(Socket.sockaddr_in(@port, @ip.to_s))
|
60
|
-
rescue Errno::EISCONN
|
55
|
+
if @io.closed?
|
56
|
+
transition(:idle)
|
57
|
+
@io = build_socket
|
61
58
|
end
|
62
|
-
|
63
|
-
|
64
|
-
transition(:connected)
|
59
|
+
try_connect
|
65
60
|
rescue Errno::EHOSTUNREACH => e
|
66
61
|
raise e if @ip_index <= 0
|
67
62
|
|
@@ -72,15 +67,25 @@ module HTTPX
|
|
72
67
|
|
73
68
|
@ip_index -= 1
|
74
69
|
retry
|
75
|
-
rescue Errno::EINPROGRESS,
|
76
|
-
Errno::EALREADY
|
77
|
-
@interests = :w
|
78
|
-
rescue ::IO::WaitReadable
|
79
|
-
@interests = :r
|
80
70
|
end
|
81
71
|
|
82
72
|
if RUBY_VERSION < "2.3"
|
83
73
|
# :nocov:
|
74
|
+
def try_connect
|
75
|
+
@io.connect_nonblock(Socket.sockaddr_in(@port, @ip.to_s))
|
76
|
+
rescue ::IO::WaitWritable, Errno::EALREADY
|
77
|
+
@interests = :w
|
78
|
+
rescue ::IO::WaitReadable
|
79
|
+
@interests = :r
|
80
|
+
rescue Errno::EISCONN
|
81
|
+
transition(:connected)
|
82
|
+
@interests = :w
|
83
|
+
else
|
84
|
+
transition(:connected)
|
85
|
+
@interests = :w
|
86
|
+
end
|
87
|
+
private :try_connect
|
88
|
+
|
84
89
|
def read(size, buffer)
|
85
90
|
@io.read_nonblock(size, buffer)
|
86
91
|
log { "READ: #{buffer.bytesize} bytes..." }
|
@@ -104,6 +109,20 @@ module HTTPX
|
|
104
109
|
end
|
105
110
|
# :nocov:
|
106
111
|
else
|
112
|
+
def try_connect
|
113
|
+
case @io.connect_nonblock(Socket.sockaddr_in(@port, @ip.to_s), exception: false)
|
114
|
+
when :wait_readable
|
115
|
+
@interests = :r
|
116
|
+
return
|
117
|
+
when :wait_writable
|
118
|
+
@interests = :w
|
119
|
+
return
|
120
|
+
end
|
121
|
+
transition(:connected)
|
122
|
+
@interests = :w
|
123
|
+
end
|
124
|
+
private :try_connect
|
125
|
+
|
107
126
|
def read(size, buffer)
|
108
127
|
ret = @io.read_nonblock(size, buffer, exception: false)
|
109
128
|
if ret == :wait_readable
|
@@ -148,14 +167,14 @@ module HTTPX
|
|
148
167
|
|
149
168
|
# :nocov:
|
150
169
|
def inspect
|
151
|
-
|
152
|
-
"#<TCP(fd: #{id}): #{@ip}:#{@port} (state: #{@state})>"
|
170
|
+
"#<#{self.class}: #{@ip}:#{@port} (state: #{@state})>"
|
153
171
|
end
|
154
172
|
# :nocov:
|
155
173
|
|
156
174
|
private
|
157
175
|
|
158
176
|
def build_socket
|
177
|
+
@ip = @addresses[@ip_index]
|
159
178
|
Socket.new(@ip.family, :STREAM, 0)
|
160
179
|
end
|
161
180
|
|
@@ -178,9 +197,9 @@ module HTTPX
|
|
178
197
|
def log_transition_state(nextstate)
|
179
198
|
case nextstate
|
180
199
|
when :connected
|
181
|
-
"Connected to #{
|
200
|
+
"Connected to #{host} (##{@io.fileno})"
|
182
201
|
else
|
183
|
-
"#{
|
202
|
+
"#{host} #{@state} -> #{nextstate}"
|
184
203
|
end
|
185
204
|
end
|
186
205
|
end
|
data/lib/httpx/io/unix.rb
CHANGED
@@ -6,34 +6,43 @@ module HTTPX
|
|
6
6
|
class UNIX < TCP
|
7
7
|
extend Forwardable
|
8
8
|
|
9
|
-
|
9
|
+
using URIExtensions
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
attr_reader :path
|
12
|
+
|
13
|
+
alias_method :host, :path
|
14
|
+
|
15
|
+
def initialize(origin, addresses, options)
|
13
16
|
@addresses = addresses
|
17
|
+
@hostname = origin.host
|
14
18
|
@state = :idle
|
15
19
|
@options = Options.new(options)
|
16
|
-
@path = @options.transport_options[:path]
|
17
20
|
@fallback_protocol = @options.fallback_protocol
|
18
21
|
if @options.io
|
19
22
|
@io = case @options.io
|
20
23
|
when Hash
|
21
|
-
@options.io[
|
24
|
+
@options.io[origin.authority]
|
22
25
|
else
|
23
26
|
@options.io
|
24
27
|
end
|
25
|
-
unless @io
|
26
|
-
|
27
|
-
|
28
|
+
raise Error, "Given IO objects do not match the request authority" unless @io
|
29
|
+
|
30
|
+
@path = @io.path
|
31
|
+
@keep_open = true
|
32
|
+
@state = :connected
|
33
|
+
else
|
34
|
+
if @options.transport_options
|
35
|
+
# :nocov:
|
36
|
+
warn ":#{__method__} is deprecated, use :addresses instead"
|
37
|
+
@path = @options.transport_options[:path]
|
38
|
+
# :nocov:
|
39
|
+
else
|
40
|
+
@path = addresses.first
|
28
41
|
end
|
29
42
|
end
|
30
43
|
@io ||= build_socket
|
31
44
|
end
|
32
45
|
|
33
|
-
def hostname
|
34
|
-
@uri.host
|
35
|
-
end
|
36
|
-
|
37
46
|
def connect
|
38
47
|
return unless closed?
|
39
48
|
|
@@ -51,6 +60,12 @@ module HTTPX
|
|
51
60
|
::IO::WaitReadable
|
52
61
|
end
|
53
62
|
|
63
|
+
# :nocov:
|
64
|
+
def inspect
|
65
|
+
"#<#{self.class}(path: #{@path}): (state: #{@state})>"
|
66
|
+
end
|
67
|
+
# :nocov:
|
68
|
+
|
54
69
|
private
|
55
70
|
|
56
71
|
def build_socket
|