httpx 1.4.3 → 1.5.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/1_4_4.md +14 -0
- data/doc/release_notes/1_5_0.md +126 -0
- data/lib/httpx/adapters/datadog.rb +24 -3
- data/lib/httpx/adapters/webmock.rb +3 -0
- data/lib/httpx/buffer.rb +16 -5
- data/lib/httpx/connection/http1.rb +8 -9
- data/lib/httpx/connection/http2.rb +48 -24
- data/lib/httpx/connection.rb +40 -20
- data/lib/httpx/errors.rb +2 -11
- data/lib/httpx/headers.rb +24 -23
- data/lib/httpx/io/ssl.rb +8 -4
- data/lib/httpx/io/tcp.rb +9 -7
- data/lib/httpx/io/unix.rb +1 -1
- data/lib/httpx/loggable.rb +13 -1
- data/lib/httpx/options.rb +63 -48
- data/lib/httpx/parser/http1.rb +1 -1
- data/lib/httpx/plugins/aws_sigv4.rb +1 -0
- data/lib/httpx/plugins/callbacks.rb +19 -6
- data/lib/httpx/plugins/circuit_breaker.rb +4 -3
- data/lib/httpx/plugins/cookies/jar.rb +0 -2
- data/lib/httpx/plugins/cookies/set_cookie_parser.rb +7 -4
- data/lib/httpx/plugins/cookies.rb +4 -4
- data/lib/httpx/plugins/follow_redirects.rb +4 -2
- data/lib/httpx/plugins/grpc/call.rb +1 -1
- data/lib/httpx/plugins/h2c.rb +7 -1
- data/lib/httpx/plugins/persistent.rb +22 -1
- data/lib/httpx/plugins/proxy/http.rb +3 -1
- data/lib/httpx/plugins/query.rb +35 -0
- data/lib/httpx/plugins/response_cache/file_store.rb +115 -15
- data/lib/httpx/plugins/response_cache/store.rb +7 -67
- data/lib/httpx/plugins/response_cache.rb +179 -29
- data/lib/httpx/plugins/retries.rb +27 -15
- data/lib/httpx/plugins/stream.rb +46 -20
- data/lib/httpx/plugins/stream_bidi.rb +315 -0
- data/lib/httpx/pool.rb +58 -5
- data/lib/httpx/request/body.rb +1 -1
- data/lib/httpx/request.rb +21 -5
- data/lib/httpx/resolver/https.rb +10 -4
- data/lib/httpx/resolver/native.rb +13 -13
- data/lib/httpx/resolver/resolver.rb +4 -0
- data/lib/httpx/resolver/system.rb +37 -14
- data/lib/httpx/resolver.rb +2 -2
- data/lib/httpx/response/body.rb +10 -21
- data/lib/httpx/response/buffer.rb +36 -12
- data/lib/httpx/response.rb +11 -1
- data/lib/httpx/selector.rb +16 -12
- data/lib/httpx/session.rb +80 -23
- data/lib/httpx/timers.rb +24 -16
- data/lib/httpx/transcoder/multipart/decoder.rb +4 -2
- data/lib/httpx/transcoder/multipart/encoder.rb +2 -1
- data/lib/httpx/version.rb +1 -1
- data/sig/buffer.rbs +1 -1
- data/sig/chainable.rbs +5 -2
- data/sig/connection/http2.rbs +11 -2
- data/sig/connection.rbs +4 -4
- data/sig/errors.rbs +0 -3
- data/sig/headers.rbs +15 -10
- data/sig/httpx.rbs +5 -1
- data/sig/io/tcp.rbs +6 -0
- data/sig/loggable.rbs +2 -0
- data/sig/options.rbs +7 -1
- data/sig/plugins/cookies/cookie.rbs +1 -3
- data/sig/plugins/cookies/jar.rbs +4 -4
- data/sig/plugins/cookies/set_cookie_parser.rbs +22 -0
- data/sig/plugins/cookies.rbs +2 -0
- data/sig/plugins/h2c.rbs +4 -0
- data/sig/plugins/proxy/http.rbs +3 -0
- data/sig/plugins/proxy.rbs +4 -0
- data/sig/plugins/response_cache/file_store.rbs +19 -0
- data/sig/plugins/response_cache/store.rbs +13 -0
- data/sig/plugins/response_cache.rbs +41 -19
- data/sig/plugins/retries.rbs +4 -3
- data/sig/plugins/stream.rbs +8 -1
- data/sig/plugins/stream_bidi.rbs +68 -0
- data/sig/plugins/upgrade/h2.rbs +9 -0
- data/sig/plugins/upgrade.rbs +5 -0
- data/sig/pool.rbs +5 -0
- data/sig/punycode.rbs +5 -0
- data/sig/request.rbs +7 -0
- data/sig/resolver/https.rbs +3 -2
- data/sig/resolver/native.rbs +1 -2
- data/sig/resolver/resolver.rbs +11 -3
- data/sig/resolver/system.rbs +19 -2
- data/sig/resolver.rbs +11 -7
- data/sig/response/body.rbs +3 -4
- data/sig/response/buffer.rbs +2 -3
- data/sig/response.rbs +2 -2
- data/sig/selector.rbs +20 -10
- data/sig/session.rbs +14 -6
- data/sig/timers.rbs +5 -7
- data/sig/transcoder/multipart.rbs +4 -3
- metadata +14 -5
- data/lib/httpx/session2.rb +0 -23
- data/lib/httpx/transcoder/utils/inflater.rb +0 -21
- data/sig/transcoder/utils/inflater.rbs +0 -12
data/lib/httpx/request.rb
CHANGED
@@ -104,21 +104,32 @@ module HTTPX
|
|
104
104
|
@state = :idle
|
105
105
|
@response = nil
|
106
106
|
@peer_address = nil
|
107
|
+
@ping = false
|
107
108
|
@persistent = @options.persistent
|
108
109
|
@active_timeouts = []
|
109
110
|
end
|
110
111
|
|
111
|
-
#
|
112
|
+
# whether request has been buffered with a ping
|
113
|
+
def ping?
|
114
|
+
@ping
|
115
|
+
end
|
116
|
+
|
117
|
+
# marks the request as having been buffered with a ping
|
118
|
+
def ping!
|
119
|
+
@ping = true
|
120
|
+
end
|
121
|
+
|
122
|
+
# the read timeout defined for this request.
|
112
123
|
def read_timeout
|
113
124
|
@options.timeout[:read_timeout]
|
114
125
|
end
|
115
126
|
|
116
|
-
# the write timeout defined for this
|
127
|
+
# the write timeout defined for this request.
|
117
128
|
def write_timeout
|
118
129
|
@options.timeout[:write_timeout]
|
119
130
|
end
|
120
131
|
|
121
|
-
# the request timeout defined for this
|
132
|
+
# the request timeout defined for this request.
|
122
133
|
def request_timeout
|
123
134
|
@options.timeout[:request_timeout]
|
124
135
|
end
|
@@ -144,6 +155,10 @@ module HTTPX
|
|
144
155
|
:w
|
145
156
|
end
|
146
157
|
|
158
|
+
def can_buffer?
|
159
|
+
@state != :done
|
160
|
+
end
|
161
|
+
|
147
162
|
# merges +h+ into the instance of HTTPX::Headers of the request.
|
148
163
|
def merge_headers(h)
|
149
164
|
@headers = @headers.merge(h)
|
@@ -211,7 +226,7 @@ module HTTPX
|
|
211
226
|
return @query if defined?(@query)
|
212
227
|
|
213
228
|
query = []
|
214
|
-
if (q = @query_params)
|
229
|
+
if (q = @query_params) && !q.empty?
|
215
230
|
query << Transcoder::Form.encode(q)
|
216
231
|
end
|
217
232
|
query << @uri.query if @uri.query
|
@@ -236,7 +251,7 @@ module HTTPX
|
|
236
251
|
|
237
252
|
# :nocov:
|
238
253
|
def inspect
|
239
|
-
"
|
254
|
+
"#<#{self.class}:#{object_id} " \
|
240
255
|
"#{@verb} " \
|
241
256
|
"#{uri} " \
|
242
257
|
"@headers=#{@headers} " \
|
@@ -249,6 +264,7 @@ module HTTPX
|
|
249
264
|
case nextstate
|
250
265
|
when :idle
|
251
266
|
@body.rewind
|
267
|
+
@ping = false
|
252
268
|
@response = nil
|
253
269
|
@drainer = nil
|
254
270
|
@active_timeouts.clear
|
data/lib/httpx/resolver/https.rb
CHANGED
@@ -2,11 +2,14 @@
|
|
2
2
|
|
3
3
|
require "resolv"
|
4
4
|
require "uri"
|
5
|
-
require "cgi"
|
6
5
|
require "forwardable"
|
7
6
|
require "httpx/base64"
|
8
7
|
|
9
8
|
module HTTPX
|
9
|
+
# Implementation of a DoH name resolver (https://www.youtube.com/watch?v=unMXvnY2FNM).
|
10
|
+
# It wraps an HTTPX::Connection object which integrates with the main session in the
|
11
|
+
# same manner as other performed HTTP requests.
|
12
|
+
#
|
10
13
|
class Resolver::HTTPS < Resolver::Resolver
|
11
14
|
extend Forwardable
|
12
15
|
using URIExtensions
|
@@ -27,14 +30,13 @@ module HTTPX
|
|
27
30
|
use_get: false,
|
28
31
|
}.freeze
|
29
32
|
|
30
|
-
def_delegators :@resolver_connection, :state, :connecting?, :to_io, :call, :close, :terminate, :inflight
|
33
|
+
def_delegators :@resolver_connection, :state, :connecting?, :to_io, :call, :close, :terminate, :inflight?, :handle_socket_timeout
|
31
34
|
|
32
35
|
def initialize(_, options)
|
33
36
|
super
|
34
37
|
@resolver_options = DEFAULTS.merge(@options.resolver_options)
|
35
38
|
@queries = {}
|
36
39
|
@requests = {}
|
37
|
-
@connections = []
|
38
40
|
@uri = URI(@resolver_options[:uri])
|
39
41
|
@uri_addresses = nil
|
40
42
|
@resolver = Resolv::DNS.new
|
@@ -75,7 +77,11 @@ module HTTPX
|
|
75
77
|
|
76
78
|
private
|
77
79
|
|
78
|
-
def resolve(connection =
|
80
|
+
def resolve(connection = nil, hostname = nil)
|
81
|
+
@connections.shift until @connections.empty? || @connections.first.state != :closed
|
82
|
+
|
83
|
+
connection ||= @connections.first
|
84
|
+
|
79
85
|
return unless connection
|
80
86
|
|
81
87
|
hostname ||= @queries.key(connection)
|
@@ -4,6 +4,9 @@ require "forwardable"
|
|
4
4
|
require "resolv"
|
5
5
|
|
6
6
|
module HTTPX
|
7
|
+
# Implements a pure ruby name resolver, which abides by the Selectable API.
|
8
|
+
# It delegates DNS payload encoding/decoding to the +resolv+ stlid gem.
|
9
|
+
#
|
7
10
|
class Resolver::Native < Resolver::Resolver
|
8
11
|
extend Forwardable
|
9
12
|
using URIExtensions
|
@@ -34,7 +37,6 @@ module HTTPX
|
|
34
37
|
@search = Array(@resolver_options[:search]).map { |srch| srch.scan(/[^.]+/) }
|
35
38
|
@_timeouts = Array(@resolver_options[:timeouts])
|
36
39
|
@timeouts = Hash.new { |timeouts, host| timeouts[host] = @_timeouts.dup }
|
37
|
-
@connections = []
|
38
40
|
@name = nil
|
39
41
|
@queries = {}
|
40
42
|
@read_buffer = "".b
|
@@ -46,6 +48,10 @@ module HTTPX
|
|
46
48
|
transition(:closed)
|
47
49
|
end
|
48
50
|
|
51
|
+
def terminate
|
52
|
+
emit(:close, self)
|
53
|
+
end
|
54
|
+
|
49
55
|
def closed?
|
50
56
|
@state == :closed
|
51
57
|
end
|
@@ -120,10 +126,7 @@ module HTTPX
|
|
120
126
|
@ns_index += 1
|
121
127
|
nameserver = @nameserver
|
122
128
|
if nameserver && @ns_index < nameserver.size
|
123
|
-
log
|
124
|
-
"resolver #{FAMILY_TYPES[@record_type]}: " \
|
125
|
-
"failed resolving on nameserver #{@nameserver[@ns_index - 1]} (#{e.message})"
|
126
|
-
end
|
129
|
+
log { "resolver #{FAMILY_TYPES[@record_type]}: failed resolving on nameserver #{@nameserver[@ns_index - 1]} (#{e.message})" }
|
127
130
|
transition(:idle)
|
128
131
|
@timeouts.clear
|
129
132
|
retry
|
@@ -158,9 +161,7 @@ module HTTPX
|
|
158
161
|
timeouts = @timeouts[h]
|
159
162
|
|
160
163
|
if !timeouts.empty?
|
161
|
-
log
|
162
|
-
"resolver #{FAMILY_TYPES[@record_type]}: timeout after #{interval}s, retry (with #{timeouts.first}s) #{h}..."
|
163
|
-
end
|
164
|
+
log { "resolver #{FAMILY_TYPES[@record_type]}: timeout after #{interval}s, retry (with #{timeouts.first}s) #{h}..." }
|
164
165
|
# must downgrade to tcp AND retry on same host as last
|
165
166
|
downgrade_socket
|
166
167
|
resolve(connection, h)
|
@@ -388,10 +389,9 @@ module HTTPX
|
|
388
389
|
|
389
390
|
if hostname.nil?
|
390
391
|
hostname = connection.peer.host
|
391
|
-
|
392
|
-
"resolver #{FAMILY_TYPES[@record_type]}: "
|
393
|
-
|
394
|
-
end if connection.peer.non_ascii_hostname
|
392
|
+
if connection.peer.non_ascii_hostname
|
393
|
+
log { "resolver #{FAMILY_TYPES[@record_type]}: resolve IDN #{connection.peer.non_ascii_hostname} as #{hostname}" }
|
394
|
+
end
|
395
395
|
|
396
396
|
hostname = generate_candidates(hostname).each do |name|
|
397
397
|
@queries[name] = connection
|
@@ -507,7 +507,7 @@ module HTTPX
|
|
507
507
|
end
|
508
508
|
|
509
509
|
while (connection = @connections.shift)
|
510
|
-
emit_resolve_error(connection, host, error)
|
510
|
+
emit_resolve_error(connection, connection.peer.host, error)
|
511
511
|
end
|
512
512
|
end
|
513
513
|
end
|
@@ -4,6 +4,9 @@ require "resolv"
|
|
4
4
|
require "ipaddr"
|
5
5
|
|
6
6
|
module HTTPX
|
7
|
+
# Base class for all internal internet name resolvers. It handles basic blocks
|
8
|
+
# from the Selectable API.
|
9
|
+
#
|
7
10
|
class Resolver::Resolver
|
8
11
|
include Callbacks
|
9
12
|
include Loggable
|
@@ -36,6 +39,7 @@ module HTTPX
|
|
36
39
|
@family = family
|
37
40
|
@record_type = RECORD_TYPES[family]
|
38
41
|
@options = options
|
42
|
+
@connections = []
|
39
43
|
|
40
44
|
set_resolver_callbacks
|
41
45
|
end
|
@@ -3,6 +3,15 @@
|
|
3
3
|
require "resolv"
|
4
4
|
|
5
5
|
module HTTPX
|
6
|
+
# Implementation of a synchronous name resolver which relies on the system resolver,
|
7
|
+
# which is lib'c getaddrinfo function (abstracted in ruby via Addrinfo.getaddrinfo).
|
8
|
+
#
|
9
|
+
# Its main advantage is relying on the reference implementation for name resolution
|
10
|
+
# across most/all OSs which deploy ruby (it's what TCPSocket also uses), its main
|
11
|
+
# disadvantage is the inability to set timeouts / check socket for readiness events,
|
12
|
+
# hence why it relies on using the Timeout module, which poses a lot of problems for
|
13
|
+
# the selector loop, specially when network is unstable.
|
14
|
+
#
|
6
15
|
class Resolver::System < Resolver::Resolver
|
7
16
|
using URIExtensions
|
8
17
|
|
@@ -23,14 +32,13 @@ module HTTPX
|
|
23
32
|
attr_reader :state
|
24
33
|
|
25
34
|
def initialize(options)
|
26
|
-
super(
|
35
|
+
super(0, options)
|
27
36
|
@resolver_options = @options.resolver_options
|
28
37
|
resolv_options = @resolver_options.dup
|
29
38
|
timeouts = resolv_options.delete(:timeouts) || Resolver::RESOLVE_TIMEOUT
|
30
39
|
@_timeouts = Array(timeouts)
|
31
40
|
@timeouts = Hash.new { |tims, host| tims[host] = @_timeouts.dup }
|
32
41
|
resolv_options.delete(:cache)
|
33
|
-
@connections = []
|
34
42
|
@queries = []
|
35
43
|
@ips = []
|
36
44
|
@pipe_mutex = Thread::Mutex.new
|
@@ -100,7 +108,14 @@ module HTTPX
|
|
100
108
|
def handle_socket_timeout(interval)
|
101
109
|
error = HTTPX::ResolveTimeoutError.new(interval, "timed out while waiting on select")
|
102
110
|
error.set_backtrace(caller)
|
103
|
-
|
111
|
+
@queries.each do |host, connection|
|
112
|
+
@connections.delete(connection)
|
113
|
+
emit_resolve_error(connection, host, error)
|
114
|
+
end
|
115
|
+
|
116
|
+
while (connection = @connections.shift)
|
117
|
+
emit_resolve_error(connection, connection.peer.host, error)
|
118
|
+
end
|
104
119
|
end
|
105
120
|
|
106
121
|
private
|
@@ -131,19 +146,22 @@ module HTTPX
|
|
131
146
|
case event
|
132
147
|
when DONE
|
133
148
|
*pair, addrs = @pipe_mutex.synchronize { @ips.pop }
|
134
|
-
|
135
|
-
|
136
|
-
|
149
|
+
if pair
|
150
|
+
@queries.delete(pair)
|
151
|
+
family, connection = pair
|
152
|
+
@connections.delete(connection)
|
137
153
|
|
138
|
-
|
139
|
-
|
154
|
+
catch(:coalesced) { emit_addresses(connection, family, addrs) }
|
155
|
+
end
|
140
156
|
when ERROR
|
141
157
|
*pair, error = @pipe_mutex.synchronize { @ips.pop }
|
142
|
-
|
143
|
-
|
158
|
+
if pair && error
|
159
|
+
@queries.delete(pair)
|
160
|
+
@connections.delete(connection)
|
144
161
|
|
145
|
-
|
146
|
-
|
162
|
+
_, connection = pair
|
163
|
+
emit_resolve_error(connection, connection.peer.host, error)
|
164
|
+
end
|
147
165
|
end
|
148
166
|
end
|
149
167
|
|
@@ -152,11 +170,16 @@ module HTTPX
|
|
152
170
|
resolve
|
153
171
|
end
|
154
172
|
|
155
|
-
def resolve(connection =
|
173
|
+
def resolve(connection = nil, hostname = nil)
|
174
|
+
@connections.shift until @connections.empty? || @connections.first.state != :closed
|
175
|
+
|
176
|
+
connection ||= @connections.first
|
177
|
+
|
156
178
|
raise Error, "no URI to resolve" unless connection
|
179
|
+
|
157
180
|
return unless @queries.empty?
|
158
181
|
|
159
|
-
hostname
|
182
|
+
hostname ||= connection.peer.host
|
160
183
|
scheme = connection.origin.scheme
|
161
184
|
log do
|
162
185
|
"resolver: resolve IDN #{connection.peer.non_ascii_hostname} as #{hostname}"
|
data/lib/httpx/resolver.rb
CHANGED
data/lib/httpx/response/body.rb
CHANGED
@@ -11,6 +11,9 @@ module HTTPX
|
|
11
11
|
# Array of encodings contained in the response "content-encoding" header.
|
12
12
|
attr_reader :encodings
|
13
13
|
|
14
|
+
attr_reader :buffer
|
15
|
+
protected :buffer
|
16
|
+
|
14
17
|
# initialized with the corresponding HTTPX::Response +response+ and HTTPX::Options +options+.
|
15
18
|
def initialize(response, options)
|
16
19
|
@response = response
|
@@ -148,18 +151,17 @@ module HTTPX
|
|
148
151
|
end
|
149
152
|
|
150
153
|
def ==(other)
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
end
|
154
|
+
super || case other
|
155
|
+
when Response::Body
|
156
|
+
@buffer == other.buffer
|
157
|
+
else
|
158
|
+
@buffer = other
|
159
|
+
end
|
158
160
|
end
|
159
161
|
|
160
162
|
# :nocov:
|
161
163
|
def inspect
|
162
|
-
"
|
164
|
+
"#<#{self.class}:#{object_id} " \
|
163
165
|
"@state=#{@state} " \
|
164
166
|
"@length=#{@length}>"
|
165
167
|
end
|
@@ -226,19 +228,6 @@ module HTTPX
|
|
226
228
|
@state = nextstate
|
227
229
|
end
|
228
230
|
|
229
|
-
def _with_same_buffer_pos # :nodoc:
|
230
|
-
return yield unless @buffer && @buffer.respond_to?(:pos)
|
231
|
-
|
232
|
-
# @type ivar @buffer: StringIO | Tempfile
|
233
|
-
current_pos = @buffer.pos
|
234
|
-
@buffer.rewind
|
235
|
-
begin
|
236
|
-
yield
|
237
|
-
ensure
|
238
|
-
@buffer.pos = current_pos
|
239
|
-
end
|
240
|
-
end
|
241
|
-
|
242
231
|
class << self
|
243
232
|
def initialize_inflater_by_encoding(encoding, response, **kwargs) # :nodoc:
|
244
233
|
case encoding
|
@@ -7,6 +7,9 @@ require "tempfile"
|
|
7
7
|
module HTTPX
|
8
8
|
# wraps and delegates to an internal buffer, which can be a StringIO or a Tempfile.
|
9
9
|
class Response::Buffer < SimpleDelegator
|
10
|
+
attr_reader :buffer
|
11
|
+
protected :buffer
|
12
|
+
|
10
13
|
# initializes buffer with the +threshold_size+ over which the payload gets buffer to a tempfile,
|
11
14
|
# the initial +bytesize+, and the +encoding+.
|
12
15
|
def initialize(threshold_size:, bytesize: 0, encoding: Encoding::BINARY)
|
@@ -20,7 +23,14 @@ module HTTPX
|
|
20
23
|
def initialize_dup(other)
|
21
24
|
super
|
22
25
|
|
23
|
-
|
26
|
+
# create new descriptor in READ-ONLY mode
|
27
|
+
@buffer =
|
28
|
+
case other.buffer
|
29
|
+
when StringIO
|
30
|
+
StringIO.new(other.buffer.string, mode: File::RDONLY)
|
31
|
+
else
|
32
|
+
other.buffer.class.new(other.buffer.path, encoding: Encoding::BINARY, mode: File::RDONLY)
|
33
|
+
end
|
24
34
|
end
|
25
35
|
|
26
36
|
# size in bytes of the buffered content.
|
@@ -46,7 +56,7 @@ module HTTPX
|
|
46
56
|
end
|
47
57
|
when Tempfile
|
48
58
|
rewind
|
49
|
-
content =
|
59
|
+
content = @buffer.read
|
50
60
|
begin
|
51
61
|
content.force_encoding(@encoding)
|
52
62
|
rescue ArgumentError # ex: unknown encoding name - utf
|
@@ -61,6 +71,30 @@ module HTTPX
|
|
61
71
|
@buffer.unlink if @buffer.respond_to?(:unlink)
|
62
72
|
end
|
63
73
|
|
74
|
+
def ==(other)
|
75
|
+
super || begin
|
76
|
+
return false unless other.is_a?(Response::Buffer)
|
77
|
+
|
78
|
+
if @buffer.nil?
|
79
|
+
other.buffer.nil?
|
80
|
+
elsif @buffer.respond_to?(:read) &&
|
81
|
+
other.respond_to?(:read)
|
82
|
+
buffer_pos = @buffer.pos
|
83
|
+
other_pos = other.buffer.pos
|
84
|
+
@buffer.rewind
|
85
|
+
other.buffer.rewind
|
86
|
+
begin
|
87
|
+
FileUtils.compare_stream(@buffer, other.buffer)
|
88
|
+
ensure
|
89
|
+
@buffer.pos = buffer_pos
|
90
|
+
other.buffer.pos = other_pos
|
91
|
+
end
|
92
|
+
else
|
93
|
+
to_s == other.to_s
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
64
98
|
private
|
65
99
|
|
66
100
|
# initializes the buffer into a StringIO, or turns it into a Tempfile when the threshold
|
@@ -82,15 +116,5 @@ module HTTPX
|
|
82
116
|
|
83
117
|
__setobj__(@buffer)
|
84
118
|
end
|
85
|
-
|
86
|
-
def _with_same_buffer_pos # :nodoc:
|
87
|
-
current_pos = @buffer.pos
|
88
|
-
@buffer.rewind
|
89
|
-
begin
|
90
|
-
yield
|
91
|
-
ensure
|
92
|
-
@buffer.pos = current_pos
|
93
|
-
end
|
94
|
-
end
|
95
119
|
end
|
96
120
|
end
|
data/lib/httpx/response.rb
CHANGED
@@ -71,6 +71,14 @@ module HTTPX
|
|
71
71
|
@content_type = nil
|
72
72
|
end
|
73
73
|
|
74
|
+
# dupped initialization
|
75
|
+
def initialize_dup(orig)
|
76
|
+
super
|
77
|
+
# if a response gets dupped, the body handle must also get dupped to prevent
|
78
|
+
# two responses from using the same file handle to read.
|
79
|
+
@body = orig.body.dup
|
80
|
+
end
|
81
|
+
|
74
82
|
# closes the respective +@request+ and +@body+.
|
75
83
|
def close
|
76
84
|
@request.close
|
@@ -126,7 +134,7 @@ module HTTPX
|
|
126
134
|
|
127
135
|
# :nocov:
|
128
136
|
def inspect
|
129
|
-
"
|
137
|
+
"#<#{self.class}:#{object_id} " \
|
130
138
|
"HTTP/#{version} " \
|
131
139
|
"@status=#{@status} " \
|
132
140
|
"@headers=#{@headers} " \
|
@@ -275,6 +283,8 @@ module HTTPX
|
|
275
283
|
true
|
276
284
|
end
|
277
285
|
|
286
|
+
def finish!; end
|
287
|
+
|
278
288
|
# raises the wrapped exception.
|
279
289
|
def raise_for_status
|
280
290
|
raise @error
|
data/lib/httpx/selector.rb
CHANGED
@@ -35,14 +35,21 @@ module HTTPX
|
|
35
35
|
end
|
36
36
|
|
37
37
|
begin
|
38
|
-
select(timeout
|
38
|
+
select(timeout) do |c|
|
39
|
+
c.log(level: 2) { "[#{c.state}] selected#{" after #{timeout} secs" unless timeout.nil?}..." }
|
40
|
+
|
41
|
+
c.call
|
42
|
+
end
|
43
|
+
|
39
44
|
@timers.fire
|
40
45
|
rescue TimeoutError => e
|
41
46
|
@timers.fire(e)
|
42
47
|
end
|
43
48
|
end
|
44
49
|
rescue StandardError => e
|
45
|
-
|
50
|
+
each_connection do |c|
|
51
|
+
c.emit(:error, e)
|
52
|
+
end
|
46
53
|
rescue Exception # rubocop:disable Lint/RescueException
|
47
54
|
each_connection do |conn|
|
48
55
|
conn.force_reset
|
@@ -77,9 +84,10 @@ module HTTPX
|
|
77
84
|
return enum_for(__method__) unless block
|
78
85
|
|
79
86
|
@selectables.each do |c|
|
80
|
-
|
87
|
+
case c
|
88
|
+
when Resolver::Resolver
|
81
89
|
c.each_connection(&block)
|
82
|
-
|
90
|
+
when Connection
|
83
91
|
yield c
|
84
92
|
end
|
85
93
|
end
|
@@ -133,6 +141,8 @@ module HTTPX
|
|
133
141
|
@selectables.delete_if do |io|
|
134
142
|
interests = io.interests
|
135
143
|
|
144
|
+
io.log(level: 2) { "[#{io.state}] registering for select (#{interests})#{" for #{interval} seconds" unless interval.nil?}" }
|
145
|
+
|
136
146
|
(r ||= []) << io if READABLE.include?(interests)
|
137
147
|
(w ||= []) << io if WRITABLE.include?(interests)
|
138
148
|
|
@@ -169,6 +179,8 @@ module HTTPX
|
|
169
179
|
|
170
180
|
interests = io.interests
|
171
181
|
|
182
|
+
io.log(level: 2) { "[#{io.state}] registering for select (#{interests})#{" for #{interval} seconds" unless interval.nil?}" }
|
183
|
+
|
172
184
|
result = case interests
|
173
185
|
when :r then io.to_io.wait_readable(interval)
|
174
186
|
when :w then io.to_io.wait_writable(interval)
|
@@ -205,13 +217,5 @@ module HTTPX
|
|
205
217
|
|
206
218
|
connection_interval
|
207
219
|
end
|
208
|
-
|
209
|
-
def emit_error(e)
|
210
|
-
@selectables.each do |c|
|
211
|
-
next if c.is_a?(Resolver::Resolver)
|
212
|
-
|
213
|
-
c.emit(:error, e)
|
214
|
-
end
|
215
|
-
end
|
216
220
|
end
|
217
221
|
end
|