httpx 0.11.3 → 0.12.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/README.md +2 -2
- data/doc/release_notes/0_11_1.md +5 -1
- data/doc/release_notes/0_12_0.md +55 -0
- data/lib/httpx.rb +2 -1
- data/lib/httpx/adapters/faraday.rb +4 -6
- data/lib/httpx/altsvc.rb +1 -0
- data/lib/httpx/connection.rb +63 -15
- data/lib/httpx/connection/http1.rb +8 -7
- data/lib/httpx/connection/http2.rb +32 -25
- data/lib/httpx/io.rb +16 -3
- data/lib/httpx/io/ssl.rb +7 -9
- data/lib/httpx/io/tcp.rb +9 -8
- data/lib/httpx/io/tls.rb +218 -0
- data/lib/httpx/io/tls/box.rb +365 -0
- data/lib/httpx/io/tls/context.rb +199 -0
- data/lib/httpx/io/tls/ffi.rb +390 -0
- data/lib/httpx/parser/http1.rb +4 -4
- data/lib/httpx/plugins/aws_sdk_authentication.rb +81 -0
- data/lib/httpx/plugins/aws_sigv4.rb +218 -0
- data/lib/httpx/plugins/compression/deflate.rb +2 -5
- data/lib/httpx/plugins/internal_telemetry.rb +93 -0
- data/lib/httpx/plugins/multipart.rb +2 -0
- data/lib/httpx/plugins/multipart/encoder.rb +4 -9
- data/lib/httpx/plugins/proxy.rb +1 -1
- data/lib/httpx/plugins/proxy/http.rb +1 -1
- data/lib/httpx/plugins/proxy/socks4.rb +8 -0
- data/lib/httpx/plugins/proxy/socks5.rb +8 -0
- data/lib/httpx/plugins/push_promise.rb +3 -2
- data/lib/httpx/plugins/retries.rb +1 -1
- data/lib/httpx/plugins/stream.rb +3 -5
- data/lib/httpx/pool.rb +0 -1
- data/lib/httpx/registry.rb +1 -7
- data/lib/httpx/request.rb +11 -1
- data/lib/httpx/resolver/https.rb +3 -11
- data/lib/httpx/response.rb +9 -2
- data/lib/httpx/selector.rb +5 -0
- data/lib/httpx/session.rb +25 -2
- data/lib/httpx/transcoder/body.rb +3 -5
- data/lib/httpx/version.rb +1 -1
- data/sig/connection/http1.rbs +2 -2
- data/sig/connection/http2.rbs +5 -3
- data/sig/plugins/aws_sdk_authentication.rbs +17 -0
- data/sig/plugins/aws_sigv4.rbs +65 -0
- data/sig/plugins/push_promise.rbs +1 -1
- metadata +13 -2
@@ -29,18 +29,13 @@ module HTTPX::Plugins
|
|
29
29
|
|
30
30
|
def rewind
|
31
31
|
form = @form.each_with_object([]) do |(key, val), aux|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
val.rewind
|
36
|
-
val
|
37
|
-
else
|
38
|
-
v
|
39
|
-
end
|
40
|
-
aux << [key, v]
|
32
|
+
val = val.reopen(val.path, File::RDONLY) if val.is_a?(File) && val.closed?
|
33
|
+
val.rewind if val.respond_to?(:rewind)
|
34
|
+
aux << [key, val]
|
41
35
|
end
|
42
36
|
@form = form
|
43
37
|
@parts = to_parts(form)
|
38
|
+
@part_index = 0
|
44
39
|
end
|
45
40
|
|
46
41
|
private
|
data/lib/httpx/plugins/proxy.rb
CHANGED
@@ -81,7 +81,7 @@ module HTTPX
|
|
81
81
|
request.uri.to_s
|
82
82
|
end
|
83
83
|
|
84
|
-
def
|
84
|
+
def set_protocol_headers(request)
|
85
85
|
super
|
86
86
|
proxy_params = @options.proxy
|
87
87
|
request.headers["proxy-authorization"] = "Basic #{proxy_params.token_authentication}" if proxy_params.authenticated?
|
@@ -35,6 +35,14 @@ module HTTPX
|
|
35
35
|
super || @state == :authenticating || @state == :negotiating
|
36
36
|
end
|
37
37
|
|
38
|
+
def interests
|
39
|
+
if @state == :connecting || @state == :authenticating || @state == :negotiating
|
40
|
+
return @write_buffer.empty? ? :r : :w
|
41
|
+
end
|
42
|
+
|
43
|
+
super
|
44
|
+
end
|
45
|
+
|
38
46
|
private
|
39
47
|
|
40
48
|
def transition(nextstate)
|
@@ -43,7 +43,7 @@ module HTTPX
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def __on_promise_request(parser, stream, h)
|
46
|
-
log(level: 1) do
|
46
|
+
log(level: 1, color: :yellow) do
|
47
47
|
# :nocov:
|
48
48
|
h.map { |k, v| "#{stream.id}: -> PROMISE HEADER: #{k}: #{v}" }.join("\n")
|
49
49
|
# :nocov:
|
@@ -57,6 +57,8 @@ module HTTPX
|
|
57
57
|
request.merge_headers(headers)
|
58
58
|
promise_headers[stream] = request
|
59
59
|
parser.pending.delete(request)
|
60
|
+
parser.streams[request] = stream
|
61
|
+
request.transition(:done)
|
60
62
|
else
|
61
63
|
stream.refuse
|
62
64
|
end
|
@@ -67,7 +69,6 @@ module HTTPX
|
|
67
69
|
return unless request
|
68
70
|
|
69
71
|
parser.__send__(:on_stream_headers, stream, request, h)
|
70
|
-
request.transition(:done)
|
71
72
|
response = request.response
|
72
73
|
response.mark_as_pushed!
|
73
74
|
stream.on(:data, &parser.method(:on_stream_data).curry(3)[stream, request])
|
data/lib/httpx/plugins/stream.rb
CHANGED
@@ -119,11 +119,9 @@ module HTTPX
|
|
119
119
|
end
|
120
120
|
|
121
121
|
def method_missing(meth, *args, &block)
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
super
|
126
|
-
end
|
122
|
+
return super unless @options.response_class.public_method_defined?(meth)
|
123
|
+
|
124
|
+
response.__send__(meth, *args, &block)
|
127
125
|
end
|
128
126
|
end
|
129
127
|
end
|
data/lib/httpx/pool.rb
CHANGED
data/lib/httpx/registry.rb
CHANGED
@@ -62,13 +62,7 @@ module HTTPX
|
|
62
62
|
handler = @registry.fetch(tag)
|
63
63
|
raise(Error, "#{tag} is not registered in #{self}") unless handler
|
64
64
|
|
65
|
-
|
66
|
-
when Symbol, String
|
67
|
-
obj = const_get(handler)
|
68
|
-
@registry[tag] = obj
|
69
|
-
else
|
70
|
-
handler
|
71
|
-
end
|
65
|
+
handler
|
72
66
|
end
|
73
67
|
|
74
68
|
# @param [Object] tag the identifier for the handler in the registry
|
data/lib/httpx/request.rb
CHANGED
@@ -217,6 +217,16 @@ module HTTPX
|
|
217
217
|
"#{unbounded_body? ? "stream" : "@bytesize=#{bytesize}"}>"
|
218
218
|
end
|
219
219
|
# :nocov:
|
220
|
+
|
221
|
+
def respond_to_missing?(meth, *args)
|
222
|
+
@body.respond_to?(meth, *args) || super
|
223
|
+
end
|
224
|
+
|
225
|
+
def method_missing(meth, *args, &block)
|
226
|
+
return super unless @body.respond_to?(meth)
|
227
|
+
|
228
|
+
@body.__send__(meth, *args, &block)
|
229
|
+
end
|
220
230
|
end
|
221
231
|
|
222
232
|
def transition(nextstate)
|
@@ -247,7 +257,7 @@ module HTTPX
|
|
247
257
|
return if @state == :expect
|
248
258
|
end
|
249
259
|
@state = nextstate
|
250
|
-
emit(@state)
|
260
|
+
emit(@state, self)
|
251
261
|
nil
|
252
262
|
end
|
253
263
|
|
data/lib/httpx/resolver/https.rb
CHANGED
@@ -55,20 +55,12 @@ module HTTPX
|
|
55
55
|
early_resolve(connection) || resolve(connection)
|
56
56
|
end
|
57
57
|
|
58
|
-
def timeout
|
59
|
-
@connections.map(&:timeout).min
|
60
|
-
end
|
61
|
-
|
62
58
|
def closed?
|
63
|
-
|
64
|
-
|
65
|
-
resolver_connection.closed?
|
59
|
+
true
|
66
60
|
end
|
67
61
|
|
68
|
-
def
|
69
|
-
|
70
|
-
|
71
|
-
resolver_connection.__send__(__method__)
|
62
|
+
def empty?
|
63
|
+
true
|
72
64
|
end
|
73
65
|
|
74
66
|
private
|
data/lib/httpx/response.rb
CHANGED
@@ -268,8 +268,15 @@ module HTTPX
|
|
268
268
|
@error.message
|
269
269
|
end
|
270
270
|
|
271
|
-
|
272
|
-
|
271
|
+
if Exception.method_defined?(:full_message)
|
272
|
+
def to_s
|
273
|
+
@error.full_message
|
274
|
+
end
|
275
|
+
else
|
276
|
+
def to_s
|
277
|
+
"#{@error.message} (#{@error.class})\n" \
|
278
|
+
"#{@error.backtrace.join("\n") if @error.backtrace}"
|
279
|
+
end
|
273
280
|
end
|
274
281
|
|
275
282
|
def raise_for_status
|
data/lib/httpx/selector.rb
CHANGED
@@ -69,6 +69,11 @@ class HTTPX::Selector
|
|
69
69
|
|
70
70
|
if @selectables.empty?
|
71
71
|
@selectables = selectables
|
72
|
+
|
73
|
+
# do not run event loop if there's nothing to wait on.
|
74
|
+
# this might happen if connect failed and connection was unregistered.
|
75
|
+
return if (!r || r.empty?) && (!w || w.empty?)
|
76
|
+
|
72
77
|
break
|
73
78
|
else
|
74
79
|
@selectables = [*selectables, @selectables]
|
data/lib/httpx/session.rb
CHANGED
@@ -199,7 +199,18 @@ module HTTPX
|
|
199
199
|
responses << response
|
200
200
|
requests.shift
|
201
201
|
|
202
|
-
break if requests.empty?
|
202
|
+
break if requests.empty?
|
203
|
+
|
204
|
+
next unless pool.empty?
|
205
|
+
|
206
|
+
# in some cases, the pool of connections might have been drained because there was some
|
207
|
+
# handshake error, and the error responses have already been emitted, but there was no
|
208
|
+
# opportunity to traverse the requests, hence we're returning only a fraction of the errors
|
209
|
+
# we were supposed to. This effectively fetches the existing responses and return them.
|
210
|
+
while (request = requests.shift)
|
211
|
+
responses << fetch_response(request, connections, request_options)
|
212
|
+
end
|
213
|
+
break
|
203
214
|
end
|
204
215
|
responses
|
205
216
|
ensure
|
@@ -269,7 +280,19 @@ module HTTPX
|
|
269
280
|
end
|
270
281
|
# :nocov:
|
271
282
|
end
|
283
|
+
end
|
284
|
+
|
285
|
+
unless ENV.grep(/https?_proxy$/i).empty?
|
286
|
+
proxy_session = plugin(:proxy)
|
287
|
+
::HTTPX.send(:remove_const, :Session)
|
288
|
+
::HTTPX.send(:const_set, :Session, proxy_session.class)
|
289
|
+
end
|
272
290
|
|
273
|
-
|
291
|
+
# :nocov:
|
292
|
+
if Session.default_options.debug_level > 2
|
293
|
+
proxy_session = plugin(:internal_telemetry)
|
294
|
+
::HTTPX.send(:remove_const, :Session)
|
295
|
+
::HTTPX.send(:const_set, :Session, proxy_session.class)
|
274
296
|
end
|
297
|
+
# :nocov:
|
275
298
|
end
|
@@ -44,11 +44,9 @@ module HTTPX::Transcoder
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def method_missing(meth, *args, &block)
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
super
|
51
|
-
end
|
47
|
+
return super unless @raw.respond_to?(meth)
|
48
|
+
|
49
|
+
@raw.__send__(meth, *args, &block)
|
52
50
|
end
|
53
51
|
end
|
54
52
|
|
data/lib/httpx/version.rb
CHANGED
data/sig/connection/http1.rbs
CHANGED
@@ -31,7 +31,7 @@ module HTTPX
|
|
31
31
|
|
32
32
|
def on_headers: (Hash[String, Array[String]] headers) -> void
|
33
33
|
|
34
|
-
def on_trailers: (
|
34
|
+
def on_trailers: (Hash[String, Array[String]] headers) -> void
|
35
35
|
|
36
36
|
def on_data: (string chunk) -> void
|
37
37
|
|
@@ -51,7 +51,7 @@ module HTTPX
|
|
51
51
|
|
52
52
|
def disable_pipelining: () -> void
|
53
53
|
|
54
|
-
def
|
54
|
+
def set_protocol_headers: (Request) -> void
|
55
55
|
|
56
56
|
def headline_uri: (Request) -> String
|
57
57
|
|
data/sig/connection/http2.rbs
CHANGED
@@ -3,7 +3,7 @@ module HTTPX
|
|
3
3
|
include Callbacks
|
4
4
|
include Loggable
|
5
5
|
|
6
|
-
attr_reader streams: Hash[HTTP2Next::Stream
|
6
|
+
attr_reader streams: Hash[Request, HTTP2Next::Stream]
|
7
7
|
attr_reader pending: Array[Request]
|
8
8
|
|
9
9
|
@options: Options
|
@@ -13,7 +13,7 @@ module HTTPX
|
|
13
13
|
@pings: Array[String]
|
14
14
|
@buffer: Buffer
|
15
15
|
|
16
|
-
def interests: () -> io_interests
|
16
|
+
def interests: () -> io_interests?
|
17
17
|
|
18
18
|
def close: () -> void
|
19
19
|
|
@@ -23,6 +23,8 @@ module HTTPX
|
|
23
23
|
|
24
24
|
def <<: (String) -> void
|
25
25
|
|
26
|
+
def can_buffer_more_requests: () -> bool
|
27
|
+
|
26
28
|
def send: (Request) -> void
|
27
29
|
|
28
30
|
def consume: () -> void
|
@@ -41,7 +43,7 @@ module HTTPX
|
|
41
43
|
|
42
44
|
def headline_uri: (Request) -> String
|
43
45
|
|
44
|
-
def
|
46
|
+
def set_protocol_headers: (Request) -> void
|
45
47
|
|
46
48
|
def handle: (Request request, HTTP2Next::Stream stream) -> void
|
47
49
|
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module HTTPX
|
2
|
+
module Plugins
|
3
|
+
module AwsSdkAuthentication
|
4
|
+
class Credentials
|
5
|
+
include _SigV4Credentials
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.load_dependencies: (singleton(Session)) -> void
|
9
|
+
|
10
|
+
def self.extra_options: (Options) -> (Options)
|
11
|
+
|
12
|
+
module InstanceMethods
|
13
|
+
def aws_sdk_authentication: (**untyped) -> instance
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module HTTPX
|
2
|
+
module Plugins
|
3
|
+
|
4
|
+
interface _SigV4Credentials
|
5
|
+
def username: () -> String
|
6
|
+
def password: () -> String
|
7
|
+
def security_token: () -> String?
|
8
|
+
end
|
9
|
+
|
10
|
+
module AWSSigV4
|
11
|
+
|
12
|
+
Credentials: _SigV4Credentials
|
13
|
+
|
14
|
+
|
15
|
+
class Signer
|
16
|
+
|
17
|
+
def sign!: (Request) -> void
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def initialize: (
|
22
|
+
service: String,
|
23
|
+
region: String,
|
24
|
+
?credentials: _SigV4Credentials,
|
25
|
+
?username: String,
|
26
|
+
?password: String,
|
27
|
+
?security_token: String,
|
28
|
+
?provider_prefix: String,
|
29
|
+
?header_provider_field: String,
|
30
|
+
?unsigned_headers: Array[String],
|
31
|
+
?apply_checksum_header: bool,
|
32
|
+
?algorithm: String
|
33
|
+
) -> untyped
|
34
|
+
|
35
|
+
|
36
|
+
def sha256_hexdigest: (bodyIO value) -> String
|
37
|
+
|
38
|
+
def hmac: (String key, String value) -> String
|
39
|
+
def hexhmac: (String key, String value) -> String
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
interface _SigV4Options
|
44
|
+
def sigv4_signer: () -> Signer?
|
45
|
+
def sigv4_signer=: (Signer) -> Signer
|
46
|
+
def with_sigv4_signer: (Signer) -> instance
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.extra_options: (Options) -> (Options & _SigV4Options)
|
50
|
+
def self.load_dependencies: (singleton(Session)) -> void
|
51
|
+
|
52
|
+
module InstanceMethods
|
53
|
+
def aws_sigv4_authentication: (**untyped) -> instance
|
54
|
+
end
|
55
|
+
|
56
|
+
module RequestMethods
|
57
|
+
def canonical_path: () -> String
|
58
|
+
|
59
|
+
def canonical_query: () -> String
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
type awsSigV4Session = Session & Plugins::AWSSigV4::InstanceMethods
|
64
|
+
end
|
65
|
+
end
|
@@ -11,7 +11,7 @@ module HTTPX
|
|
11
11
|
module InstanceMethods
|
12
12
|
private
|
13
13
|
|
14
|
-
def promise_headers:
|
14
|
+
def promise_headers: () -> Hash[HTTP2Next::Stream, Request]
|
15
15
|
def __on_promise_request: (Connection::HTTP2, HTTP2Next::Stream, headers_input) -> void
|
16
16
|
def __on_promise_response: (Connection::HTTP2, HTTP2Next::Stream, headers_input) -> void
|
17
17
|
end
|