httpx 0.12.0 → 0.13.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|