httpx 0.10.0 → 0.10.1
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_10_1.md +39 -0
- data/lib/httpx/chainable.rb +7 -6
- data/lib/httpx/connection.rb +4 -15
- data/lib/httpx/connection/http1.rb +14 -1
- data/lib/httpx/connection/http2.rb +11 -12
- data/lib/httpx/errors.rb +1 -1
- data/lib/httpx/plugins/multipart.rb +15 -1
- data/lib/httpx/plugins/proxy.rb +16 -2
- data/lib/httpx/plugins/proxy/socks4.rb +14 -16
- data/lib/httpx/pool.rb +8 -14
- data/lib/httpx/request.rb +1 -1
- data/lib/httpx/resolver.rb +0 -2
- data/lib/httpx/resolver/https.rb +15 -22
- data/lib/httpx/resolver/native.rb +12 -13
- data/lib/httpx/resolver/resolver_mixin.rb +4 -2
- data/lib/httpx/resolver/system.rb +2 -2
- data/lib/httpx/selector.rb +8 -13
- data/lib/httpx/session.rb +9 -3
- data/lib/httpx/transcoder.rb +18 -0
- data/lib/httpx/transcoder/form.rb +9 -1
- data/lib/httpx/version.rb +1 -1
- data/sig/connection.rbs +84 -1
- data/sig/connection/http1.rbs +66 -0
- data/sig/connection/http2.rbs +74 -0
- data/sig/httpx.rbs +1 -0
- data/sig/options.rbs +3 -3
- data/sig/plugins/basic_authentication.rbs +1 -1
- data/sig/plugins/compression.rbs +1 -1
- 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/h2c.rbs +1 -1
- data/sig/plugins/multipart.rbs +4 -2
- data/sig/plugins/persistent.rbs +1 -1
- data/sig/plugins/proxy.rbs +2 -2
- data/sig/plugins/proxy/ssh.rbs +1 -1
- data/sig/plugins/rate_limiter.rbs +1 -1
- data/sig/pool.rbs +36 -2
- data/sig/request.rbs +1 -1
- data/sig/resolver.rbs +26 -0
- data/sig/resolver/https.rbs +49 -0
- data/sig/resolver/native.rbs +60 -0
- data/sig/resolver/resolver_mixin.rbs +27 -0
- data/sig/resolver/system.rbs +17 -0
- data/sig/response.rbs +1 -1
- data/sig/selector.rbs +20 -0
- data/sig/session.rbs +2 -2
- data/sig/transcoder.rbs +4 -2
- data/sig/transcoder/form.rbs +1 -1
- metadata +11 -4
- data/lib/httpx/resolver/options.rb +0 -25
- data/sig/test.rbs +0 -9
@@ -15,7 +15,6 @@ module HTTPX
|
|
15
15
|
"AAAA" => Resolv::DNS::Resource::IN::AAAA,
|
16
16
|
}.freeze
|
17
17
|
|
18
|
-
# :nocov:
|
19
18
|
DEFAULTS = if RUBY_VERSION < "2.2"
|
20
19
|
{
|
21
20
|
**Resolv::DNS::Config.default_config_hash,
|
@@ -44,7 +43,6 @@ module HTTPX
|
|
44
43
|
false
|
45
44
|
end
|
46
45
|
end if DEFAULTS[:nameserver]
|
47
|
-
# :nocov:
|
48
46
|
|
49
47
|
DNS_PORT = 53
|
50
48
|
|
@@ -53,15 +51,15 @@ module HTTPX
|
|
53
51
|
def initialize(options)
|
54
52
|
@options = Options.new(options)
|
55
53
|
@ns_index = 0
|
56
|
-
@resolver_options =
|
57
|
-
@nameserver = @resolver_options
|
58
|
-
@_timeouts = Array(@resolver_options
|
54
|
+
@resolver_options = DEFAULTS.merge(@options.resolver_options)
|
55
|
+
@nameserver = @resolver_options[:nameserver]
|
56
|
+
@_timeouts = Array(@resolver_options[:timeouts])
|
59
57
|
@timeouts = Hash.new { |timeouts, host| timeouts[host] = @_timeouts.dup }
|
60
|
-
@_record_types = Hash.new { |types, host| types[host] = @resolver_options
|
58
|
+
@_record_types = Hash.new { |types, host| types[host] = @resolver_options[:record_types].dup }
|
61
59
|
@connections = []
|
62
60
|
@queries = {}
|
63
61
|
@read_buffer = "".b
|
64
|
-
@write_buffer = Buffer.new(@resolver_options
|
62
|
+
@write_buffer = Buffer.new(@resolver_options[:packet_size])
|
65
63
|
@state = :idle
|
66
64
|
end
|
67
65
|
|
@@ -111,9 +109,9 @@ module HTTPX
|
|
111
109
|
return if early_resolve(connection)
|
112
110
|
|
113
111
|
if @nameserver.nil?
|
114
|
-
ex = ResolveError.new("
|
112
|
+
ex = ResolveError.new("No available nameserver")
|
115
113
|
ex.set_backtrace(caller)
|
116
|
-
|
114
|
+
throw(:resolve_error, ex)
|
117
115
|
else
|
118
116
|
@connections << connection
|
119
117
|
resolve
|
@@ -164,7 +162,7 @@ module HTTPX
|
|
164
162
|
connections.each { |ch| resolve(ch) }
|
165
163
|
end
|
166
164
|
|
167
|
-
def dread(wsize = @resolver_options
|
165
|
+
def dread(wsize = @resolver_options[:packet_size])
|
168
166
|
loop do
|
169
167
|
siz = @io.read(wsize, @read_buffer)
|
170
168
|
return unless siz && siz.positive?
|
@@ -199,13 +197,14 @@ module HTTPX
|
|
199
197
|
end
|
200
198
|
end
|
201
199
|
|
202
|
-
if addresses.empty?
|
200
|
+
if addresses.nil? || addresses.empty?
|
203
201
|
hostname, connection = @queries.first
|
204
202
|
@_record_types[hostname].shift
|
205
203
|
if @_record_types[hostname].empty?
|
206
204
|
@queries.delete(hostname)
|
207
205
|
@_record_types.delete(hostname)
|
208
206
|
@connections.delete(connection)
|
207
|
+
|
209
208
|
raise NativeResolveError.new(connection, hostname)
|
210
209
|
end
|
211
210
|
else
|
@@ -223,7 +222,7 @@ module HTTPX
|
|
223
222
|
end
|
224
223
|
else
|
225
224
|
@connections.delete(connection)
|
226
|
-
Resolver.cached_lookup_set(connection.origin.host, addresses) if @resolver_options
|
225
|
+
Resolver.cached_lookup_set(connection.origin.host, addresses) if @resolver_options[:cache]
|
227
226
|
emit_addresses(connection, addresses.map { |addr| addr["data"] })
|
228
227
|
end
|
229
228
|
end
|
@@ -243,7 +242,7 @@ module HTTPX
|
|
243
242
|
log { "resolver: resolve IDN #{connection.origin.non_ascii_hostname} as #{hostname}" } if connection.origin.non_ascii_hostname
|
244
243
|
end
|
245
244
|
@queries[hostname] = connection
|
246
|
-
type = @_record_types[hostname].first
|
245
|
+
type = @_record_types[hostname].first || "A"
|
247
246
|
log { "resolver: query #{type} for #{hostname}" }
|
248
247
|
begin
|
249
248
|
@write_buffer << Resolver.encode_dns_query(hostname, type: RECORD_TYPES[type])
|
@@ -38,7 +38,7 @@ module HTTPX
|
|
38
38
|
def early_resolve(connection, hostname: connection.origin.host)
|
39
39
|
addresses = connection.addresses ||
|
40
40
|
ip_resolve(hostname) ||
|
41
|
-
(@resolver_options
|
41
|
+
(@resolver_options[:cache] && Resolver.cached_lookup(hostname)) ||
|
42
42
|
system_resolve(hostname)
|
43
43
|
return unless addresses
|
44
44
|
|
@@ -57,11 +57,13 @@ module HTTPX
|
|
57
57
|
ips.map { |ip| IPAddr.new(ip) }
|
58
58
|
end
|
59
59
|
|
60
|
-
def emit_resolve_error(connection, hostname, ex = nil)
|
60
|
+
def emit_resolve_error(connection, hostname = connection.origin.host, ex = nil)
|
61
61
|
emit(:error, connection, resolve_error(hostname, ex))
|
62
62
|
end
|
63
63
|
|
64
64
|
def resolve_error(hostname, ex = nil)
|
65
|
+
return ex if ex.is_a?(ResolveError)
|
66
|
+
|
65
67
|
message = ex ? ex.message : "Can't resolve #{hostname}"
|
66
68
|
error = ResolveError.new(message)
|
67
69
|
error.set_backtrace(ex ? ex.backtrace : caller)
|
@@ -14,9 +14,9 @@ module HTTPX
|
|
14
14
|
|
15
15
|
def initialize(options)
|
16
16
|
@options = Options.new(options)
|
17
|
-
@resolver_options =
|
17
|
+
@resolver_options = @options.resolver_options
|
18
18
|
@state = :idle
|
19
|
-
resolv_options = @resolver_options.
|
19
|
+
resolv_options = @resolver_options.dup
|
20
20
|
timeouts = resolv_options.delete(:timeouts)
|
21
21
|
resolv_options.delete(:cache)
|
22
22
|
@resolver = Resolv::DNS.new(resolv_options.empty? ? nil : resolv_options)
|
data/lib/httpx/selector.rb
CHANGED
@@ -4,19 +4,14 @@ require "io/wait"
|
|
4
4
|
|
5
5
|
module IOExtensions
|
6
6
|
refine IO do
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
return unless r || w
|
17
|
-
|
18
|
-
self
|
19
|
-
end
|
7
|
+
# provides a fallback for rubies where IO#wait isn't implemented,
|
8
|
+
# but IO#wait_readable and IO#wait_writable are.
|
9
|
+
def wait(timeout = nil, _mode = :read_write)
|
10
|
+
r, w = IO.select([self], [self], nil, timeout)
|
11
|
+
|
12
|
+
return unless r || w
|
13
|
+
|
14
|
+
self
|
20
15
|
end
|
21
16
|
end
|
22
17
|
end
|
data/lib/httpx/session.rb
CHANGED
@@ -77,10 +77,16 @@ module HTTPX
|
|
77
77
|
end
|
78
78
|
|
79
79
|
def set_connection_callbacks(connection, connections, options)
|
80
|
-
connection.on(:
|
81
|
-
other_connection =
|
80
|
+
connection.on(:misdirected) do |misdirected_request|
|
81
|
+
other_connection = connection.create_idle(ssl: { alpn_protocols: %w[http/1.1] })
|
82
|
+
other_connection.merge(connection)
|
83
|
+
catch(:coalesced) do
|
84
|
+
pool.init_connection(other_connection, options)
|
85
|
+
end
|
86
|
+
set_connection_callbacks(other_connection, connections, options)
|
82
87
|
connections << other_connection
|
83
|
-
|
88
|
+
misdirected_request.transition(:idle)
|
89
|
+
other_connection.send(misdirected_request)
|
84
90
|
end
|
85
91
|
connection.on(:altsvc) do |alt_origin, origin, alt_params|
|
86
92
|
other_connection = build_altsvc_connection(connection, connections, alt_origin, origin, alt_params, options)
|
data/lib/httpx/transcoder.rb
CHANGED
@@ -3,6 +3,24 @@
|
|
3
3
|
module HTTPX
|
4
4
|
module Transcoder
|
5
5
|
extend Registry
|
6
|
+
|
7
|
+
def self.normalize_keys(key, value, &block)
|
8
|
+
if value.respond_to?(:to_ary)
|
9
|
+
if value.empty?
|
10
|
+
block.call("#{key}[]")
|
11
|
+
else
|
12
|
+
value.to_ary.each do |element|
|
13
|
+
normalize_keys("#{key}[]", element, &block)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
elsif value.respond_to?(:to_hash)
|
17
|
+
value.to_hash.each do |child_key, child_value|
|
18
|
+
normalize_keys("#{key}[#{child_key}]", child_value, &block)
|
19
|
+
end
|
20
|
+
else
|
21
|
+
block.call(key.to_s, value)
|
22
|
+
end
|
23
|
+
end
|
6
24
|
end
|
7
25
|
end
|
8
26
|
|
@@ -12,10 +12,18 @@ module HTTPX::Transcoder
|
|
12
12
|
|
13
13
|
def_delegator :@raw, :to_s
|
14
14
|
|
15
|
+
def_delegator :@raw, :to_str
|
16
|
+
|
15
17
|
def_delegator :@raw, :bytesize
|
16
18
|
|
17
19
|
def initialize(form)
|
18
|
-
@raw =
|
20
|
+
@raw = form.each_with_object("".b) do |(key, val), buf|
|
21
|
+
HTTPX::Transcoder.normalize_keys(key, val) do |k, v|
|
22
|
+
buf << "&" unless buf.empty?
|
23
|
+
buf << URI.encode_www_form_component(k)
|
24
|
+
buf << "=#{URI.encode_www_form_component(v.to_s)}" unless v.nil?
|
25
|
+
end
|
26
|
+
end
|
19
27
|
end
|
20
28
|
|
21
29
|
def content_type
|
data/lib/httpx/version.rb
CHANGED
data/sig/connection.rbs
CHANGED
@@ -1,2 +1,85 @@
|
|
1
|
-
|
1
|
+
module HTTPX
|
2
|
+
class Connection
|
3
|
+
interface _Parser
|
4
|
+
|
5
|
+
def on: (Symbol) { (*untyped) -> void } -> void
|
6
|
+
def empty?: () -> bool
|
7
|
+
def close: () -> void
|
8
|
+
def consume: () -> void
|
9
|
+
def <<: (string) -> void
|
10
|
+
end
|
11
|
+
|
12
|
+
include Loggable
|
13
|
+
include Callbacks
|
14
|
+
extend HTTPX::Registry[String, Class]
|
15
|
+
|
16
|
+
attr_reader origin: generic_uri
|
17
|
+
attr_reader state: Symbol
|
18
|
+
attr_reader pending: Array[Request]
|
19
|
+
attr_reader options: options
|
20
|
+
|
21
|
+
def addresses: () -> Array[ipaddr]?
|
22
|
+
|
23
|
+
def addresses=: (Array[ipaddr]) -> void
|
24
|
+
|
25
|
+
def match?: (generic_uri, options) -> bool
|
26
|
+
|
27
|
+
def mergeable?: (Connection) -> bool
|
28
|
+
|
29
|
+
def coalescable?: (Connection) -> bool
|
30
|
+
|
31
|
+
def create_idle: (options) -> Connection
|
32
|
+
| () -> Connection
|
33
|
+
|
34
|
+
def merge: (Connection) -> void
|
35
|
+
|
36
|
+
def purge_pending: () { (Request) -> void } -> void
|
37
|
+
|
38
|
+
def match_altsvcs?: (generic_uri) -> bool
|
39
|
+
|
40
|
+
def connecting?: () -> bool
|
41
|
+
def inflight?: () -> boolish
|
42
|
+
|
43
|
+
def interests: () -> io_interests?
|
44
|
+
|
45
|
+
def to_io: () -> _ToIO
|
46
|
+
|
47
|
+
def call: () -> void
|
48
|
+
|
49
|
+
def close: () -> void
|
50
|
+
def reset: () -> void
|
51
|
+
|
52
|
+
def send: (Request) -> void
|
53
|
+
|
54
|
+
def timeout: () -> Numeric?
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def initialize: (String, generic_uri, options) -> untyped
|
59
|
+
|
60
|
+
def connect: () -> void
|
61
|
+
|
62
|
+
def exhausted?: () -> boolish
|
63
|
+
|
64
|
+
def consume: () -> void
|
65
|
+
|
66
|
+
def send_pending: () -> void
|
67
|
+
|
68
|
+
def parser: () -> _Parser
|
69
|
+
|
70
|
+
def build_parser: () -> _Parser
|
71
|
+
| (String) -> _Parser
|
72
|
+
|
73
|
+
def set_parser_callbacks: (_Parser) -> void
|
74
|
+
|
75
|
+
def transition: (Symbol) -> void
|
76
|
+
|
77
|
+
def handle_response: () -> void
|
78
|
+
|
79
|
+
def on_error: (StandardError) -> void
|
80
|
+
|
81
|
+
def handle_error: (StandardError) -> void
|
82
|
+
|
83
|
+
def total_timeout: () -> Timers::Timer?
|
84
|
+
end
|
2
85
|
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module HTTPX
|
2
|
+
class Connection::HTTP1
|
3
|
+
include Callbacks
|
4
|
+
include Loggable
|
5
|
+
|
6
|
+
attr_reader pending: Array[Request]
|
7
|
+
|
8
|
+
@options: Options
|
9
|
+
@max_concurrent_requests: Integer
|
10
|
+
@max_requests: Integer
|
11
|
+
@parser: HTTP1
|
12
|
+
@buffer: Buffer
|
13
|
+
|
14
|
+
def interests: () -> io_interests?
|
15
|
+
|
16
|
+
def reset: () -> void
|
17
|
+
|
18
|
+
def close: () -> void
|
19
|
+
|
20
|
+
def empty?: () -> bool
|
21
|
+
|
22
|
+
def exhausted?: () -> bool
|
23
|
+
|
24
|
+
def <<: (String) -> void
|
25
|
+
|
26
|
+
def send: (Request) -> void
|
27
|
+
|
28
|
+
def consume: () -> void
|
29
|
+
|
30
|
+
def handle_error: (StandardError ex) -> void
|
31
|
+
|
32
|
+
def on_headers: (Hash[String, Array[String]] headers) -> void
|
33
|
+
|
34
|
+
def on_trailers: (Array[String, String] headers) -> void
|
35
|
+
|
36
|
+
def on_data: (string chunk) -> void
|
37
|
+
|
38
|
+
def on_complete: () -> void
|
39
|
+
|
40
|
+
def dispatch: () -> void
|
41
|
+
|
42
|
+
def ping: () -> void
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def initialize: (Buffer, options) -> untyped
|
47
|
+
|
48
|
+
def manage_connection: (Response) -> void
|
49
|
+
|
50
|
+
def disable: () -> void
|
51
|
+
|
52
|
+
def disable_pipelining: () -> void
|
53
|
+
|
54
|
+
def set_request_headers: (Request) -> void
|
55
|
+
|
56
|
+
def headline_uri: (Request) -> String
|
57
|
+
|
58
|
+
def handle: (Request request) -> void
|
59
|
+
|
60
|
+
def join_headers: (Request request) -> void
|
61
|
+
|
62
|
+
def join_body: (Request request) -> void
|
63
|
+
|
64
|
+
def capitalized: (String field) -> String
|
65
|
+
end
|
66
|
+
end
|
data/sig/connection/http2.rbs
CHANGED
@@ -1,4 +1,78 @@
|
|
1
1
|
module HTTPX
|
2
2
|
class Connection::HTTP2
|
3
|
+
include Callbacks
|
4
|
+
include Loggable
|
5
|
+
|
6
|
+
attr_reader streams: Hash[HTTP2Next::Stream, Response]
|
7
|
+
attr_reader pending: Array[Request]
|
8
|
+
|
9
|
+
@options: Options
|
10
|
+
@max_concurrent_requests: Integer
|
11
|
+
@max_requests: Integer
|
12
|
+
@drains: Hash[Request, String]
|
13
|
+
@pings: Array[String]
|
14
|
+
@buffer: Buffer
|
15
|
+
|
16
|
+
def interests: () -> io_interests
|
17
|
+
|
18
|
+
def close: () -> void
|
19
|
+
|
20
|
+
def empty?: () -> bool
|
21
|
+
|
22
|
+
def exhausted?: () -> bool
|
23
|
+
|
24
|
+
def <<: (String) -> void
|
25
|
+
|
26
|
+
def send: (Request) -> void
|
27
|
+
|
28
|
+
def consume: () -> void
|
29
|
+
|
30
|
+
def handle_error: (StandardError ex) -> void
|
31
|
+
|
32
|
+
def ping: () -> void
|
33
|
+
|
34
|
+
alias reset init_connection
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def initialize: (Buffer, options) -> untyped
|
39
|
+
|
40
|
+
def send_pending: () -> void
|
41
|
+
|
42
|
+
def headline_uri: (Request) -> String
|
43
|
+
|
44
|
+
def set_request_headers: (Request) -> void
|
45
|
+
|
46
|
+
def handle: (Request request, HTTP2Next::Stream stream) -> void
|
47
|
+
|
48
|
+
def init_connection: () -> void
|
49
|
+
|
50
|
+
def handle_stream: (HTTP2Next::Stream stream, Request request) -> void
|
51
|
+
|
52
|
+
def join_headers: (HTTP2Next::Stream stream, Request request) -> void
|
53
|
+
|
54
|
+
def join_body: (HTTP2Next::Stream stream, Request request) -> void
|
55
|
+
|
56
|
+
|
57
|
+
# def on_stream_headers: (HTTP2Next::Stream stream, Request request, Array[String, String] headers) -> void
|
58
|
+
|
59
|
+
# def on_stream_data: (HTTP2Next::Stream stream, Request request, string data) -> void
|
60
|
+
|
61
|
+
# def on_stream_close: (HTTP2Next::Stream stream, Request request, Symbol? error) -> void
|
62
|
+
|
63
|
+
def on_frame: (string bytes) -> void
|
64
|
+
|
65
|
+
def on_settings: (*untyped) -> void
|
66
|
+
|
67
|
+
def on_close: (Integer last_frame, Symbol? error, String? payload) -> void
|
68
|
+
|
69
|
+
def on_frame_sent: (HTTP2Next::frame) -> void
|
70
|
+
def on_frame_received: (HTTP2Next::frame) -> void
|
71
|
+
|
72
|
+
def on_promise: (HTTP2Next::Stream) -> void
|
73
|
+
|
74
|
+
def on_origin: (String) -> void
|
75
|
+
|
76
|
+
def on_pong: (string ping) -> void
|
3
77
|
end
|
4
78
|
end
|