httpx 0.18.6 → 0.18.7
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_18_5.md +2 -2
- data/doc/release_notes/0_18_7.md +5 -0
- data/lib/httpx/connection/http1.rb +5 -5
- data/lib/httpx/connection/http2.rb +1 -5
- data/lib/httpx/connection.rb +17 -9
- data/lib/httpx/io/tcp.rb +3 -1
- data/lib/httpx/plugins/internal_telemetry.rb +1 -1
- data/lib/httpx/plugins/multipart/mime_type_detector.rb +5 -1
- data/lib/httpx/plugins/proxy/http.rb +10 -23
- data/lib/httpx/plugins/proxy/socks4.rb +1 -1
- data/lib/httpx/plugins/proxy/socks5.rb +1 -1
- data/lib/httpx/plugins/proxy.rb +18 -7
- data/lib/httpx/resolver/https.rb +1 -1
- data/lib/httpx/resolver/native.rb +9 -2
- data/lib/httpx/resolver/resolver_mixin.rb +1 -1
- data/lib/httpx/resolver/system.rb +1 -1
- data/lib/httpx/session.rb +1 -15
- data/lib/httpx/session_extensions.rb +19 -0
- data/lib/httpx/version.rb +1 -1
- data/lib/httpx.rb +1 -0
- data/sig/connection/http1.rbs +0 -2
- data/sig/connection/http2.rbs +2 -2
- data/sig/connection.rbs +1 -0
- metadata +4 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ab9b9577b0e266b140e21030307b3f2436af346a13f1e0931af05020ba42f7e6
|
4
|
+
data.tar.gz: c5d043448ef41b0532c08d1622540d80c68511ef59cffcc810a6f8bd92f348d5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8b4ec58f2ab031d23f28a86bc47b40d0f0d79eea9aea64590b0cc3d07269738513de1364608e0c0282a6956d816b78b900520dbad4daab1f73522b8b7f73d138
|
7
|
+
data.tar.gz: f2d2c297b530bfb3567ebcd1678bad1d729187dd75c9107839c925def1a708c4648fe80df614a01af02bce309594e256e274e042f3c6b8347182aebff1df9935
|
data/doc/release_notes/0_18_5.md
CHANGED
@@ -3,8 +3,8 @@
|
|
3
3
|
## Improvements
|
4
4
|
|
5
5
|
* ruby 3.1 is now officially supported.
|
6
|
-
* when user sets a `Host` header for an HTTP/2 request, this will be used in the `:authority` HTTP/2 pseudo-header, instead of silently ignored (mimicking what "curl" does).
|
6
|
+
* when a user sets a `Host` header for an HTTP/2 request, this will be used in the `:authority` HTTP/2 pseudo-header, instead of silently ignored (mimicking what "curl" does).
|
7
7
|
|
8
8
|
## Bugfixes
|
9
9
|
|
10
|
-
* fixed "throw outside of catch block" error happening when pipelining requests on an HTTP/1
|
10
|
+
* fixed "throw outside of catch block" error happening when pipelining requests on an HTTP/1 connection and resulting in a timeout.
|
@@ -297,10 +297,6 @@ module HTTPX
|
|
297
297
|
extra_headers
|
298
298
|
end
|
299
299
|
|
300
|
-
def headline_uri(request)
|
301
|
-
request.path
|
302
|
-
end
|
303
|
-
|
304
300
|
def handle(request)
|
305
301
|
catch(:buffer_full) do
|
306
302
|
request.transition(:headers)
|
@@ -314,8 +310,12 @@ module HTTPX
|
|
314
310
|
end
|
315
311
|
end
|
316
312
|
|
313
|
+
def join_headline(request)
|
314
|
+
"#{request.verb.to_s.upcase} #{request.path} HTTP/#{@version.join(".")}"
|
315
|
+
end
|
316
|
+
|
317
317
|
def join_headers(request)
|
318
|
-
headline =
|
318
|
+
headline = join_headline(request)
|
319
319
|
@buffer << headline << CRLF
|
320
320
|
log(color: :yellow) { "<- HEADLINE: #{headline.chomp.inspect}" }
|
321
321
|
extra_headers = set_protocol_headers(request)
|
@@ -158,10 +158,6 @@ module HTTPX
|
|
158
158
|
end
|
159
159
|
end
|
160
160
|
|
161
|
-
def headline_uri(request)
|
162
|
-
request.path
|
163
|
-
end
|
164
|
-
|
165
161
|
def handle(request, stream)
|
166
162
|
catch(:buffer_full) do
|
167
163
|
request.transition(:headers)
|
@@ -213,7 +209,7 @@ module HTTPX
|
|
213
209
|
{
|
214
210
|
":scheme" => request.scheme,
|
215
211
|
":method" => request.verb.to_s.upcase,
|
216
|
-
":path" =>
|
212
|
+
":path" => request.path,
|
217
213
|
":authority" => request.authority,
|
218
214
|
}
|
219
215
|
end
|
data/lib/httpx/connection.rb
CHANGED
@@ -44,7 +44,7 @@ module HTTPX
|
|
44
44
|
|
45
45
|
def_delegator :@write_buffer, :empty?
|
46
46
|
|
47
|
-
attr_reader :origin, :state, :pending, :options
|
47
|
+
attr_reader :origin, :origins, :state, :pending, :options
|
48
48
|
|
49
49
|
attr_writer :timers
|
50
50
|
|
@@ -489,6 +489,18 @@ module HTTPX
|
|
489
489
|
end
|
490
490
|
|
491
491
|
def transition(nextstate)
|
492
|
+
handle_transition(nextstate)
|
493
|
+
rescue Errno::ECONNREFUSED,
|
494
|
+
Errno::EADDRNOTAVAIL,
|
495
|
+
Errno::EHOSTUNREACH,
|
496
|
+
TLSError => e
|
497
|
+
# connect errors, exit gracefully
|
498
|
+
handle_error(e)
|
499
|
+
@state = :closed
|
500
|
+
emit(:close)
|
501
|
+
end
|
502
|
+
|
503
|
+
def handle_transition(nextstate)
|
492
504
|
case nextstate
|
493
505
|
when :idle
|
494
506
|
@timeout = @current_timeout = @options.timeout[:connect_timeout]
|
@@ -525,14 +537,6 @@ module HTTPX
|
|
525
537
|
emit(:activate)
|
526
538
|
end
|
527
539
|
@state = nextstate
|
528
|
-
rescue Errno::ECONNREFUSED,
|
529
|
-
Errno::EADDRNOTAVAIL,
|
530
|
-
Errno::EHOSTUNREACH,
|
531
|
-
TLSError => e
|
532
|
-
# connect errors, exit gracefully
|
533
|
-
handle_error(e)
|
534
|
-
@state = :closed
|
535
|
-
emit(:close)
|
536
540
|
end
|
537
541
|
|
538
542
|
def purge_after_closed
|
@@ -550,6 +554,10 @@ module HTTPX
|
|
550
554
|
ex.set_backtrace(error.backtrace)
|
551
555
|
error = ex
|
552
556
|
else
|
557
|
+
# inactive connections do not contribute to the select loop, therefore
|
558
|
+
# they should fail due to such errors.
|
559
|
+
return if @state == :inactive
|
560
|
+
|
553
561
|
if @timeout
|
554
562
|
@timeout -= error.timeout
|
555
563
|
return unless @timeout <= 0
|
data/lib/httpx/io/tcp.rb
CHANGED
@@ -14,9 +14,13 @@ module HTTPX
|
|
14
14
|
def call(file, _)
|
15
15
|
return nil if file.eof? # FileMagic returns "application/x-empty" for empty files
|
16
16
|
|
17
|
-
FileMagic.open(FileMagic::MAGIC_MIME_TYPE) do |filemagic|
|
17
|
+
mime = FileMagic.open(FileMagic::MAGIC_MIME_TYPE) do |filemagic|
|
18
18
|
filemagic.buffer(file.read(MAGIC_NUMBER))
|
19
19
|
end
|
20
|
+
|
21
|
+
file.rewind
|
22
|
+
|
23
|
+
mime
|
20
24
|
end
|
21
25
|
elsif defined?(Marcel)
|
22
26
|
def call(file, filename)
|
@@ -13,7 +13,7 @@ module HTTPX
|
|
13
13
|
|
14
14
|
private
|
15
15
|
|
16
|
-
def
|
16
|
+
def handle_transition(nextstate)
|
17
17
|
return super unless @options.proxy && @options.proxy.uri.scheme == "http"
|
18
18
|
|
19
19
|
case nextstate
|
@@ -23,7 +23,8 @@ module HTTPX
|
|
23
23
|
@io.connect
|
24
24
|
return unless @io.connected?
|
25
25
|
|
26
|
-
@parser =
|
26
|
+
@parser = registry(@io.protocol).new(@write_buffer, @options.merge(max_concurrent_requests: 1))
|
27
|
+
@parser.extend(ProxyParser)
|
27
28
|
@parser.once(:response, &method(:__http_on_connect))
|
28
29
|
@parser.on(:close) { transition(:closing) }
|
29
30
|
__http_proxy_connect
|
@@ -36,7 +37,7 @@ module HTTPX
|
|
36
37
|
@parser.close
|
37
38
|
@parser = nil
|
38
39
|
when :idle
|
39
|
-
@parser
|
40
|
+
@parser.callbacks.clear
|
40
41
|
set_parser_callbacks(@parser)
|
41
42
|
end
|
42
43
|
end
|
@@ -54,7 +55,7 @@ module HTTPX
|
|
54
55
|
@inflight += 1
|
55
56
|
parser.send(connect_request)
|
56
57
|
else
|
57
|
-
|
58
|
+
handle_transition(:connected)
|
58
59
|
end
|
59
60
|
end
|
60
61
|
|
@@ -76,9 +77,11 @@ module HTTPX
|
|
76
77
|
end
|
77
78
|
end
|
78
79
|
|
79
|
-
|
80
|
-
def
|
81
|
-
request.
|
80
|
+
module ProxyParser
|
81
|
+
def join_headline(request)
|
82
|
+
return super if request.verb == :connect
|
83
|
+
|
84
|
+
"#{request.verb.to_s.upcase} #{request.uri} HTTP/#{@version.join(".")}"
|
82
85
|
end
|
83
86
|
|
84
87
|
def set_protocol_headers(request)
|
@@ -91,22 +94,6 @@ module HTTPX
|
|
91
94
|
end
|
92
95
|
end
|
93
96
|
|
94
|
-
class ConnectProxyParser < ProxyParser
|
95
|
-
attr_reader :pending
|
96
|
-
|
97
|
-
def headline_uri(request)
|
98
|
-
return super unless request.verb == :connect
|
99
|
-
|
100
|
-
tunnel = request.path
|
101
|
-
log { "establishing HTTP proxy tunnel to #{tunnel}" }
|
102
|
-
tunnel
|
103
|
-
end
|
104
|
-
|
105
|
-
def empty?
|
106
|
-
@requests.reject { |r| r.verb == :connect }.empty? || @requests.all? { |request| !request.response.nil? }
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
97
|
class ConnectRequest < Request
|
111
98
|
def initialize(uri, _options)
|
112
99
|
super(:connect, uri, {})
|
data/lib/httpx/plugins/proxy.rb
CHANGED
@@ -85,7 +85,7 @@ module HTTPX
|
|
85
85
|
end
|
86
86
|
uris
|
87
87
|
end
|
88
|
-
|
88
|
+
{ uri: @_proxy_uris.first } unless @_proxy_uris.empty?
|
89
89
|
end
|
90
90
|
|
91
91
|
def find_connection(request, connections, options)
|
@@ -109,8 +109,10 @@ module HTTPX
|
|
109
109
|
return super unless proxy
|
110
110
|
|
111
111
|
connection = options.connection_class.new("tcp", uri, options)
|
112
|
-
|
113
|
-
|
112
|
+
catch(:coalesced) do
|
113
|
+
pool.init_connection(connection, options)
|
114
|
+
connection
|
115
|
+
end
|
114
116
|
end
|
115
117
|
|
116
118
|
def fetch_response(request, connections, options)
|
@@ -181,11 +183,20 @@ module HTTPX
|
|
181
183
|
super && @options.proxy == options.proxy
|
182
184
|
end
|
183
185
|
|
184
|
-
|
185
|
-
def coalescable?(*)
|
186
|
+
def coalescable?(connection)
|
186
187
|
return super unless @options.proxy
|
187
188
|
|
188
|
-
|
189
|
+
if @io.protocol == "h2" &&
|
190
|
+
@origin.scheme == "https" &&
|
191
|
+
connection.origin.scheme == "https" &&
|
192
|
+
@io.can_verify_peer?
|
193
|
+
# in proxied connections, .origin is the proxy ; Given names
|
194
|
+
# are stored in .origins, this is what is used.
|
195
|
+
origin = URI(connection.origins.first)
|
196
|
+
@io.verify_hostname(origin.host)
|
197
|
+
else
|
198
|
+
@origin == connection.origin
|
199
|
+
end
|
189
200
|
end
|
190
201
|
|
191
202
|
def send(request)
|
@@ -234,7 +245,7 @@ module HTTPX
|
|
234
245
|
end
|
235
246
|
end
|
236
247
|
|
237
|
-
def
|
248
|
+
def handle_transition(nextstate)
|
238
249
|
return super unless @options.proxy
|
239
250
|
|
240
251
|
case nextstate
|
data/lib/httpx/resolver/https.rb
CHANGED
@@ -29,7 +29,7 @@ module HTTPX
|
|
29
29
|
attr_writer :pool
|
30
30
|
|
31
31
|
def initialize(options)
|
32
|
-
@options = Options.new(options)
|
32
|
+
@options = HTTPX::Options.new(options)
|
33
33
|
@resolver_options = DEFAULTS.merge(@options.resolver_options)
|
34
34
|
@_record_types = Hash.new { |types, host| types[host] = @resolver_options[:record_types].dup }
|
35
35
|
@queries = {}
|
@@ -50,7 +50,7 @@ module HTTPX
|
|
50
50
|
attr_reader :state
|
51
51
|
|
52
52
|
def initialize(options)
|
53
|
-
@options = Options.new(options)
|
53
|
+
@options = HTTPX::Options.new(options)
|
54
54
|
@ns_index = 0
|
55
55
|
@resolver_options = DEFAULTS.merge(@options.resolver_options)
|
56
56
|
@nameserver = @resolver_options[:nameserver]
|
@@ -200,6 +200,7 @@ module HTTPX
|
|
200
200
|
hostname, connection = @queries.first
|
201
201
|
if @_record_types[hostname].empty?
|
202
202
|
@queries.delete(hostname)
|
203
|
+
@timeouts.delete(hostname)
|
203
204
|
@connections.delete(connection)
|
204
205
|
ex = NativeResolveError.new(connection, hostname, e.message)
|
205
206
|
ex.set_backtrace(e.backtrace)
|
@@ -213,6 +214,7 @@ module HTTPX
|
|
213
214
|
if @_record_types[hostname].empty?
|
214
215
|
@queries.delete(hostname)
|
215
216
|
@_record_types.delete(hostname)
|
217
|
+
@timeouts.delete(hostname)
|
216
218
|
@connections.delete(connection)
|
217
219
|
|
218
220
|
raise NativeResolveError.new(connection, hostname)
|
@@ -236,13 +238,18 @@ module HTTPX
|
|
236
238
|
end
|
237
239
|
|
238
240
|
if address.key?("alias") # CNAME
|
239
|
-
|
241
|
+
# clean up intermediate queries
|
242
|
+
@timeouts.delete(address["name"]) unless connection.origin.host == address["name"]
|
243
|
+
|
244
|
+
if catch(:coalesced) { early_resolve(connection, hostname: address["alias"]) }
|
245
|
+
@timeouts.delete(connection.origin.host)
|
240
246
|
@connections.delete(connection)
|
241
247
|
else
|
242
248
|
resolve(connection, address["alias"])
|
243
249
|
return
|
244
250
|
end
|
245
251
|
else
|
252
|
+
@timeouts.delete(connection.origin.host)
|
246
253
|
@connections.delete(connection)
|
247
254
|
Resolver.cached_lookup_set(connection.origin.host, addresses) if @resolver_options[:cache]
|
248
255
|
emit_addresses(connection, addresses.map { |addr| addr["data"] })
|
@@ -32,7 +32,7 @@ module HTTPX
|
|
32
32
|
end
|
33
33
|
log { "resolver: answer #{connection.origin.host}: #{addresses.inspect}" }
|
34
34
|
connection.addresses = addresses
|
35
|
-
|
35
|
+
emit(:resolve, connection)
|
36
36
|
end
|
37
37
|
|
38
38
|
def early_resolve(connection, hostname: connection.origin.host)
|
data/lib/httpx/session.rb
CHANGED
@@ -207,7 +207,7 @@ module HTTPX
|
|
207
207
|
|
208
208
|
return responses unless request
|
209
209
|
|
210
|
-
pool.next_tick until (response = fetch_response(request, connections, request.options))
|
210
|
+
catch(:coalesced) { pool.next_tick } until (response = fetch_response(request, connections, request.options))
|
211
211
|
|
212
212
|
responses << response
|
213
213
|
requests.shift
|
@@ -309,18 +309,4 @@ module HTTPX
|
|
309
309
|
# :nocov:
|
310
310
|
end
|
311
311
|
end
|
312
|
-
|
313
|
-
unless ENV.grep(/https?_proxy$/i).empty?
|
314
|
-
proxy_session = plugin(:proxy)
|
315
|
-
::HTTPX.send(:remove_const, :Session)
|
316
|
-
::HTTPX.send(:const_set, :Session, proxy_session.class)
|
317
|
-
end
|
318
|
-
|
319
|
-
# :nocov:
|
320
|
-
if Session.default_options.debug_level > 2
|
321
|
-
proxy_session = plugin(:internal_telemetry)
|
322
|
-
::HTTPX.send(:remove_const, :Session)
|
323
|
-
::HTTPX.send(:const_set, :Session, proxy_session.class)
|
324
|
-
end
|
325
|
-
# :nocov:
|
326
312
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module HTTPX
|
4
|
+
unless ENV.keys.grep(/\Ahttps?_proxy\z/i).empty?
|
5
|
+
proxy_session = plugin(:proxy)
|
6
|
+
remove_const(:Session)
|
7
|
+
const_set(:Session, proxy_session.class)
|
8
|
+
remove_const(:Options)
|
9
|
+
const_set(:Options, proxy_session.class.default_options.class)
|
10
|
+
end
|
11
|
+
|
12
|
+
# :nocov:
|
13
|
+
if Session.default_options.debug_level > 2
|
14
|
+
proxy_session = plugin(:internal_telemetry)
|
15
|
+
remove_const(:Session)
|
16
|
+
const_set(:Session, proxy_session.class)
|
17
|
+
end
|
18
|
+
# :nocov:
|
19
|
+
end
|
data/lib/httpx/version.rb
CHANGED
data/lib/httpx.rb
CHANGED
data/sig/connection/http1.rbs
CHANGED
data/sig/connection/http2.rbs
CHANGED
@@ -46,8 +46,6 @@ module HTTPX
|
|
46
46
|
|
47
47
|
def send_pending: () -> void
|
48
48
|
|
49
|
-
def headline_uri: (Request) -> String
|
50
|
-
|
51
49
|
def set_protocol_headers: (Request) -> _Each[[String, String]]
|
52
50
|
|
53
51
|
def handle: (Request request, HTTP2Next::Stream stream) -> void
|
@@ -56,6 +54,8 @@ module HTTPX
|
|
56
54
|
|
57
55
|
def handle_stream: (HTTP2Next::Stream stream, Request request) -> void
|
58
56
|
|
57
|
+
def join_headline: (Request request) -> String
|
58
|
+
|
59
59
|
def join_headers: (HTTP2Next::Stream stream, Request request) -> void
|
60
60
|
|
61
61
|
def join_trailers: (HTTP2Next::Stream stream, Request request) -> void
|
data/sig/connection.rbs
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: httpx
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.18.
|
4
|
+
version: 0.18.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tiago Cardoso
|
@@ -69,6 +69,7 @@ extra_rdoc_files:
|
|
69
69
|
- doc/release_notes/0_18_4.md
|
70
70
|
- doc/release_notes/0_18_5.md
|
71
71
|
- doc/release_notes/0_18_6.md
|
72
|
+
- doc/release_notes/0_18_7.md
|
72
73
|
- doc/release_notes/0_1_0.md
|
73
74
|
- doc/release_notes/0_2_0.md
|
74
75
|
- doc/release_notes/0_2_1.md
|
@@ -131,6 +132,7 @@ files:
|
|
131
132
|
- doc/release_notes/0_18_4.md
|
132
133
|
- doc/release_notes/0_18_5.md
|
133
134
|
- doc/release_notes/0_18_6.md
|
135
|
+
- doc/release_notes/0_18_7.md
|
134
136
|
- doc/release_notes/0_1_0.md
|
135
137
|
- doc/release_notes/0_2_0.md
|
136
138
|
- doc/release_notes/0_2_1.md
|
@@ -234,6 +236,7 @@ files:
|
|
234
236
|
- lib/httpx/selector.rb
|
235
237
|
- lib/httpx/session.rb
|
236
238
|
- lib/httpx/session2.rb
|
239
|
+
- lib/httpx/session_extensions.rb
|
237
240
|
- lib/httpx/timers.rb
|
238
241
|
- lib/httpx/transcoder.rb
|
239
242
|
- lib/httpx/transcoder/body.rb
|