httpx 0.15.4 → 0.18.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_16_0.md +93 -0
- data/doc/release_notes/0_16_1.md +5 -0
- data/doc/release_notes/0_17_0.md +49 -0
- data/doc/release_notes/0_18_0.md +69 -0
- data/lib/httpx/adapters/datadog.rb +1 -1
- data/lib/httpx/adapters/faraday.rb +8 -14
- data/lib/httpx/adapters/webmock.rb +9 -3
- data/lib/httpx/altsvc.rb +2 -2
- data/lib/httpx/buffer.rb +1 -1
- data/lib/httpx/callbacks.rb +1 -1
- data/lib/httpx/chainable.rb +18 -11
- data/lib/httpx/connection/http1.rb +21 -13
- data/lib/httpx/connection/http2.rb +20 -25
- data/lib/httpx/connection.rb +73 -77
- data/lib/httpx/domain_name.rb +1 -1
- data/lib/httpx/errors.rb +11 -11
- data/lib/httpx/extensions.rb +50 -4
- data/lib/httpx/headers.rb +1 -1
- data/lib/httpx/io/ssl.rb +3 -3
- data/lib/httpx/io/tls.rb +8 -8
- data/lib/httpx/loggable.rb +5 -5
- data/lib/httpx/options.rb +108 -81
- data/lib/httpx/parser/http1.rb +11 -7
- data/lib/httpx/plugins/aws_sdk_authentication.rb +42 -18
- data/lib/httpx/plugins/aws_sigv4.rb +19 -20
- data/lib/httpx/plugins/compression.rb +17 -14
- data/lib/httpx/plugins/cookies/cookie.rb +4 -2
- data/lib/httpx/plugins/cookies/jar.rb +21 -2
- data/lib/httpx/plugins/cookies.rb +20 -7
- data/lib/httpx/plugins/digest_authentication.rb +19 -15
- data/lib/httpx/plugins/expect.rb +26 -18
- data/lib/httpx/plugins/follow_redirects.rb +9 -9
- data/lib/httpx/plugins/grpc/call.rb +4 -1
- data/lib/httpx/plugins/grpc/message.rb +2 -2
- data/lib/httpx/plugins/grpc.rb +72 -46
- data/lib/httpx/plugins/h2c.rb +7 -3
- data/lib/httpx/plugins/internal_telemetry.rb +8 -8
- data/lib/httpx/plugins/multipart/decoder.rb +187 -0
- data/lib/httpx/plugins/multipart/mime_type_detector.rb +3 -3
- data/lib/httpx/plugins/multipart/part.rb +2 -2
- data/lib/httpx/plugins/multipart.rb +16 -2
- data/lib/httpx/plugins/ntlm_authentication.rb +12 -10
- 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 +20 -13
- data/lib/httpx/plugins/proxy.rb +10 -10
- data/lib/httpx/plugins/response_cache/store.rb +55 -0
- data/lib/httpx/plugins/response_cache.rb +88 -0
- data/lib/httpx/plugins/retries.rb +46 -23
- data/lib/httpx/plugins/stream.rb +3 -4
- data/lib/httpx/plugins/upgrade.rb +7 -6
- data/lib/httpx/pool.rb +39 -13
- data/lib/httpx/registry.rb +2 -2
- data/lib/httpx/request.rb +16 -25
- data/lib/httpx/resolver/https.rb +4 -8
- data/lib/httpx/resolver/native.rb +19 -5
- data/lib/httpx/resolver/resolver_mixin.rb +2 -1
- data/lib/httpx/resolver/system.rb +2 -0
- data/lib/httpx/resolver.rb +2 -2
- data/lib/httpx/response.rb +91 -48
- data/lib/httpx/selector.rb +11 -24
- data/lib/httpx/session.rb +41 -23
- data/lib/httpx/session2.rb +23 -0
- data/lib/httpx/timers.rb +84 -0
- data/lib/httpx/transcoder/body.rb +3 -2
- data/lib/httpx/transcoder/chunker.rb +2 -1
- data/lib/httpx/transcoder/form.rb +20 -0
- data/lib/httpx/transcoder/json.rb +12 -0
- data/lib/httpx/transcoder.rb +62 -1
- data/lib/httpx/utils.rb +10 -2
- data/lib/httpx/version.rb +1 -1
- data/lib/httpx.rb +7 -3
- data/sig/buffer.rbs +3 -1
- data/sig/chainable.rbs +31 -29
- data/sig/connection/http1.rbs +11 -5
- data/sig/connection/http2.rbs +16 -5
- data/sig/connection.rbs +31 -13
- data/sig/errors.rbs +35 -1
- data/sig/headers.rbs +20 -19
- data/sig/httpx.rbs +4 -1
- data/sig/loggable.rbs +3 -1
- data/sig/options.rbs +45 -34
- data/sig/parser/http1.rbs +3 -3
- data/sig/plugins/authentication.rbs +1 -1
- data/sig/plugins/aws_sdk_authentication.rbs +25 -3
- data/sig/plugins/aws_sigv4.rbs +13 -5
- data/sig/plugins/basic_authentication.rbs +1 -1
- data/sig/plugins/compression.rbs +4 -6
- data/sig/plugins/cookies/cookie.rbs +5 -7
- data/sig/plugins/cookies/jar.rbs +9 -10
- data/sig/plugins/cookies.rbs +4 -5
- 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 +64 -10
- data/sig/plugins/ntlm_authentication.rbs +2 -3
- data/sig/plugins/persistent.rbs +3 -8
- data/sig/plugins/proxy/ssh.rbs +4 -4
- data/sig/plugins/proxy.rbs +13 -13
- data/sig/plugins/push_promise.rbs +0 -2
- data/sig/plugins/response_cache.rbs +35 -0
- data/sig/plugins/retries.rbs +7 -8
- data/sig/plugins/stream.rbs +1 -1
- data/sig/plugins/upgrade.rbs +2 -3
- data/sig/pool.rbs +7 -2
- data/sig/registry.rbs +1 -1
- data/sig/request.rbs +11 -8
- data/sig/resolver/native.rbs +10 -5
- data/sig/resolver/resolver_mixin.rbs +4 -5
- data/sig/resolver/system.rbs +4 -0
- data/sig/resolver.rbs +7 -0
- data/sig/response.rbs +26 -13
- data/sig/selector.rbs +11 -9
- data/sig/session.rbs +22 -23
- data/sig/timers.rbs +32 -0
- data/sig/transcoder/body.rbs +6 -1
- data/sig/transcoder/chunker.rbs +8 -2
- data/sig/transcoder/form.rbs +3 -1
- data/sig/transcoder/json.rbs +2 -0
- data/sig/transcoder.rbs +13 -5
- data/sig/utils.rbs +6 -0
- metadata +18 -18
- data/lib/httpx/request2.rb +0 -14
data/lib/httpx/options.rb
CHANGED
|
@@ -30,6 +30,7 @@ module HTTPX
|
|
|
30
30
|
:request_body_class => Class.new(Request::Body),
|
|
31
31
|
:response_body_class => Class.new(Response::Body),
|
|
32
32
|
:connection_class => Class.new(Connection),
|
|
33
|
+
:options_class => Class.new(self),
|
|
33
34
|
:transport => nil,
|
|
34
35
|
:transport_options => nil,
|
|
35
36
|
:addresses => nil,
|
|
@@ -38,71 +39,100 @@ module HTTPX
|
|
|
38
39
|
:resolver_options => { cache: true },
|
|
39
40
|
}.freeze
|
|
40
41
|
|
|
42
|
+
begin
|
|
43
|
+
module HashExtensions
|
|
44
|
+
refine Hash do
|
|
45
|
+
def >=(other)
|
|
46
|
+
Hash[other] <= self
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def <=(other)
|
|
50
|
+
other = Hash[other]
|
|
51
|
+
return false unless size <= other.size
|
|
52
|
+
|
|
53
|
+
each do |k, v|
|
|
54
|
+
v2 = other.fetch(k) { return false }
|
|
55
|
+
return false unless v2 == v
|
|
56
|
+
end
|
|
57
|
+
true
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
using HashExtensions
|
|
62
|
+
end unless Hash.method_defined?(:>=)
|
|
63
|
+
|
|
41
64
|
class << self
|
|
42
65
|
def new(options = {})
|
|
43
66
|
# let enhanced options go through
|
|
44
|
-
return options if self == Options && options.class
|
|
67
|
+
return options if self == Options && options.class < self
|
|
45
68
|
return options if options.is_a?(self)
|
|
46
69
|
|
|
47
70
|
super
|
|
48
71
|
end
|
|
49
72
|
|
|
50
|
-
def
|
|
51
|
-
|
|
73
|
+
def method_added(meth)
|
|
74
|
+
super
|
|
52
75
|
|
|
53
|
-
|
|
54
|
-
class_eval(<<-OUT, __FILE__, __LINE__ + 1)
|
|
55
|
-
def #{name}=(value)
|
|
56
|
-
return if value.nil?
|
|
76
|
+
return unless meth =~ /^option_(.+)$/
|
|
57
77
|
|
|
58
|
-
|
|
59
|
-
#{layout}
|
|
60
|
-
end
|
|
78
|
+
optname = Regexp.last_match(1).to_sym
|
|
61
79
|
|
|
62
|
-
|
|
63
|
-
|
|
80
|
+
attr_reader(optname)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def def_option(optname, *args, &block)
|
|
84
|
+
if args.size.zero? && !block
|
|
85
|
+
class_eval(<<-OUT, __FILE__, __LINE__ + 1)
|
|
86
|
+
def option_#{optname}(v); v; end # def option_smth(v); v; end
|
|
64
87
|
OUT
|
|
88
|
+
return
|
|
89
|
+
end
|
|
65
90
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
91
|
+
deprecated_def_option(optname, *args, &block)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def deprecated_def_option(optname, layout = nil, &interpreter)
|
|
95
|
+
warn "DEPRECATION WARNING: using `def_option(#{optname})` for setting options is deprecated. " \
|
|
96
|
+
"Define module OptionsMethods and `def option_#{optname}(val)` instead."
|
|
69
97
|
|
|
70
|
-
|
|
98
|
+
if layout
|
|
99
|
+
class_eval(<<-OUT, __FILE__, __LINE__ + 1)
|
|
100
|
+
def option_#{optname}(value) # def option_origin(v)
|
|
101
|
+
#{layout} # URI(v)
|
|
102
|
+
end # end
|
|
103
|
+
OUT
|
|
104
|
+
elsif interpreter
|
|
105
|
+
define_method(:"option_#{optname}") do |value|
|
|
106
|
+
instance_exec(value, &interpreter)
|
|
71
107
|
end
|
|
72
|
-
else
|
|
73
|
-
attr_writer name
|
|
74
108
|
end
|
|
75
|
-
|
|
76
|
-
protected :"#{name}="
|
|
77
109
|
end
|
|
78
110
|
end
|
|
79
111
|
|
|
80
112
|
def initialize(options = {})
|
|
81
113
|
defaults = DEFAULT_OPTIONS.merge(options)
|
|
82
|
-
defaults.each do |
|
|
114
|
+
defaults.each do |k, v|
|
|
83
115
|
next if v.nil?
|
|
84
116
|
|
|
85
117
|
begin
|
|
86
|
-
__send__(:"#{k}
|
|
118
|
+
value = __send__(:"option_#{k}", v)
|
|
119
|
+
instance_variable_set(:"@#{k}", value)
|
|
87
120
|
rescue NoMethodError
|
|
88
121
|
raise Error, "unknown option: #{k}"
|
|
89
122
|
end
|
|
90
123
|
end
|
|
124
|
+
freeze
|
|
91
125
|
end
|
|
92
126
|
|
|
93
|
-
|
|
127
|
+
def option_origin(value)
|
|
94
128
|
URI(value)
|
|
95
|
-
|
|
129
|
+
end
|
|
96
130
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
else
|
|
101
|
-
Headers.new(value)
|
|
102
|
-
end
|
|
103
|
-
OUT
|
|
131
|
+
def option_headers(value)
|
|
132
|
+
Headers.new(value)
|
|
133
|
+
end
|
|
104
134
|
|
|
105
|
-
|
|
135
|
+
def option_timeout(value)
|
|
106
136
|
timeouts = Hash[value]
|
|
107
137
|
|
|
108
138
|
if timeouts.key?(:loop_timeout)
|
|
@@ -111,42 +141,43 @@ module HTTPX
|
|
|
111
141
|
end
|
|
112
142
|
|
|
113
143
|
timeouts
|
|
114
|
-
|
|
144
|
+
end
|
|
115
145
|
|
|
116
|
-
|
|
117
|
-
raise
|
|
146
|
+
def option_max_concurrent_requests(value)
|
|
147
|
+
raise TypeError, ":max_concurrent_requests must be positive" unless value.positive?
|
|
118
148
|
|
|
119
149
|
value
|
|
120
|
-
|
|
150
|
+
end
|
|
121
151
|
|
|
122
|
-
|
|
123
|
-
raise
|
|
152
|
+
def option_max_requests(value)
|
|
153
|
+
raise TypeError, ":max_requests must be positive" unless value.positive?
|
|
124
154
|
|
|
125
155
|
value
|
|
126
|
-
|
|
156
|
+
end
|
|
127
157
|
|
|
128
|
-
|
|
158
|
+
def option_window_size(value)
|
|
129
159
|
Integer(value)
|
|
130
|
-
|
|
160
|
+
end
|
|
131
161
|
|
|
132
|
-
|
|
162
|
+
def option_body_threshold_size(value)
|
|
133
163
|
Integer(value)
|
|
134
|
-
|
|
164
|
+
end
|
|
135
165
|
|
|
136
|
-
|
|
166
|
+
def option_transport(value)
|
|
137
167
|
transport = value.to_s
|
|
138
|
-
raise
|
|
168
|
+
raise TypeError, "\#{transport} is an unsupported transport type" unless IO.registry.key?(transport)
|
|
139
169
|
|
|
140
170
|
transport
|
|
141
|
-
|
|
171
|
+
end
|
|
142
172
|
|
|
143
|
-
|
|
173
|
+
def option_addresses(value)
|
|
144
174
|
Array(value)
|
|
145
|
-
|
|
175
|
+
end
|
|
146
176
|
|
|
147
177
|
%i[
|
|
148
178
|
params form json body ssl http2_settings
|
|
149
|
-
request_class response_class headers_class request_body_class
|
|
179
|
+
request_class response_class headers_class request_body_class
|
|
180
|
+
response_body_class connection_class options_class
|
|
150
181
|
io fallback_protocol debug debug_level transport_options resolver_class resolver_options
|
|
151
182
|
persistent
|
|
152
183
|
].each do |method_name|
|
|
@@ -154,6 +185,7 @@ module HTTPX
|
|
|
154
185
|
end
|
|
155
186
|
|
|
156
187
|
REQUEST_IVARS = %i[@params @form @json @body].freeze
|
|
188
|
+
private_constant :REQUEST_IVARS
|
|
157
189
|
|
|
158
190
|
def ==(other)
|
|
159
191
|
ivars = instance_variables | other.instance_variables
|
|
@@ -171,18 +203,17 @@ module HTTPX
|
|
|
171
203
|
end
|
|
172
204
|
|
|
173
205
|
def merge(other)
|
|
174
|
-
raise ArgumentError, "#{other
|
|
206
|
+
raise ArgumentError, "#{other} is not a valid set of options" unless other.respond_to?(:to_hash)
|
|
175
207
|
|
|
176
208
|
h2 = other.to_hash
|
|
177
209
|
return self if h2.empty?
|
|
178
210
|
|
|
179
211
|
h1 = to_hash
|
|
180
212
|
|
|
181
|
-
return self if h1
|
|
213
|
+
return self if h1 >= h2
|
|
182
214
|
|
|
183
|
-
merged = h1.merge(h2) do |
|
|
184
|
-
|
|
185
|
-
when :headers, :ssl, :http2_settings, :timeout
|
|
215
|
+
merged = h1.merge(h2) do |_k, v1, v2|
|
|
216
|
+
if v1.respond_to?(:merge) && v2.respond_to?(:merge)
|
|
186
217
|
v1.merge(v2)
|
|
187
218
|
else
|
|
188
219
|
v2
|
|
@@ -193,34 +224,30 @@ module HTTPX
|
|
|
193
224
|
end
|
|
194
225
|
|
|
195
226
|
def to_hash
|
|
196
|
-
|
|
197
|
-
[ivar[1..-1].to_sym
|
|
227
|
+
instance_variables.each_with_object({}) do |ivar, hs|
|
|
228
|
+
hs[ivar[1..-1].to_sym] = instance_variable_get(ivar)
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
if RUBY_VERSION > "2.4.0"
|
|
233
|
+
def initialize_dup(other)
|
|
234
|
+
instance_variables.each do |ivar|
|
|
235
|
+
instance_variable_set(ivar, other.instance_variable_get(ivar).dup)
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
else
|
|
239
|
+
def initialize_dup(other)
|
|
240
|
+
instance_variables.each do |ivar|
|
|
241
|
+
value = other.instance_variable_get(ivar)
|
|
242
|
+
value = case value
|
|
243
|
+
when Symbol, Fixnum, TrueClass, FalseClass # rubocop:disable Lint/UnifiedInteger
|
|
244
|
+
value
|
|
245
|
+
else
|
|
246
|
+
value.dup
|
|
247
|
+
end
|
|
248
|
+
instance_variable_set(ivar, value)
|
|
249
|
+
end
|
|
198
250
|
end
|
|
199
|
-
Hash[hash_pairs]
|
|
200
|
-
end
|
|
201
|
-
|
|
202
|
-
def initialize_dup(other)
|
|
203
|
-
self.headers = other.headers.dup
|
|
204
|
-
self.ssl = other.ssl.dup
|
|
205
|
-
self.request_class = other.request_class.dup
|
|
206
|
-
self.response_class = other.response_class.dup
|
|
207
|
-
self.headers_class = other.headers_class.dup
|
|
208
|
-
self.request_body_class = other.request_body_class.dup
|
|
209
|
-
self.response_body_class = other.response_body_class.dup
|
|
210
|
-
self.connection_class = other.connection_class.dup
|
|
211
|
-
end
|
|
212
|
-
|
|
213
|
-
def freeze
|
|
214
|
-
super
|
|
215
|
-
|
|
216
|
-
headers.freeze
|
|
217
|
-
ssl.freeze
|
|
218
|
-
request_class.freeze
|
|
219
|
-
response_class.freeze
|
|
220
|
-
headers_class.freeze
|
|
221
|
-
request_body_class.freeze
|
|
222
|
-
response_body_class.freeze
|
|
223
|
-
connection_class.freeze
|
|
224
251
|
end
|
|
225
252
|
end
|
|
226
253
|
end
|
data/lib/httpx/parser/http1.rb
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
module HTTPX
|
|
4
4
|
module Parser
|
|
5
|
-
Error
|
|
5
|
+
class Error < Error; end
|
|
6
6
|
|
|
7
7
|
class HTTP1
|
|
8
8
|
VERSIONS = %w[1.0 1.1].freeze
|
|
@@ -60,7 +60,7 @@ module HTTPX
|
|
|
60
60
|
(m = %r{\AHTTP(?:/(\d+\.\d+))?\s+(\d\d\d)(?:\s+(.*))?}in.match(@buffer)) ||
|
|
61
61
|
raise(Error, "wrong head line format")
|
|
62
62
|
version, code, _ = m.captures
|
|
63
|
-
raise(Error, "unsupported HTTP version (HTTP/#{version})") unless VERSIONS.include?(version)
|
|
63
|
+
raise(Error, "unsupported HTTP version (HTTP/#{version})") unless version && VERSIONS.include?(version)
|
|
64
64
|
|
|
65
65
|
@http_version = version.split(".").map(&:to_i)
|
|
66
66
|
@status_code = code.to_i
|
|
@@ -72,9 +72,14 @@ module HTTPX
|
|
|
72
72
|
|
|
73
73
|
def parse_headers
|
|
74
74
|
headers = @headers
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
75
|
+
buffer = @buffer
|
|
76
|
+
|
|
77
|
+
while (idx = buffer.index("\n"))
|
|
78
|
+
line = buffer.byteslice(0..idx)
|
|
79
|
+
raise Error, "wrong header format" if line.start_with?("\s", "\t")
|
|
80
|
+
|
|
81
|
+
line.lstrip!
|
|
82
|
+
buffer = @buffer = buffer.byteslice((idx + 1)..-1)
|
|
78
83
|
if line.empty?
|
|
79
84
|
case @state
|
|
80
85
|
when :headers
|
|
@@ -97,9 +102,8 @@ module HTTPX
|
|
|
97
102
|
raise Error, "wrong header format" unless separator_index
|
|
98
103
|
|
|
99
104
|
key = line.byteslice(0..(separator_index - 1))
|
|
100
|
-
raise Error, "wrong header format" if key.start_with?("\s", "\t")
|
|
101
105
|
|
|
102
|
-
key.
|
|
106
|
+
key.rstrip! # was lstripped previously!
|
|
103
107
|
value = line.byteslice((separator_index + 1)..-1)
|
|
104
108
|
value.strip!
|
|
105
109
|
raise Error, "wrong header format" if value.nil?
|
|
@@ -8,6 +8,23 @@ module HTTPX
|
|
|
8
8
|
# It requires the "aws-sdk-core" gem.
|
|
9
9
|
#
|
|
10
10
|
module AwsSdkAuthentication
|
|
11
|
+
# Mock configuration, to be used only when resolving credentials
|
|
12
|
+
class Configuration
|
|
13
|
+
attr_reader :profile
|
|
14
|
+
|
|
15
|
+
def initialize(profile)
|
|
16
|
+
@profile = profile
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def respond_to_missing?(*)
|
|
20
|
+
true
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def method_missing(*)
|
|
24
|
+
nil
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
11
28
|
#
|
|
12
29
|
# encapsulates access to an AWS SDK credentials store.
|
|
13
30
|
#
|
|
@@ -30,23 +47,8 @@ module HTTPX
|
|
|
30
47
|
end
|
|
31
48
|
|
|
32
49
|
class << self
|
|
33
|
-
attr_reader :credentials, :region
|
|
34
|
-
|
|
35
50
|
def load_dependencies(_klass)
|
|
36
51
|
require "aws-sdk-core"
|
|
37
|
-
|
|
38
|
-
client = Class.new(Seahorse::Client::Base) do
|
|
39
|
-
@identifier = :httpx
|
|
40
|
-
set_api(Aws::S3::ClientApi::API)
|
|
41
|
-
add_plugin(Aws::Plugins::CredentialsConfiguration)
|
|
42
|
-
add_plugin(Aws::Plugins::RegionalEndpoint)
|
|
43
|
-
class << self
|
|
44
|
-
attr_reader :identifier
|
|
45
|
-
end
|
|
46
|
-
end.new
|
|
47
|
-
|
|
48
|
-
@credentials = Credentials.new(client.config[:credentials])
|
|
49
|
-
@region = client.config[:region]
|
|
50
52
|
end
|
|
51
53
|
|
|
52
54
|
def configure(klass)
|
|
@@ -56,6 +58,26 @@ module HTTPX
|
|
|
56
58
|
def extra_options(options)
|
|
57
59
|
options.merge(max_concurrent_requests: 1)
|
|
58
60
|
end
|
|
61
|
+
|
|
62
|
+
def credentials(profile)
|
|
63
|
+
mock_configuration = Configuration.new(profile)
|
|
64
|
+
Credentials.new(Aws::CredentialProviderChain.new(mock_configuration).resolve)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def region(profile)
|
|
68
|
+
# https://github.com/aws/aws-sdk-ruby/blob/version-3/gems/aws-sdk-core/lib/aws-sdk-core/plugins/regional_endpoint.rb#L62
|
|
69
|
+
keys = %w[AWS_REGION AMAZON_REGION AWS_DEFAULT_REGION]
|
|
70
|
+
env_region = ENV.values_at(*keys).compact.first
|
|
71
|
+
env_region = nil if env_region == ""
|
|
72
|
+
cfg_region = Aws.shared_config.region(profile: profile)
|
|
73
|
+
env_region || cfg_region
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
module OptionsMethods
|
|
78
|
+
def option_aws_profile(value)
|
|
79
|
+
String(value)
|
|
80
|
+
end
|
|
59
81
|
end
|
|
60
82
|
|
|
61
83
|
module InstanceMethods
|
|
@@ -64,9 +86,11 @@ module HTTPX
|
|
|
64
86
|
# aws_authentication(credentials: Aws::Credentials.new('akid', 'secret'))
|
|
65
87
|
# aws_authentication()
|
|
66
88
|
#
|
|
67
|
-
def aws_sdk_authentication(
|
|
68
|
-
credentials
|
|
69
|
-
region
|
|
89
|
+
def aws_sdk_authentication(
|
|
90
|
+
credentials: AwsSdkAuthentication.credentials(@options.aws_profile),
|
|
91
|
+
region: AwsSdkAuthentication.region(@options.aws_profile),
|
|
92
|
+
**options
|
|
93
|
+
)
|
|
70
94
|
|
|
71
95
|
aws_sigv4_authentication(
|
|
72
96
|
credentials: credentials,
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "set"
|
|
4
|
-
require "aws-sdk-s3"
|
|
5
|
-
|
|
6
3
|
module HTTPX
|
|
7
4
|
module Plugins
|
|
8
5
|
#
|
|
@@ -75,16 +72,16 @@ module HTTPX
|
|
|
75
72
|
|
|
76
73
|
# canonical request
|
|
77
74
|
creq = "#{request.verb.to_s.upcase}" \
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
75
|
+
"\n#{request.canonical_path}" \
|
|
76
|
+
"\n#{request.canonical_query}" \
|
|
77
|
+
"\n#{canonical_headers}" \
|
|
78
|
+
"\n#{signed_headers}" \
|
|
79
|
+
"\n#{content_hashed}"
|
|
83
80
|
|
|
84
81
|
credential_scope = "#{date}" \
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
82
|
+
"/#{@region}" \
|
|
83
|
+
"/#{@service}" \
|
|
84
|
+
"/#{lower_provider_prefix}_request"
|
|
88
85
|
|
|
89
86
|
algo_line = "#{upper_provider_prefix}-HMAC-#{@algorithm}"
|
|
90
87
|
# string to sign
|
|
@@ -141,22 +138,24 @@ module HTTPX
|
|
|
141
138
|
end
|
|
142
139
|
|
|
143
140
|
class << self
|
|
144
|
-
def
|
|
145
|
-
|
|
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)
|
|
141
|
+
def load_dependencies(*)
|
|
142
|
+
require "set"
|
|
153
143
|
require "digest/sha2"
|
|
154
144
|
require "openssl"
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def configure(klass)
|
|
155
148
|
klass.plugin(:expect)
|
|
156
149
|
klass.plugin(:compression)
|
|
157
150
|
end
|
|
158
151
|
end
|
|
159
152
|
|
|
153
|
+
module OptionsMethods
|
|
154
|
+
def option_sigv4_signer(value)
|
|
155
|
+
value.is_a?(Signer) ? value : Signer.new(value)
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
160
159
|
module InstanceMethods
|
|
161
160
|
def aws_sigv4_authentication(**options)
|
|
162
161
|
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
|
|
|
@@ -71,6 +72,8 @@ module HTTPX
|
|
|
71
72
|
end
|
|
72
73
|
|
|
73
74
|
module ResponseBodyMethods
|
|
75
|
+
using ArrayExtensions
|
|
76
|
+
|
|
74
77
|
attr_reader :encodings
|
|
75
78
|
|
|
76
79
|
def initialize(*)
|
|
@@ -89,7 +92,7 @@ module HTTPX
|
|
|
89
92
|
Float::INFINITY
|
|
90
93
|
end
|
|
91
94
|
|
|
92
|
-
@_inflaters = @headers.get("content-encoding").
|
|
95
|
+
@_inflaters = @headers.get("content-encoding").filter_map do |encoding|
|
|
93
96
|
next if encoding == "identity"
|
|
94
97
|
|
|
95
98
|
inflater = @options.encodings.registry(encoding).inflater(compressed_length)
|
|
@@ -99,7 +102,7 @@ module HTTPX
|
|
|
99
102
|
|
|
100
103
|
@encodings << encoding
|
|
101
104
|
inflater
|
|
102
|
-
end
|
|
105
|
+
end
|
|
103
106
|
|
|
104
107
|
# this can happen if the only declared encoding is "identity"
|
|
105
108
|
remove_instance_variable(:@_inflaters) if @_inflaters.empty?
|
|
@@ -133,7 +136,7 @@ module HTTPX
|
|
|
133
136
|
end
|
|
134
137
|
|
|
135
138
|
def each(&blk)
|
|
136
|
-
return enum_for(__method__) unless
|
|
139
|
+
return enum_for(__method__) unless blk
|
|
137
140
|
|
|
138
141
|
return deflate(&blk) if @buffer.size.zero?
|
|
139
142
|
|
|
@@ -43,7 +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?
|
|
46
|
+
(@created_at <=> other.created_at).nonzero? || 0
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
class << self
|
|
@@ -107,6 +107,8 @@ module HTTPX
|
|
|
107
107
|
|
|
108
108
|
@path ||= "/"
|
|
109
109
|
raise ArgumentError, "name must be specified" if @name.nil?
|
|
110
|
+
|
|
111
|
+
@name = @name.to_s
|
|
110
112
|
end
|
|
111
113
|
|
|
112
114
|
def expires
|
|
@@ -122,7 +124,7 @@ module HTTPX
|
|
|
122
124
|
# Returns a string for use in the Cookie header, i.e. `name=value`
|
|
123
125
|
# or `name="value"`.
|
|
124
126
|
def cookie_value
|
|
125
|
-
"#{@name}=#{Scanner.quote(@value)}"
|
|
127
|
+
"#{@name}=#{Scanner.quote(@value.to_s)}"
|
|
126
128
|
end
|
|
127
129
|
alias_method :to_s, :cookie_value
|
|
128
130
|
|
|
@@ -55,9 +55,9 @@ module HTTPX
|
|
|
55
55
|
end
|
|
56
56
|
|
|
57
57
|
def each(uri = nil, &blk)
|
|
58
|
-
return enum_for(__method__, uri) unless
|
|
58
|
+
return enum_for(__method__, uri) unless blk
|
|
59
59
|
|
|
60
|
-
return @
|
|
60
|
+
return @cookies.each(&blk) unless uri
|
|
61
61
|
|
|
62
62
|
uri = URI(uri)
|
|
63
63
|
|
|
@@ -73,6 +73,25 @@ module HTTPX
|
|
|
73
73
|
end
|
|
74
74
|
end
|
|
75
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
|
|
76
95
|
end
|
|
77
96
|
end
|
|
78
97
|
end
|
|
@@ -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
|