httpx 0.15.1 → 0.16.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/0_15_2.md +9 -0
- data/doc/release_notes/0_15_3.md +5 -0
- data/doc/release_notes/0_15_4.md +5 -0
- data/doc/release_notes/0_16_0.md +93 -0
- data/lib/httpx.rb +6 -3
- data/lib/httpx/adapters/faraday.rb +3 -11
- data/lib/httpx/buffer.rb +1 -1
- data/lib/httpx/callbacks.rb +1 -1
- data/lib/httpx/chainable.rb +15 -8
- data/lib/httpx/connection.rb +2 -2
- data/lib/httpx/connection/http1.rb +3 -1
- data/lib/httpx/connection/http2.rb +1 -11
- data/lib/httpx/errors.rb +11 -11
- data/lib/httpx/io/ssl.rb +2 -2
- data/lib/httpx/io/tls.rb +1 -1
- data/lib/httpx/loggable.rb +1 -1
- data/lib/httpx/options.rb +81 -74
- data/lib/httpx/parser/http1.rb +1 -1
- data/lib/httpx/plugins/aws_sigv4.rb +10 -9
- data/lib/httpx/plugins/compression.rb +12 -11
- data/lib/httpx/plugins/cookies.rb +20 -7
- data/lib/httpx/plugins/cookies/cookie.rb +4 -3
- data/lib/httpx/plugins/cookies/jar.rb +24 -1
- data/lib/httpx/plugins/digest_authentication.rb +15 -11
- data/lib/httpx/plugins/expect.rb +19 -15
- data/lib/httpx/plugins/follow_redirects.rb +9 -9
- data/lib/httpx/plugins/grpc.rb +73 -47
- data/lib/httpx/plugins/grpc/call.rb +4 -1
- data/lib/httpx/plugins/ntlm_authentication.rb +8 -6
- data/lib/httpx/plugins/proxy.rb +4 -6
- data/lib/httpx/plugins/proxy/socks4.rb +2 -1
- data/lib/httpx/plugins/proxy/socks5.rb +2 -1
- data/lib/httpx/plugins/proxy/ssh.rb +9 -9
- data/lib/httpx/plugins/retries.rb +25 -21
- data/lib/httpx/plugins/upgrade.rb +7 -6
- data/lib/httpx/registry.rb +1 -1
- data/lib/httpx/request.rb +4 -12
- data/lib/httpx/resolver/https.rb +0 -2
- data/lib/httpx/response.rb +45 -18
- data/lib/httpx/selector.rb +13 -12
- data/lib/httpx/session.rb +19 -8
- data/lib/httpx/session2.rb +21 -0
- data/lib/httpx/transcoder/body.rb +1 -1
- data/lib/httpx/transcoder/chunker.rb +2 -1
- data/lib/httpx/version.rb +1 -1
- data/sig/buffer.rbs +2 -0
- data/sig/chainable.rbs +24 -28
- data/sig/connection.rbs +20 -8
- data/sig/connection/http1.rbs +3 -3
- data/sig/connection/http2.rbs +1 -1
- data/sig/errors.rbs +35 -1
- data/sig/headers.rbs +5 -5
- data/sig/httpx.rbs +4 -1
- data/sig/loggable.rbs +3 -1
- data/sig/options.rbs +35 -32
- data/sig/plugins/authentication.rbs +1 -1
- data/sig/plugins/aws_sdk_authentication.rbs +5 -1
- data/sig/plugins/aws_sigv4.rbs +1 -2
- data/sig/plugins/basic_authentication.rbs +1 -1
- data/sig/plugins/compression.rbs +4 -6
- data/sig/plugins/cookies.rbs +4 -5
- data/sig/plugins/cookies/cookie.rbs +5 -7
- data/sig/plugins/cookies/jar.rbs +9 -10
- data/sig/plugins/digest_authentication.rbs +2 -3
- data/sig/plugins/expect.rbs +2 -4
- data/sig/plugins/follow_redirects.rbs +3 -5
- data/sig/plugins/grpc.rbs +4 -7
- data/sig/plugins/h2c.rbs +0 -2
- data/sig/plugins/multipart.rbs +2 -4
- data/sig/plugins/ntlm_authentication.rbs +2 -3
- data/sig/plugins/persistent.rbs +3 -8
- data/sig/plugins/proxy.rbs +7 -7
- data/sig/plugins/proxy/ssh.rbs +4 -4
- data/sig/plugins/push_promise.rbs +0 -2
- data/sig/plugins/retries.rbs +4 -8
- data/sig/plugins/stream.rbs +1 -1
- data/sig/plugins/upgrade.rbs +2 -3
- data/sig/pool.rbs +1 -2
- data/sig/registry.rbs +1 -1
- data/sig/request.rbs +2 -2
- data/sig/resolver.rbs +7 -0
- data/sig/resolver/native.rbs +9 -5
- data/sig/resolver/resolver_mixin.rbs +4 -5
- data/sig/resolver/system.rbs +2 -0
- data/sig/response.rbs +17 -11
- data/sig/selector.rbs +7 -6
- data/sig/session.rbs +19 -14
- data/sig/transcoder.rbs +11 -4
- data/sig/transcoder/body.rbs +6 -1
- data/sig/transcoder/chunker.rbs +8 -2
- data/sig/transcoder/form.rbs +2 -1
- data/sig/transcoder/json.rbs +1 -0
- data/sig/utils.rbs +2 -0
- metadata +12 -2
data/lib/httpx/parser/http1.rb
CHANGED
@@ -141,22 +141,23 @@ module HTTPX
|
|
141
141
|
end
|
142
142
|
|
143
143
|
class << self
|
144
|
-
def
|
145
|
-
Class.new(options.class) do
|
146
|
-
def_option(:sigv4_signer, <<-OUT)
|
147
|
-
value.is_a?(#{Signer}) ? value : #{Signer}.new(value)
|
148
|
-
OUT
|
149
|
-
end.new(options)
|
150
|
-
end
|
151
|
-
|
152
|
-
def load_dependencies(klass)
|
144
|
+
def load_dependencies(*)
|
153
145
|
require "digest/sha2"
|
154
146
|
require "openssl"
|
147
|
+
end
|
148
|
+
|
149
|
+
def configure(klass)
|
155
150
|
klass.plugin(:expect)
|
156
151
|
klass.plugin(:compression)
|
157
152
|
end
|
158
153
|
end
|
159
154
|
|
155
|
+
module OptionsMethods
|
156
|
+
def option_sigv4_signer(value)
|
157
|
+
value.is_a?(Signer) ? value : Signer.new(value)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
160
161
|
module InstanceMethods
|
161
162
|
def aws_sigv4_authentication(**options)
|
162
163
|
with(sigv4_signer: Signer.new(**options))
|
@@ -23,21 +23,22 @@ module HTTPX
|
|
23
23
|
encodings = Module.new do
|
24
24
|
extend Registry
|
25
25
|
end
|
26
|
+
options.merge(encodings: encodings)
|
27
|
+
end
|
28
|
+
end
|
26
29
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
30
|
+
module OptionsMethods
|
31
|
+
def option_compression_threshold_size(value)
|
32
|
+
bytes = Integer(value)
|
33
|
+
raise TypeError, ":expect_threshold_size must be positive" unless bytes.positive?
|
31
34
|
|
32
|
-
|
33
|
-
|
35
|
+
bytes
|
36
|
+
end
|
34
37
|
|
35
|
-
|
36
|
-
|
38
|
+
def option_encodings(value)
|
39
|
+
raise TypeError, ":encodings must be a registry" unless value.respond_to?(:registry)
|
37
40
|
|
38
|
-
|
39
|
-
OUT
|
40
|
-
end.new(options).merge(encodings: encodings)
|
41
|
+
value
|
41
42
|
end
|
42
43
|
end
|
43
44
|
|
@@ -18,12 +18,10 @@ module HTTPX
|
|
18
18
|
require "httpx/plugins/cookies/set_cookie_parser"
|
19
19
|
end
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
OUT
|
26
|
-
end.new(options)
|
21
|
+
module OptionsMethods
|
22
|
+
def option_cookies(value)
|
23
|
+
value.is_a?(Jar) ? value : Jar.new(value)
|
24
|
+
end
|
27
25
|
end
|
28
26
|
|
29
27
|
module InstanceMethods
|
@@ -63,7 +61,7 @@ module HTTPX
|
|
63
61
|
|
64
62
|
def build_request(*, _)
|
65
63
|
request = super
|
66
|
-
request.headers.set_cookie(
|
64
|
+
request.headers.set_cookie(request.options.cookies[request.uri])
|
67
65
|
request
|
68
66
|
end
|
69
67
|
end
|
@@ -77,6 +75,21 @@ module HTTPX
|
|
77
75
|
add("cookie", header_value)
|
78
76
|
end
|
79
77
|
end
|
78
|
+
|
79
|
+
module OptionsMethods
|
80
|
+
def initialize(*)
|
81
|
+
super
|
82
|
+
|
83
|
+
return unless @headers.key?("cookie")
|
84
|
+
|
85
|
+
@headers.delete("cookie").each do |ck|
|
86
|
+
ck.split(/ *; */).each do |cookie|
|
87
|
+
name, value = cookie.split("=", 2)
|
88
|
+
@cookies.add(Cookie.new(name, value))
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
80
93
|
end
|
81
94
|
register_plugin :cookies, Cookies
|
82
95
|
end
|
@@ -43,8 +43,7 @@ module HTTPX
|
|
43
43
|
# Precedence: 1. longer path 2. older creation
|
44
44
|
(@name <=> other.name).nonzero? ||
|
45
45
|
(other.path.length <=> @path.length).nonzero? ||
|
46
|
-
(@created_at <=> other.created_at).nonzero? ||
|
47
|
-
@value <=> other.value
|
46
|
+
(@created_at <=> other.created_at).nonzero? || 0
|
48
47
|
end
|
49
48
|
|
50
49
|
class << self
|
@@ -108,6 +107,8 @@ module HTTPX
|
|
108
107
|
|
109
108
|
@path ||= "/"
|
110
109
|
raise ArgumentError, "name must be specified" if @name.nil?
|
110
|
+
|
111
|
+
@name = @name.to_s
|
111
112
|
end
|
112
113
|
|
113
114
|
def expires
|
@@ -123,7 +124,7 @@ module HTTPX
|
|
123
124
|
# Returns a string for use in the Cookie header, i.e. `name=value`
|
124
125
|
# or `name="value"`.
|
125
126
|
def cookie_value
|
126
|
-
"#{@name}=#{Scanner.quote(@value)}"
|
127
|
+
"#{@name}=#{Scanner.quote(@value.to_s)}"
|
127
128
|
end
|
128
129
|
alias_method :to_s, :cookie_value
|
129
130
|
|
@@ -43,6 +43,10 @@ module HTTPX
|
|
43
43
|
|
44
44
|
c.path = path if path && c.path == "/"
|
45
45
|
|
46
|
+
# If the user agent receives a new cookie with the same cookie-name, domain-value, and path-value
|
47
|
+
# as a cookie that it has already stored, the existing cookie is evicted and replaced with the new cookie.
|
48
|
+
@cookies.delete_if { |ck| ck.name == c.name && ck.domain == c.domain && ck.path == c.path }
|
49
|
+
|
46
50
|
@cookies << c
|
47
51
|
end
|
48
52
|
|
@@ -53,7 +57,7 @@ module HTTPX
|
|
53
57
|
def each(uri = nil, &blk)
|
54
58
|
return enum_for(__method__, uri) unless block_given?
|
55
59
|
|
56
|
-
return @
|
60
|
+
return @cookies.each(&blk) unless uri
|
57
61
|
|
58
62
|
uri = URI(uri)
|
59
63
|
|
@@ -69,6 +73,25 @@ module HTTPX
|
|
69
73
|
end
|
70
74
|
end
|
71
75
|
end
|
76
|
+
|
77
|
+
def merge(other)
|
78
|
+
cookies_dup = dup
|
79
|
+
|
80
|
+
other.each do |elem|
|
81
|
+
cookie = case elem
|
82
|
+
when Cookie
|
83
|
+
elem
|
84
|
+
when Array
|
85
|
+
Cookie.new(*elem)
|
86
|
+
else
|
87
|
+
Cookie.new(elem)
|
88
|
+
end
|
89
|
+
|
90
|
+
cookies_dup.add(cookie)
|
91
|
+
end
|
92
|
+
|
93
|
+
cookies_dup
|
94
|
+
end
|
72
95
|
end
|
73
96
|
end
|
74
97
|
end
|
@@ -14,19 +14,23 @@ module HTTPX
|
|
14
14
|
|
15
15
|
DigestError = Class.new(Error)
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
17
|
+
class << self
|
18
|
+
def extra_options(options)
|
19
|
+
options.merge(max_concurrent_requests: 1)
|
20
|
+
end
|
21
|
+
|
22
|
+
def load_dependencies(*)
|
23
|
+
require "securerandom"
|
24
|
+
require "digest"
|
25
|
+
end
|
25
26
|
end
|
26
27
|
|
27
|
-
|
28
|
-
|
29
|
-
|
28
|
+
module OptionsMethods
|
29
|
+
def option_digest(value)
|
30
|
+
raise TypeError, ":digest must be a Digest" unless value.is_a?(Digest)
|
31
|
+
|
32
|
+
value
|
33
|
+
end
|
30
34
|
end
|
31
35
|
|
32
36
|
module InstanceMethods
|
data/lib/httpx/plugins/expect.rb
CHANGED
@@ -10,26 +10,30 @@ module HTTPX
|
|
10
10
|
module Expect
|
11
11
|
EXPECT_TIMEOUT = 2
|
12
12
|
|
13
|
-
|
14
|
-
|
13
|
+
class << self
|
14
|
+
def no_expect_store
|
15
|
+
@no_expect_store ||= []
|
16
|
+
end
|
17
|
+
|
18
|
+
def extra_options(options)
|
19
|
+
options.merge(expect_timeout: EXPECT_TIMEOUT)
|
20
|
+
end
|
15
21
|
end
|
16
22
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
raise Error, ":expect_timeout must be positive" unless seconds.positive?
|
23
|
+
module OptionsMethods
|
24
|
+
def option_expect_timeout(value)
|
25
|
+
seconds = Integer(value)
|
26
|
+
raise TypeError, ":expect_timeout must be positive" unless seconds.positive?
|
22
27
|
|
23
|
-
|
24
|
-
|
28
|
+
seconds
|
29
|
+
end
|
25
30
|
|
26
|
-
|
27
|
-
|
28
|
-
|
31
|
+
def option_expect_threshold_size(value)
|
32
|
+
bytes = Integer(value)
|
33
|
+
raise TypeError, ":expect_threshold_size must be positive" unless bytes.positive?
|
29
34
|
|
30
|
-
|
31
|
-
|
32
|
-
end.new(options).merge(expect_timeout: EXPECT_TIMEOUT)
|
35
|
+
bytes
|
36
|
+
end
|
33
37
|
end
|
34
38
|
|
35
39
|
module RequestMethods
|
@@ -17,17 +17,17 @@ module HTTPX
|
|
17
17
|
MAX_REDIRECTS = 3
|
18
18
|
REDIRECT_STATUS = (300..399).freeze
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
raise Error, ":max_redirects must be positive" if num.negative?
|
20
|
+
module OptionsMethods
|
21
|
+
def option_max_redirects(value)
|
22
|
+
num = Integer(value)
|
23
|
+
raise TypeError, ":max_redirects must be positive" if num.negative?
|
25
24
|
|
26
|
-
|
27
|
-
|
25
|
+
num
|
26
|
+
end
|
28
27
|
|
29
|
-
|
30
|
-
|
28
|
+
def option_follow_insecure_redirects(value)
|
29
|
+
value
|
30
|
+
end
|
31
31
|
end
|
32
32
|
|
33
33
|
module InstanceMethods
|
data/lib/httpx/plugins/grpc.rb
CHANGED
@@ -49,7 +49,6 @@ module HTTPX
|
|
49
49
|
class << self
|
50
50
|
def load_dependencies(*)
|
51
51
|
require "stringio"
|
52
|
-
require "google/protobuf"
|
53
52
|
require "httpx/plugins/grpc/message"
|
54
53
|
require "httpx/plugins/grpc/call"
|
55
54
|
end
|
@@ -61,36 +60,7 @@ module HTTPX
|
|
61
60
|
end
|
62
61
|
|
63
62
|
def extra_options(options)
|
64
|
-
|
65
|
-
def_option(:grpc_service, <<-OUT)
|
66
|
-
String(value)
|
67
|
-
OUT
|
68
|
-
|
69
|
-
def_option(:grpc_compression, <<-OUT)
|
70
|
-
case value
|
71
|
-
when true, false
|
72
|
-
value
|
73
|
-
else
|
74
|
-
value.to_s
|
75
|
-
end
|
76
|
-
OUT
|
77
|
-
|
78
|
-
def_option(:grpc_rpcs, <<-OUT)
|
79
|
-
Hash[value]
|
80
|
-
OUT
|
81
|
-
|
82
|
-
def_option(:grpc_deadline, <<-OUT)
|
83
|
-
raise Error, ":grpc_deadline must be positive" unless value.positive?
|
84
|
-
|
85
|
-
value
|
86
|
-
OUT
|
87
|
-
|
88
|
-
def_option(:call_credentials, <<-OUT)
|
89
|
-
raise Error, ":call_credentials must respond to #call" unless value.respond_to?(:call)
|
90
|
-
|
91
|
-
value
|
92
|
-
OUT
|
93
|
-
end.new(options).merge(
|
63
|
+
options.merge(
|
94
64
|
fallback_protocol: "h2",
|
95
65
|
http2_settings: { wait_for_handshake: false },
|
96
66
|
grpc_rpcs: {}.freeze,
|
@@ -100,6 +70,37 @@ module HTTPX
|
|
100
70
|
end
|
101
71
|
end
|
102
72
|
|
73
|
+
module OptionsMethods
|
74
|
+
def option_grpc_service(value)
|
75
|
+
String(value)
|
76
|
+
end
|
77
|
+
|
78
|
+
def option_grpc_compression(value)
|
79
|
+
case value
|
80
|
+
when true, false
|
81
|
+
value
|
82
|
+
else
|
83
|
+
value.to_s
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def option_grpc_rpcs(value)
|
88
|
+
Hash[value]
|
89
|
+
end
|
90
|
+
|
91
|
+
def option_grpc_deadline(value)
|
92
|
+
raise TypeError, ":grpc_deadline must be positive" unless value.positive?
|
93
|
+
|
94
|
+
value
|
95
|
+
end
|
96
|
+
|
97
|
+
def option_call_credentials(value)
|
98
|
+
raise TypeError, ":call_credentials must respond to #call" unless value.respond_to?(:call)
|
99
|
+
|
100
|
+
value
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
103
104
|
module ResponseMethods
|
104
105
|
attr_reader :trailing_metadata
|
105
106
|
|
@@ -140,9 +141,19 @@ module HTTPX
|
|
140
141
|
deadline: @options.grpc_deadline,
|
141
142
|
}.merge(opts)
|
142
143
|
|
143
|
-
|
144
|
-
|
145
|
-
|
144
|
+
session_class = Class.new(self.class) do
|
145
|
+
class_eval(<<-OUT, __FILE__, __LINE__ + 1)
|
146
|
+
def #{rpc_name}(input, **opts)
|
147
|
+
rpc_execute("#{rpc_name}", input, **opts)
|
148
|
+
end
|
149
|
+
OUT
|
150
|
+
end
|
151
|
+
|
152
|
+
session_class.new(@options.merge(
|
153
|
+
grpc_rpcs: @options.grpc_rpcs.merge(
|
154
|
+
rpc_name.underscore => [rpc_name, input, output, rpc_opts]
|
155
|
+
).freeze
|
156
|
+
))
|
146
157
|
end
|
147
158
|
|
148
159
|
def build_stub(origin, service: nil, compression: false)
|
@@ -150,7 +161,32 @@ module HTTPX
|
|
150
161
|
|
151
162
|
origin = URI.parse("#{scheme}://#{origin}")
|
152
163
|
|
153
|
-
|
164
|
+
session = self
|
165
|
+
|
166
|
+
if service && service.respond_to?(:rpc_descs)
|
167
|
+
# it's a grpc generic service
|
168
|
+
service.rpc_descs.each do |rpc_name, rpc_desc|
|
169
|
+
rpc_opts = {
|
170
|
+
marshal_method: rpc_desc.marshal_method,
|
171
|
+
unmarshal_method: rpc_desc.unmarshal_method,
|
172
|
+
}
|
173
|
+
|
174
|
+
input = rpc_desc.input
|
175
|
+
input = input.type if input.respond_to?(:type)
|
176
|
+
|
177
|
+
output = rpc_desc.output
|
178
|
+
if output.respond_to?(:type)
|
179
|
+
rpc_opts[:stream] = true
|
180
|
+
output = output.type
|
181
|
+
end
|
182
|
+
|
183
|
+
session = session.rpc(rpc_name, input, output, **rpc_opts)
|
184
|
+
end
|
185
|
+
|
186
|
+
service = service.service_name
|
187
|
+
end
|
188
|
+
|
189
|
+
session.with(origin: origin, grpc_service: service, grpc_compression: compression)
|
154
190
|
end
|
155
191
|
|
156
192
|
def execute(rpc_method, input,
|
@@ -166,7 +202,7 @@ module HTTPX
|
|
166
202
|
private
|
167
203
|
|
168
204
|
def rpc_execute(rpc_name, input, **opts)
|
169
|
-
rpc_name, input_enc, output_enc, rpc_opts = @options.grpc_rpcs[rpc_name
|
205
|
+
rpc_name, input_enc, output_enc, rpc_opts = @options.grpc_rpcs[rpc_name]
|
170
206
|
|
171
207
|
exec_opts = rpc_opts.merge(opts)
|
172
208
|
|
@@ -180,7 +216,7 @@ module HTTPX
|
|
180
216
|
end
|
181
217
|
end
|
182
218
|
else
|
183
|
-
input_enc.
|
219
|
+
input_enc.__send__(marshal_method, input)
|
184
220
|
end
|
185
221
|
|
186
222
|
call = execute(rpc_name, messages, **exec_opts)
|
@@ -230,16 +266,6 @@ module HTTPX
|
|
230
266
|
|
231
267
|
build_request(:post, uri, headers: headers, body: body)
|
232
268
|
end
|
233
|
-
|
234
|
-
def respond_to_missing?(meth, *, &blk)
|
235
|
-
@options.grpc_rpcs.key?(meth.to_s) || super
|
236
|
-
end
|
237
|
-
|
238
|
-
def method_missing(meth, *args, **kwargs, &blk)
|
239
|
-
return rpc_execute(meth, *args, **kwargs, &blk) if @options.grpc_rpcs.key?(meth.to_s)
|
240
|
-
|
241
|
-
super
|
242
|
-
end
|
243
269
|
end
|
244
270
|
end
|
245
271
|
register_plugin :grpc, GRPC
|