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
@@ -10,6 +10,7 @@ module HTTPX
|
|
10
10
|
def initialize(response)
|
11
11
|
@response = response
|
12
12
|
@decoder = ->(z) { z }
|
13
|
+
@consumed = false
|
13
14
|
end
|
14
15
|
|
15
16
|
def inspect
|
@@ -25,7 +26,7 @@ module HTTPX
|
|
25
26
|
end
|
26
27
|
|
27
28
|
def trailing_metadata
|
28
|
-
return unless @
|
29
|
+
return unless @consumed
|
29
30
|
|
30
31
|
@response.trailing_metadata
|
31
32
|
end
|
@@ -40,8 +41,10 @@ module HTTPX
|
|
40
41
|
Message.stream(@response).each do |message|
|
41
42
|
y << @decoder.call(message)
|
42
43
|
end
|
44
|
+
@consumed = true
|
43
45
|
end
|
44
46
|
else
|
47
|
+
@consumed = true
|
45
48
|
@decoder.call(Message.unary(@response))
|
46
49
|
end
|
47
50
|
end
|
@@ -15,13 +15,15 @@ module HTTPX
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def extra_options(options)
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
options.merge(max_concurrent_requests: 1)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
module OptionsMethods
|
23
|
+
def option_ntlm(value)
|
24
|
+
raise TypeError, ":ntlm must be a #{NTLMParams}" unless value.is_a?(NTLMParams)
|
21
25
|
|
22
|
-
|
23
|
-
OUT
|
24
|
-
end.new(options).merge(max_concurrent_requests: 1)
|
26
|
+
value
|
25
27
|
end
|
26
28
|
end
|
27
29
|
|
data/lib/httpx/plugins/proxy.rb
CHANGED
@@ -64,13 +64,11 @@ module HTTPX
|
|
64
64
|
klass.plugin(:"proxy/socks4")
|
65
65
|
klass.plugin(:"proxy/socks5")
|
66
66
|
end
|
67
|
+
end
|
67
68
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
value.is_a?(#{Parameters}) ? value : Hash[value]
|
72
|
-
OUT
|
73
|
-
end.new(options)
|
69
|
+
module OptionsMethods
|
70
|
+
def option_proxy(value)
|
71
|
+
value.is_a?(Parameters) ? value : Hash[value]
|
74
72
|
end
|
75
73
|
end
|
76
74
|
|
@@ -6,16 +6,16 @@ module HTTPX
|
|
6
6
|
module Plugins
|
7
7
|
module Proxy
|
8
8
|
module SSH
|
9
|
-
|
10
|
-
|
9
|
+
class << self
|
10
|
+
def load_dependencies(*)
|
11
|
+
require "net/ssh/gateway"
|
12
|
+
end
|
11
13
|
end
|
12
14
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
OUT
|
18
|
-
end.new(options)
|
15
|
+
module OptionsMethods
|
16
|
+
def option_proxy(value)
|
17
|
+
Hash[value]
|
18
|
+
end
|
19
19
|
end
|
20
20
|
|
21
21
|
module InstanceMethods
|
@@ -65,7 +65,7 @@ module HTTPX
|
|
65
65
|
when "http"
|
66
66
|
TCPSocket.open("localhost", port)
|
67
67
|
else
|
68
|
-
raise
|
68
|
+
raise TypeError, "unexpected scheme: #{request_uri.scheme}"
|
69
69
|
end
|
70
70
|
end
|
71
71
|
end
|
@@ -17,39 +17,43 @@ module HTTPX
|
|
17
17
|
Errno::ECONNRESET,
|
18
18
|
Errno::ECONNABORTED,
|
19
19
|
Errno::EPIPE,
|
20
|
-
|
20
|
+
TLSError,
|
21
21
|
TimeoutError,
|
22
22
|
Parser::Error,
|
23
23
|
Errno::EINVAL,
|
24
24
|
Errno::ETIMEDOUT].freeze
|
25
25
|
|
26
26
|
def self.extra_options(options)
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
27
|
+
options.merge(max_retries: MAX_RETRIES)
|
28
|
+
end
|
29
|
+
|
30
|
+
module OptionsMethods
|
31
|
+
def option_retry_after(value)
|
32
|
+
# return early if callable
|
33
|
+
unless value.respond_to?(:call)
|
34
|
+
value = Integer(value)
|
35
|
+
raise TypeError, ":retry_after must be positive" unless value.positive?
|
36
|
+
end
|
34
37
|
|
35
|
-
|
36
|
-
|
38
|
+
value
|
39
|
+
end
|
37
40
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
+
def option_max_retries(value)
|
42
|
+
num = Integer(value)
|
43
|
+
raise TypeError, ":max_retries must be positive" unless num.positive?
|
41
44
|
|
42
|
-
|
43
|
-
|
45
|
+
num
|
46
|
+
end
|
44
47
|
|
45
|
-
|
48
|
+
def option_retry_change_requests(v)
|
49
|
+
v
|
50
|
+
end
|
46
51
|
|
47
|
-
|
48
|
-
|
52
|
+
def option_retry_on(value)
|
53
|
+
raise ":retry_on must be called with the response" unless value.respond_to?(:call)
|
49
54
|
|
50
|
-
|
51
|
-
|
52
|
-
end.new(options).merge(max_retries: MAX_RETRIES)
|
55
|
+
value
|
56
|
+
end
|
53
57
|
end
|
54
58
|
|
55
59
|
module InstanceMethods
|
@@ -18,14 +18,15 @@ module HTTPX
|
|
18
18
|
upgrade_handlers = Module.new do
|
19
19
|
extend Registry
|
20
20
|
end
|
21
|
+
options.merge(upgrade_handlers: upgrade_handlers)
|
22
|
+
end
|
23
|
+
end
|
21
24
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
+
module OptionsMethods
|
26
|
+
def option_upgrade_handlers(value)
|
27
|
+
raise TypeError, ":upgrade_handlers must be a registry" unless value.respond_to?(:registry)
|
25
28
|
|
26
|
-
|
27
|
-
OUT
|
28
|
-
end.new(options).merge(upgrade_handlers: upgrade_handlers)
|
29
|
+
value
|
29
30
|
end
|
30
31
|
end
|
31
32
|
|
data/lib/httpx/registry.rb
CHANGED
data/lib/httpx/request.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "delegate"
|
3
4
|
require "forwardable"
|
4
5
|
|
5
6
|
module HTTPX
|
@@ -155,7 +156,7 @@ module HTTPX
|
|
155
156
|
end
|
156
157
|
# :nocov:
|
157
158
|
|
158
|
-
class Body
|
159
|
+
class Body < SimpleDelegator
|
159
160
|
class << self
|
160
161
|
def new(*, options)
|
161
162
|
return options.body if options.body.is_a?(self)
|
@@ -177,6 +178,7 @@ module HTTPX
|
|
177
178
|
|
178
179
|
@headers["content-type"] ||= @body.content_type
|
179
180
|
@headers["content-length"] = @body.bytesize unless unbounded_body?
|
181
|
+
super(@body)
|
180
182
|
end
|
181
183
|
|
182
184
|
def each(&block)
|
@@ -214,7 +216,7 @@ module HTTPX
|
|
214
216
|
|
215
217
|
def stream(body)
|
216
218
|
encoded = body
|
217
|
-
encoded = Transcoder.registry("chunker").encode(body) if chunked?
|
219
|
+
encoded = Transcoder.registry("chunker").encode(body.enum_for(:each)) if chunked?
|
218
220
|
encoded
|
219
221
|
end
|
220
222
|
|
@@ -238,16 +240,6 @@ module HTTPX
|
|
238
240
|
"#{unbounded_body? ? "stream" : "@bytesize=#{bytesize}"}>"
|
239
241
|
end
|
240
242
|
# :nocov:
|
241
|
-
|
242
|
-
def respond_to_missing?(meth, *args)
|
243
|
-
@body.respond_to?(meth, *args) || super
|
244
|
-
end
|
245
|
-
|
246
|
-
def method_missing(meth, *args, &block)
|
247
|
-
return super unless @body.respond_to?(meth)
|
248
|
-
|
249
|
-
@body.__send__(meth, *args, &block)
|
250
|
-
end
|
251
243
|
end
|
252
244
|
|
253
245
|
def transition(nextstate)
|
data/lib/httpx/resolver/https.rb
CHANGED
data/lib/httpx/response.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "objspace"
|
3
4
|
require "stringio"
|
4
5
|
require "tempfile"
|
5
6
|
require "fileutils"
|
@@ -92,6 +93,16 @@ module HTTPX
|
|
92
93
|
@length = 0
|
93
94
|
@buffer = nil
|
94
95
|
@state = :idle
|
96
|
+
ObjectSpace.define_finalizer(self, self.class.finalize(@buffer))
|
97
|
+
end
|
98
|
+
|
99
|
+
def self.finalize(buffer)
|
100
|
+
proc {
|
101
|
+
return unless buffer
|
102
|
+
|
103
|
+
@buffer.close
|
104
|
+
@buffer.unlink if @buffer.respond_to?(:unlink)
|
105
|
+
}
|
95
106
|
end
|
96
107
|
|
97
108
|
def closed?
|
@@ -134,18 +145,26 @@ module HTTPX
|
|
134
145
|
end
|
135
146
|
|
136
147
|
def to_s
|
137
|
-
|
138
|
-
|
139
|
-
|
148
|
+
case @buffer
|
149
|
+
when StringIO
|
150
|
+
begin
|
151
|
+
@buffer.string.force_encoding(@encoding)
|
152
|
+
rescue ArgumentError
|
153
|
+
@buffer.string
|
154
|
+
end
|
155
|
+
when Tempfile, File
|
156
|
+
rewind
|
157
|
+
content = _with_same_buffer_pos { @buffer.read }
|
140
158
|
begin
|
141
|
-
|
159
|
+
content.force_encoding(@encoding)
|
142
160
|
rescue ArgumentError # ex: unknown encoding name - utf
|
143
|
-
|
161
|
+
content
|
144
162
|
end
|
163
|
+
when nil
|
164
|
+
"".b
|
165
|
+
else
|
166
|
+
@buffer
|
145
167
|
end
|
146
|
-
"".b
|
147
|
-
ensure
|
148
|
-
close
|
149
168
|
end
|
150
169
|
alias_method :to_str, :to_s
|
151
170
|
|
@@ -177,7 +196,11 @@ module HTTPX
|
|
177
196
|
end
|
178
197
|
|
179
198
|
def ==(other)
|
180
|
-
|
199
|
+
if other.respond_to?(:read)
|
200
|
+
_with_same_buffer_pos { FileUtils.compare_stream(@buffer, other) }
|
201
|
+
else
|
202
|
+
to_s == other.to_s
|
203
|
+
end
|
181
204
|
end
|
182
205
|
|
183
206
|
# :nocov:
|
@@ -204,7 +227,7 @@ module HTTPX
|
|
204
227
|
@buffer = Tempfile.new("httpx", encoding: Encoding::BINARY, mode: File::RDWR)
|
205
228
|
else
|
206
229
|
@state = :memory
|
207
|
-
@buffer = StringIO.new("".b
|
230
|
+
@buffer = StringIO.new("".b)
|
208
231
|
end
|
209
232
|
when :memory
|
210
233
|
if @length > @threshold_size
|
@@ -222,6 +245,18 @@ module HTTPX
|
|
222
245
|
|
223
246
|
return unless %i[memory buffer].include?(@state)
|
224
247
|
end
|
248
|
+
|
249
|
+
def _with_same_buffer_pos
|
250
|
+
return yield unless @buffer && @buffer.respond_to?(:pos)
|
251
|
+
|
252
|
+
current_pos = @buffer.pos
|
253
|
+
@buffer.rewind
|
254
|
+
begin
|
255
|
+
yield
|
256
|
+
rescue StandardError
|
257
|
+
@buffer.pos = current_pos
|
258
|
+
end
|
259
|
+
end
|
225
260
|
end
|
226
261
|
end
|
227
262
|
|
@@ -286,14 +321,6 @@ module HTTPX
|
|
286
321
|
def raise_for_status
|
287
322
|
raise @error
|
288
323
|
end
|
289
|
-
|
290
|
-
# rubocop:disable Style/MissingRespondToMissing
|
291
|
-
def method_missing(meth, *, &block)
|
292
|
-
raise NoMethodError, "undefined response method `#{meth}' for error response" if @options.response_class.public_method_defined?(meth)
|
293
|
-
|
294
|
-
super
|
295
|
-
end
|
296
|
-
# rubocop:enable Style/MissingRespondToMissing
|
297
324
|
end
|
298
325
|
end
|
299
326
|
|
data/lib/httpx/selector.rb
CHANGED
@@ -43,9 +43,6 @@ class HTTPX::Selector
|
|
43
43
|
|
44
44
|
private
|
45
45
|
|
46
|
-
READ_INTERESTS = %i[r rw].freeze
|
47
|
-
WRITE_INTERESTS = %i[w rw].freeze
|
48
|
-
|
49
46
|
def select_many(interval, &block)
|
50
47
|
selectables, r, w = nil
|
51
48
|
|
@@ -64,8 +61,8 @@ class HTTPX::Selector
|
|
64
61
|
selectables.each do |io|
|
65
62
|
interests = io.interests
|
66
63
|
|
67
|
-
(r ||= []) << io if
|
68
|
-
(w ||= []) << io if
|
64
|
+
(r ||= []) << io if READABLE.include?(interests)
|
65
|
+
(w ||= []) << io if WRITABLE.include?(interests)
|
69
66
|
end
|
70
67
|
|
71
68
|
if @selectables.empty?
|
@@ -77,7 +74,7 @@ class HTTPX::Selector
|
|
77
74
|
|
78
75
|
break
|
79
76
|
else
|
80
|
-
@selectables
|
77
|
+
@selectables.concat(selectables)
|
81
78
|
end
|
82
79
|
rescue StandardError
|
83
80
|
@selectables = selectables if selectables
|
@@ -95,14 +92,18 @@ class HTTPX::Selector
|
|
95
92
|
retry
|
96
93
|
end
|
97
94
|
|
98
|
-
|
99
|
-
|
95
|
+
if writers
|
96
|
+
readers.each do |io|
|
97
|
+
yield io
|
100
98
|
|
101
|
-
|
102
|
-
|
103
|
-
|
99
|
+
# so that we don't yield 2 times
|
100
|
+
writers.delete(io)
|
101
|
+
end if readers
|
104
102
|
|
105
|
-
|
103
|
+
writers.each(&block)
|
104
|
+
else
|
105
|
+
readers.each(&block) if readers
|
106
|
+
end
|
106
107
|
end
|
107
108
|
|
108
109
|
def select_one(interval)
|