httpx 1.3.3 → 1.4.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_3_3.md +1 -1
- data/doc/release_notes/1_3_4.md +6 -0
- data/doc/release_notes/1_4_0.md +43 -0
- data/lib/httpx/adapters/faraday.rb +2 -0
- data/lib/httpx/adapters/webmock.rb +11 -5
- data/lib/httpx/callbacks.rb +0 -5
- data/lib/httpx/chainable.rb +3 -1
- data/lib/httpx/connection/http2.rb +11 -7
- data/lib/httpx/connection.rb +128 -16
- data/lib/httpx/errors.rb +12 -0
- data/lib/httpx/loggable.rb +5 -5
- data/lib/httpx/options.rb +26 -16
- data/lib/httpx/plugins/aws_sigv4.rb +31 -16
- data/lib/httpx/plugins/callbacks.rb +12 -2
- data/lib/httpx/plugins/circuit_breaker.rb +0 -5
- data/lib/httpx/plugins/content_digest.rb +202 -0
- data/lib/httpx/plugins/expect.rb +4 -3
- data/lib/httpx/plugins/follow_redirects.rb +7 -8
- data/lib/httpx/plugins/h2c.rb +23 -20
- data/lib/httpx/plugins/internal_telemetry.rb +27 -0
- data/lib/httpx/plugins/persistent.rb +16 -0
- data/lib/httpx/plugins/proxy/http.rb +17 -19
- data/lib/httpx/plugins/proxy.rb +91 -93
- data/lib/httpx/plugins/retries.rb +5 -8
- data/lib/httpx/plugins/upgrade.rb +5 -10
- data/lib/httpx/plugins/webdav.rb +6 -0
- data/lib/httpx/plugins/xml.rb +76 -0
- data/lib/httpx/pool.rb +73 -244
- data/lib/httpx/request/body.rb +16 -12
- data/lib/httpx/request.rb +1 -1
- data/lib/httpx/resolver/https.rb +12 -19
- data/lib/httpx/resolver/multi.rb +34 -16
- data/lib/httpx/resolver/native.rb +36 -13
- data/lib/httpx/resolver/resolver.rb +49 -11
- data/lib/httpx/resolver/system.rb +29 -11
- data/lib/httpx/resolver.rb +21 -14
- data/lib/httpx/response/body.rb +12 -1
- data/lib/httpx/response.rb +5 -3
- data/lib/httpx/selector.rb +164 -95
- data/lib/httpx/session.rb +296 -139
- data/lib/httpx/transcoder/gzip.rb +0 -3
- data/lib/httpx/transcoder/json.rb +14 -2
- data/lib/httpx/transcoder/multipart/encoder.rb +3 -1
- data/lib/httpx/transcoder/utils/deflater.rb +7 -4
- data/lib/httpx/transcoder/utils/inflater.rb +2 -0
- data/lib/httpx/transcoder.rb +0 -1
- data/lib/httpx/version.rb +1 -1
- data/lib/httpx.rb +19 -20
- data/sig/callbacks.rbs +0 -1
- data/sig/chainable.rbs +4 -0
- data/sig/connection/http2.rbs +1 -1
- data/sig/connection.rbs +14 -3
- data/sig/errors.rbs +6 -0
- data/sig/loggable.rbs +2 -0
- data/sig/options.rbs +7 -0
- data/sig/plugins/aws_sigv4.rbs +8 -2
- data/sig/plugins/content_digest.rbs +51 -0
- data/sig/plugins/cookies/cookie.rbs +9 -0
- data/sig/plugins/grpc/call.rbs +4 -0
- data/sig/plugins/persistent.rbs +4 -1
- data/sig/plugins/proxy/socks5.rbs +11 -3
- data/sig/plugins/proxy.rbs +18 -11
- data/sig/plugins/push_promise.rbs +3 -0
- data/sig/plugins/rate_limiter.rbs +2 -0
- data/sig/plugins/retries.rbs +1 -1
- data/sig/plugins/ssrf_filter.rbs +26 -0
- data/sig/plugins/webdav.rbs +23 -0
- data/sig/plugins/xml.rbs +37 -0
- data/sig/pool.rbs +25 -33
- data/sig/request/body.rbs +5 -1
- data/sig/resolver/multi.rbs +26 -1
- data/sig/resolver/native.rbs +0 -2
- data/sig/resolver/resolver.rbs +21 -2
- data/sig/resolver.rbs +5 -1
- data/sig/response/body.rbs +2 -2
- data/sig/response/buffer.rbs +2 -2
- data/sig/selector.rbs +30 -4
- data/sig/session.rbs +45 -18
- data/sig/transcoder/body.rbs +1 -1
- data/sig/transcoder/chunker.rbs +1 -1
- data/sig/transcoder/deflate.rbs +1 -0
- data/sig/transcoder/form.rbs +8 -0
- data/sig/transcoder/gzip.rbs +4 -1
- data/sig/transcoder/multipart.rbs +3 -3
- data/sig/transcoder/utils/body_reader.rbs +2 -2
- data/sig/transcoder/utils/deflater.rbs +2 -2
- metadata +12 -4
- data/lib/httpx/transcoder/xml.rb +0 -52
- data/sig/transcoder/xml.rbs +0 -22
@@ -135,7 +135,7 @@ module HTTPX
|
|
135
135
|
return unless query
|
136
136
|
|
137
137
|
h, connection = query
|
138
|
-
host = connection.
|
138
|
+
host = connection.peer.host
|
139
139
|
timeout = (@timeouts[host][0] -= loop_time)
|
140
140
|
|
141
141
|
return unless timeout <= 0
|
@@ -164,7 +164,10 @@ module HTTPX
|
|
164
164
|
@connections.delete(connection)
|
165
165
|
# This loop_time passed to the exception is bogus. Ideally we would pass the total
|
166
166
|
# resolve timeout, including from the previous retries.
|
167
|
-
|
167
|
+
ex = ResolveTimeoutError.new(loop_time, "Timed out while resolving #{connection.peer.host}")
|
168
|
+
ex.set_backtrace(ex ? ex.backtrace : caller)
|
169
|
+
emit_resolve_error(connection, host, ex)
|
170
|
+
emit(:close, self)
|
168
171
|
end
|
169
172
|
end
|
170
173
|
|
@@ -248,7 +251,10 @@ module HTTPX
|
|
248
251
|
|
249
252
|
unless @queries.value?(connection)
|
250
253
|
@connections.delete(connection)
|
251
|
-
|
254
|
+
ex = NativeResolveError.new(connection, connection.peer.host, "name or service not known")
|
255
|
+
ex.set_backtrace(ex ? ex.backtrace : caller)
|
256
|
+
emit_resolve_error(connection, connection.peer.host, ex)
|
257
|
+
emit(:close, self)
|
252
258
|
end
|
253
259
|
|
254
260
|
resolve
|
@@ -265,13 +271,13 @@ module HTTPX
|
|
265
271
|
hostname, connection = @queries.first
|
266
272
|
reset_hostname(hostname)
|
267
273
|
@connections.delete(connection)
|
268
|
-
ex = NativeResolveError.new(connection, connection.
|
274
|
+
ex = NativeResolveError.new(connection, connection.peer.host, "unknown DNS error (error code #{result})")
|
269
275
|
raise ex
|
270
276
|
when :decode_error
|
271
277
|
hostname, connection = @queries.first
|
272
278
|
reset_hostname(hostname)
|
273
279
|
@connections.delete(connection)
|
274
|
-
ex = NativeResolveError.new(connection, connection.
|
280
|
+
ex = NativeResolveError.new(connection, connection.peer.host, result.message)
|
275
281
|
ex.set_backtrace(result.backtrace)
|
276
282
|
raise ex
|
277
283
|
end
|
@@ -283,7 +289,7 @@ module HTTPX
|
|
283
289
|
hostname, connection = @queries.first
|
284
290
|
reset_hostname(hostname)
|
285
291
|
@connections.delete(connection)
|
286
|
-
raise NativeResolveError.new(connection, connection.
|
292
|
+
raise NativeResolveError.new(connection, connection.peer.host)
|
287
293
|
else
|
288
294
|
address = addresses.first
|
289
295
|
name = address["name"]
|
@@ -309,9 +315,9 @@ module HTTPX
|
|
309
315
|
if address.key?("alias") # CNAME
|
310
316
|
hostname_alias = address["alias"]
|
311
317
|
# clean up intermediate queries
|
312
|
-
@timeouts.delete(name) unless connection.
|
318
|
+
@timeouts.delete(name) unless connection.peer.host == name
|
313
319
|
|
314
|
-
if
|
320
|
+
if early_resolve(connection, hostname: hostname_alias)
|
315
321
|
@connections.delete(connection)
|
316
322
|
else
|
317
323
|
if @socket_type == :tcp
|
@@ -326,13 +332,13 @@ module HTTPX
|
|
326
332
|
end
|
327
333
|
else
|
328
334
|
reset_hostname(name, connection: connection)
|
329
|
-
@timeouts.delete(connection.
|
335
|
+
@timeouts.delete(connection.peer.host)
|
330
336
|
@connections.delete(connection)
|
331
|
-
Resolver.cached_lookup_set(connection.
|
337
|
+
Resolver.cached_lookup_set(connection.peer.host, @family, addresses) if @resolver_options[:cache]
|
332
338
|
catch(:coalesced) { emit_addresses(connection, @family, addresses.map { |addr| addr["data"] }) }
|
333
339
|
end
|
334
340
|
end
|
335
|
-
return emit(:close) if @connections.empty?
|
341
|
+
return emit(:close, self) if @connections.empty?
|
336
342
|
|
337
343
|
resolve
|
338
344
|
end
|
@@ -345,8 +351,8 @@ module HTTPX
|
|
345
351
|
hostname ||= @queries.key(connection)
|
346
352
|
|
347
353
|
if hostname.nil?
|
348
|
-
hostname = connection.
|
349
|
-
log { "resolver: resolve IDN #{connection.
|
354
|
+
hostname = connection.peer.host
|
355
|
+
log { "resolver: resolve IDN #{connection.peer.non_ascii_hostname} as #{hostname}" } if connection.peer.non_ascii_hostname
|
350
356
|
|
351
357
|
hostname = generate_candidates(hostname).each do |name|
|
352
358
|
@queries[name] = connection
|
@@ -358,7 +364,10 @@ module HTTPX
|
|
358
364
|
begin
|
359
365
|
@write_buffer << encode_dns_query(hostname)
|
360
366
|
rescue Resolv::DNS::EncodeError => e
|
367
|
+
reset_hostname(hostname, connection: connection)
|
368
|
+
@connections.delete(connection)
|
361
369
|
emit_resolve_error(connection, hostname, e)
|
370
|
+
emit(:close, self) if @connections.empty?
|
362
371
|
end
|
363
372
|
end
|
364
373
|
|
@@ -430,17 +439,31 @@ module HTTPX
|
|
430
439
|
@read_buffer.clear
|
431
440
|
end
|
432
441
|
@state = nextstate
|
442
|
+
rescue Errno::ECONNREFUSED,
|
443
|
+
Errno::EADDRNOTAVAIL,
|
444
|
+
Errno::EHOSTUNREACH,
|
445
|
+
SocketError,
|
446
|
+
IOError,
|
447
|
+
ConnectTimeoutError => e
|
448
|
+
# these errors may happen during TCP handshake
|
449
|
+
# treat them as resolve errors.
|
450
|
+
handle_error(e)
|
433
451
|
end
|
434
452
|
|
435
453
|
def handle_error(error)
|
436
454
|
if error.respond_to?(:connection) &&
|
437
455
|
error.respond_to?(:host)
|
456
|
+
reset_hostname(error.host, connection: error.connection)
|
457
|
+
@connections.delete(error.connection)
|
438
458
|
emit_resolve_error(error.connection, error.host, error)
|
439
459
|
else
|
440
460
|
@queries.each do |host, connection|
|
461
|
+
reset_hostname(host, connection: connection)
|
462
|
+
@connections.delete(connection)
|
441
463
|
emit_resolve_error(connection, host, error)
|
442
464
|
end
|
443
465
|
end
|
466
|
+
emit(:close, self) if @connections.empty?
|
444
467
|
end
|
445
468
|
|
446
469
|
def reset_hostname(hostname, connection: @queries.delete(hostname), reset_candidates: true)
|
@@ -26,14 +26,26 @@ module HTTPX
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
-
attr_reader :family
|
29
|
+
attr_reader :family, :options
|
30
30
|
|
31
|
-
attr_writer :
|
31
|
+
attr_writer :current_selector, :current_session
|
32
|
+
|
33
|
+
attr_accessor :multi
|
32
34
|
|
33
35
|
def initialize(family, options)
|
34
36
|
@family = family
|
35
37
|
@record_type = RECORD_TYPES[family]
|
36
38
|
@options = options
|
39
|
+
|
40
|
+
set_resolver_callbacks
|
41
|
+
end
|
42
|
+
|
43
|
+
def each_connection(&block)
|
44
|
+
enum_for(__method__) unless block
|
45
|
+
|
46
|
+
return unless @connections
|
47
|
+
|
48
|
+
@connections.each(&block)
|
37
49
|
end
|
38
50
|
|
39
51
|
def close; end
|
@@ -48,6 +60,10 @@ module HTTPX
|
|
48
60
|
true
|
49
61
|
end
|
50
62
|
|
63
|
+
def inflight?
|
64
|
+
false
|
65
|
+
end
|
66
|
+
|
51
67
|
def emit_addresses(connection, family, addresses, early_resolve = false)
|
52
68
|
addresses.map! do |address|
|
53
69
|
address.is_a?(IPAddr) ? address : IPAddr.new(address.to_s)
|
@@ -56,14 +72,14 @@ module HTTPX
|
|
56
72
|
# double emission check, but allow early resolution to work
|
57
73
|
return if !early_resolve && connection.addresses && !addresses.intersect?(connection.addresses)
|
58
74
|
|
59
|
-
log { "resolver: answer #{FAMILY_TYPES[RECORD_TYPES[family]]} #{connection.
|
60
|
-
if @
|
75
|
+
log { "resolver: answer #{FAMILY_TYPES[RECORD_TYPES[family]]} #{connection.peer.host}: #{addresses.inspect}" }
|
76
|
+
if @current_selector && # if triggered by early resolve, session may not be here yet
|
61
77
|
!connection.io &&
|
62
78
|
connection.options.ip_families.size > 1 &&
|
63
79
|
family == Socket::AF_INET &&
|
64
|
-
addresses.first.to_s != connection.
|
80
|
+
addresses.first.to_s != connection.peer.host.to_s
|
65
81
|
log { "resolver: A response, applying resolution delay..." }
|
66
|
-
@
|
82
|
+
@current_selector.after(0.05) do
|
67
83
|
unless connection.state == :closed ||
|
68
84
|
# double emission check
|
69
85
|
(connection.addresses && addresses.intersect?(connection.addresses))
|
@@ -92,20 +108,22 @@ module HTTPX
|
|
92
108
|
end
|
93
109
|
end
|
94
110
|
|
95
|
-
def early_resolve(connection, hostname: connection.
|
111
|
+
def early_resolve(connection, hostname: connection.peer.host)
|
96
112
|
addresses = @resolver_options[:cache] && (connection.addresses || HTTPX::Resolver.nolookup_resolve(hostname))
|
97
113
|
|
98
|
-
return unless addresses
|
114
|
+
return false unless addresses
|
99
115
|
|
100
116
|
addresses = addresses.select { |addr| addr.family == @family }
|
101
117
|
|
102
|
-
return if addresses.empty?
|
118
|
+
return false if addresses.empty?
|
103
119
|
|
104
120
|
emit_addresses(connection, @family, addresses, true)
|
121
|
+
|
122
|
+
true
|
105
123
|
end
|
106
124
|
|
107
|
-
def emit_resolve_error(connection, hostname = connection.
|
108
|
-
|
125
|
+
def emit_resolve_error(connection, hostname = connection.peer.host, ex = nil)
|
126
|
+
emit_connection_error(connection, resolve_error(hostname, ex))
|
109
127
|
end
|
110
128
|
|
111
129
|
def resolve_error(hostname, ex = nil)
|
@@ -116,5 +134,25 @@ module HTTPX
|
|
116
134
|
error.set_backtrace(ex ? ex.backtrace : caller)
|
117
135
|
error
|
118
136
|
end
|
137
|
+
|
138
|
+
def set_resolver_callbacks
|
139
|
+
on(:resolve, &method(:resolve_connection))
|
140
|
+
on(:error, &method(:emit_connection_error))
|
141
|
+
on(:close, &method(:close_resolver))
|
142
|
+
end
|
143
|
+
|
144
|
+
def resolve_connection(connection)
|
145
|
+
@current_session.__send__(:on_resolver_connection, connection, @current_selector)
|
146
|
+
end
|
147
|
+
|
148
|
+
def emit_connection_error(connection, error)
|
149
|
+
return connection.emit(:connect_error, error) if connection.connecting? && connection.callbacks_for?(:connect_error)
|
150
|
+
|
151
|
+
connection.emit(:error, error)
|
152
|
+
end
|
153
|
+
|
154
|
+
def close_resolver(resolver)
|
155
|
+
@current_session.__send__(:on_resolver_close, resolver, @current_selector)
|
156
|
+
end
|
119
157
|
end
|
120
158
|
end
|
@@ -47,8 +47,12 @@ module HTTPX
|
|
47
47
|
yield self
|
48
48
|
end
|
49
49
|
|
50
|
-
def
|
51
|
-
|
50
|
+
def multi
|
51
|
+
self
|
52
|
+
end
|
53
|
+
|
54
|
+
def empty?
|
55
|
+
true
|
52
56
|
end
|
53
57
|
|
54
58
|
def close
|
@@ -84,7 +88,7 @@ module HTTPX
|
|
84
88
|
|
85
89
|
return unless connection
|
86
90
|
|
87
|
-
@timeouts[connection.
|
91
|
+
@timeouts[connection.peer.host].first
|
88
92
|
end
|
89
93
|
|
90
94
|
def <<(connection)
|
@@ -92,6 +96,11 @@ module HTTPX
|
|
92
96
|
resolve
|
93
97
|
end
|
94
98
|
|
99
|
+
def early_resolve(connection, **)
|
100
|
+
self << connection
|
101
|
+
true
|
102
|
+
end
|
103
|
+
|
95
104
|
def handle_socket_timeout(interval)
|
96
105
|
error = HTTPX::ResolveTimeoutError.new(interval, "timed out while waiting on select")
|
97
106
|
error.set_backtrace(caller)
|
@@ -120,23 +129,26 @@ module HTTPX
|
|
120
129
|
def consume
|
121
130
|
return if @connections.empty?
|
122
131
|
|
123
|
-
|
132
|
+
if @pipe_read.wait_readable
|
133
|
+
event = @pipe_read.getbyte
|
134
|
+
|
124
135
|
case event
|
125
136
|
when DONE
|
126
137
|
*pair, addrs = @pipe_mutex.synchronize { @ips.pop }
|
127
138
|
@queries.delete(pair)
|
139
|
+
_, connection = pair
|
140
|
+
@connections.delete(connection)
|
128
141
|
|
129
142
|
family, connection = pair
|
130
143
|
catch(:coalesced) { emit_addresses(connection, family, addrs) }
|
131
144
|
when ERROR
|
132
145
|
*pair, error = @pipe_mutex.synchronize { @ips.pop }
|
133
146
|
@queries.delete(pair)
|
147
|
+
@connections.delete(connection)
|
134
148
|
|
135
|
-
|
136
|
-
emit_resolve_error(connection, connection.
|
149
|
+
_, connection = pair
|
150
|
+
emit_resolve_error(connection, connection.peer.host, error)
|
137
151
|
end
|
138
|
-
|
139
|
-
@connections.delete(connection) if @queries.empty?
|
140
152
|
end
|
141
153
|
|
142
154
|
return emit(:close, self) if @connections.empty?
|
@@ -148,9 +160,9 @@ module HTTPX
|
|
148
160
|
raise Error, "no URI to resolve" unless connection
|
149
161
|
return unless @queries.empty?
|
150
162
|
|
151
|
-
hostname = connection.
|
163
|
+
hostname = connection.peer.host
|
152
164
|
scheme = connection.origin.scheme
|
153
|
-
log { "resolver: resolve IDN #{connection.
|
165
|
+
log { "resolver: resolve IDN #{connection.peer.non_ascii_hostname} as #{hostname}" } if connection.peer.non_ascii_hostname
|
154
166
|
|
155
167
|
transition(:open)
|
156
168
|
|
@@ -164,7 +176,7 @@ module HTTPX
|
|
164
176
|
def async_resolve(connection, hostname, scheme)
|
165
177
|
families = connection.options.ip_families
|
166
178
|
log { "resolver: query for #{hostname}" }
|
167
|
-
timeouts = @timeouts[connection.
|
179
|
+
timeouts = @timeouts[connection.peer.host]
|
168
180
|
resolve_timeout = timeouts.first
|
169
181
|
|
170
182
|
Thread.start do
|
@@ -210,5 +222,11 @@ module HTTPX
|
|
210
222
|
def __addrinfo_resolve(host, scheme)
|
211
223
|
Addrinfo.getaddrinfo(host, scheme, Socket::AF_UNSPEC, Socket::SOCK_STREAM)
|
212
224
|
end
|
225
|
+
|
226
|
+
def emit_connection_error(_, error)
|
227
|
+
throw(:resolve_error, error)
|
228
|
+
end
|
229
|
+
|
230
|
+
def close_resolver(resolver); end
|
213
231
|
end
|
214
232
|
end
|
data/lib/httpx/resolver.rb
CHANGED
@@ -53,8 +53,8 @@ module HTTPX
|
|
53
53
|
|
54
54
|
def cached_lookup(hostname)
|
55
55
|
now = Utils.now
|
56
|
-
|
57
|
-
lookup(hostname, now)
|
56
|
+
lookup_synchronize do |lookups|
|
57
|
+
lookup(hostname, lookups, now)
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
@@ -63,37 +63,37 @@ module HTTPX
|
|
63
63
|
entries.each do |entry|
|
64
64
|
entry["TTL"] += now
|
65
65
|
end
|
66
|
-
|
66
|
+
lookup_synchronize do |lookups|
|
67
67
|
case family
|
68
68
|
when Socket::AF_INET6
|
69
|
-
|
69
|
+
lookups[hostname].concat(entries)
|
70
70
|
when Socket::AF_INET
|
71
|
-
|
71
|
+
lookups[hostname].unshift(*entries)
|
72
72
|
end
|
73
73
|
entries.each do |entry|
|
74
74
|
next unless entry["name"] != hostname
|
75
75
|
|
76
76
|
case family
|
77
77
|
when Socket::AF_INET6
|
78
|
-
|
78
|
+
lookups[entry["name"]] << entry
|
79
79
|
when Socket::AF_INET
|
80
|
-
|
80
|
+
lookups[entry["name"]].unshift(entry)
|
81
81
|
end
|
82
82
|
end
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
86
86
|
# do not use directly!
|
87
|
-
def lookup(hostname, ttl)
|
88
|
-
return unless
|
87
|
+
def lookup(hostname, lookups, ttl)
|
88
|
+
return unless lookups.key?(hostname)
|
89
89
|
|
90
|
-
entries =
|
90
|
+
entries = lookups[hostname] = lookups[hostname].select do |address|
|
91
91
|
address["TTL"] > ttl
|
92
92
|
end
|
93
93
|
|
94
94
|
ips = entries.flat_map do |address|
|
95
95
|
if address.key?("alias")
|
96
|
-
lookup(address["alias"], ttl)
|
96
|
+
lookup(address["alias"], lookups, ttl)
|
97
97
|
else
|
98
98
|
IPAddr.new(address["data"])
|
99
99
|
end
|
@@ -103,12 +103,11 @@ module HTTPX
|
|
103
103
|
end
|
104
104
|
|
105
105
|
def generate_id
|
106
|
-
|
106
|
+
id_synchronize { @identifier = (@identifier + 1) & 0xFFFF }
|
107
107
|
end
|
108
108
|
|
109
109
|
def encode_dns_query(hostname, type: Resolv::DNS::Resource::IN::A, message_id: generate_id)
|
110
|
-
Resolv::DNS::Message.new.tap do |query|
|
111
|
-
query.id = message_id
|
110
|
+
Resolv::DNS::Message.new(message_id).tap do |query|
|
112
111
|
query.rd = 1
|
113
112
|
query.add_question(hostname, type)
|
114
113
|
end.encode
|
@@ -150,5 +149,13 @@ module HTTPX
|
|
150
149
|
|
151
150
|
[:ok, addresses]
|
152
151
|
end
|
152
|
+
|
153
|
+
def lookup_synchronize
|
154
|
+
@lookup_mutex.synchronize { yield(@lookups) }
|
155
|
+
end
|
156
|
+
|
157
|
+
def id_synchronize(&block)
|
158
|
+
@identifier_mutex.synchronize(&block)
|
159
|
+
end
|
153
160
|
end
|
154
161
|
end
|
data/lib/httpx/response/body.rb
CHANGED
@@ -17,12 +17,23 @@ module HTTPX
|
|
17
17
|
@headers = response.headers
|
18
18
|
@options = options
|
19
19
|
@window_size = options.window_size
|
20
|
-
@encoding = response.content_type.charset || Encoding::BINARY
|
21
20
|
@encodings = []
|
22
21
|
@length = 0
|
23
22
|
@buffer = nil
|
24
23
|
@reader = nil
|
25
24
|
@state = :idle
|
25
|
+
|
26
|
+
# initialize response encoding
|
27
|
+
@encoding = if (enc = response.content_type.charset)
|
28
|
+
begin
|
29
|
+
Encoding.find(enc)
|
30
|
+
rescue ArgumentError
|
31
|
+
Encoding::BINARY
|
32
|
+
end
|
33
|
+
else
|
34
|
+
Encoding::BINARY
|
35
|
+
end
|
36
|
+
|
26
37
|
initialize_inflaters
|
27
38
|
end
|
28
39
|
|
data/lib/httpx/response.rb
CHANGED
@@ -166,10 +166,12 @@ module HTTPX
|
|
166
166
|
decode(Transcoder::Form)
|
167
167
|
end
|
168
168
|
|
169
|
-
# decodes the response payload into a Nokogiri::XML::Node object **if** the payload is valid
|
170
|
-
# "application/xml" (requires the "nokogiri" gem).
|
171
169
|
def xml
|
172
|
-
|
170
|
+
# TODO: remove at next major version.
|
171
|
+
warn "DEPRECATION WARNING: calling `.#{__method__}` on plain HTTPX responses is deprecated. " \
|
172
|
+
"Use HTTPX.plugin(:xml) sessions and call `.#{__method__}` in its responses instead."
|
173
|
+
require "httpx/plugins/xml"
|
174
|
+
decode(Plugins::XML::Transcoder)
|
173
175
|
end
|
174
176
|
|
175
177
|
private
|