httpx 0.13.2 → 0.14.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_10_1.md +1 -1
- data/doc/release_notes/0_13_0.md +2 -2
- data/doc/release_notes/0_13_1.md +1 -1
- data/doc/release_notes/0_14_0.md +79 -0
- data/lib/httpx.rb +1 -2
- data/lib/httpx/callbacks.rb +12 -3
- data/lib/httpx/connection.rb +12 -9
- data/lib/httpx/connection/http1.rb +26 -11
- data/lib/httpx/connection/http2.rb +52 -8
- data/lib/httpx/headers.rb +1 -1
- data/lib/httpx/io/tcp.rb +1 -1
- data/lib/httpx/options.rb +91 -56
- data/lib/httpx/plugins/aws_sdk_authentication.rb +5 -2
- data/lib/httpx/plugins/aws_sigv4.rb +4 -4
- data/lib/httpx/plugins/basic_authentication.rb +8 -3
- data/lib/httpx/plugins/compression.rb +8 -8
- data/lib/httpx/plugins/compression/brotli.rb +4 -3
- data/lib/httpx/plugins/compression/deflate.rb +4 -3
- data/lib/httpx/plugins/compression/gzip.rb +2 -1
- data/lib/httpx/plugins/cookies.rb +3 -7
- data/lib/httpx/plugins/digest_authentication.rb +4 -4
- data/lib/httpx/plugins/expect.rb +6 -6
- data/lib/httpx/plugins/follow_redirects.rb +3 -3
- data/lib/httpx/plugins/grpc.rb +247 -0
- data/lib/httpx/plugins/grpc/call.rb +62 -0
- data/lib/httpx/plugins/grpc/message.rb +85 -0
- data/lib/httpx/plugins/multipart/part.rb +1 -1
- data/lib/httpx/plugins/proxy.rb +3 -7
- data/lib/httpx/plugins/proxy/ssh.rb +3 -3
- data/lib/httpx/plugins/rate_limiter.rb +1 -1
- data/lib/httpx/plugins/retries.rb +13 -14
- data/lib/httpx/plugins/stream.rb +96 -74
- data/lib/httpx/plugins/upgrade.rb +4 -4
- data/lib/httpx/request.rb +25 -2
- data/lib/httpx/response.rb +4 -0
- data/lib/httpx/session.rb +17 -7
- data/lib/httpx/transcoder/chunker.rb +1 -1
- data/lib/httpx/version.rb +1 -1
- data/sig/callbacks.rbs +2 -0
- data/sig/connection/http1.rbs +4 -0
- data/sig/connection/http2.rbs +5 -1
- data/sig/options.rbs +9 -2
- data/sig/plugins/aws_sdk_authentication.rbs +2 -0
- data/sig/plugins/basic_authentication.rbs +2 -0
- data/sig/plugins/compression.rbs +2 -2
- data/sig/plugins/stream.rbs +17 -16
- data/sig/request.rbs +7 -2
- data/sig/response.rbs +1 -0
- data/sig/session.rbs +4 -0
- metadata +38 -35
- data/lib/httpx/timeout.rb +0 -67
- data/sig/timeout.rbs +0 -29
data/lib/httpx/headers.rb
CHANGED
data/lib/httpx/io/tcp.rb
CHANGED
@@ -63,7 +63,7 @@ module HTTPX
|
|
63
63
|
@ip_index -= 1
|
64
64
|
retry
|
65
65
|
rescue Errno::ETIMEDOUT => e
|
66
|
-
raise ConnectTimeoutError.new(@options.timeout
|
66
|
+
raise ConnectTimeoutError.new(@options.timeout[:connect_timeout], e.message) if @ip_index <= 0
|
67
67
|
|
68
68
|
@ip_index -= 1
|
69
69
|
retry
|
data/lib/httpx/options.rb
CHANGED
@@ -4,6 +4,37 @@ module HTTPX
|
|
4
4
|
class Options
|
5
5
|
WINDOW_SIZE = 1 << 14 # 16K
|
6
6
|
MAX_BODY_THRESHOLD_SIZE = (1 << 10) * 112 # 112K
|
7
|
+
CONNECT_TIMEOUT = 60
|
8
|
+
OPERATION_TIMEOUT = 60
|
9
|
+
KEEP_ALIVE_TIMEOUT = 20
|
10
|
+
|
11
|
+
DEFAULT_OPTIONS = {
|
12
|
+
:debug => ENV.key?("HTTPX_DEBUG") ? $stderr : nil,
|
13
|
+
:debug_level => (ENV["HTTPX_DEBUG"] || 1).to_i,
|
14
|
+
:ssl => {},
|
15
|
+
:http2_settings => { settings_enable_push: 0 },
|
16
|
+
:fallback_protocol => "http/1.1",
|
17
|
+
:timeout => {
|
18
|
+
connect_timeout: CONNECT_TIMEOUT,
|
19
|
+
operation_timeout: OPERATION_TIMEOUT,
|
20
|
+
keep_alive_timeout: KEEP_ALIVE_TIMEOUT,
|
21
|
+
},
|
22
|
+
:headers => {},
|
23
|
+
:window_size => WINDOW_SIZE,
|
24
|
+
:body_threshold_size => MAX_BODY_THRESHOLD_SIZE,
|
25
|
+
:request_class => Class.new(Request),
|
26
|
+
:response_class => Class.new(Response),
|
27
|
+
:headers_class => Class.new(Headers),
|
28
|
+
:request_body_class => Class.new(Request::Body),
|
29
|
+
:response_body_class => Class.new(Response::Body),
|
30
|
+
:connection_class => Class.new(Connection),
|
31
|
+
:transport => nil,
|
32
|
+
:transport_options => nil,
|
33
|
+
:addresses => nil,
|
34
|
+
:persistent => false,
|
35
|
+
:resolver_class => (ENV["HTTPX_RESOLVER"] || :native).to_sym,
|
36
|
+
:resolver_options => { cache: true },
|
37
|
+
}.freeze
|
7
38
|
|
8
39
|
class << self
|
9
40
|
def new(options = {})
|
@@ -14,10 +45,23 @@ module HTTPX
|
|
14
45
|
super
|
15
46
|
end
|
16
47
|
|
17
|
-
def def_option(name, &interpreter)
|
48
|
+
def def_option(name, layout = nil, &interpreter)
|
18
49
|
attr_reader name
|
19
50
|
|
20
|
-
if
|
51
|
+
if layout
|
52
|
+
class_eval(<<-OUT, __FILE__, __LINE__ + 1)
|
53
|
+
def #{name}=(value)
|
54
|
+
return if value.nil?
|
55
|
+
|
56
|
+
value = begin
|
57
|
+
#{layout}
|
58
|
+
end
|
59
|
+
|
60
|
+
@#{name} = value
|
61
|
+
end
|
62
|
+
OUT
|
63
|
+
|
64
|
+
elsif interpreter
|
21
65
|
define_method(:"#{name}=") do |value|
|
22
66
|
return if value.nil?
|
23
67
|
|
@@ -32,80 +76,71 @@ module HTTPX
|
|
32
76
|
end
|
33
77
|
|
34
78
|
def initialize(options = {})
|
35
|
-
defaults =
|
36
|
-
:debug => ENV.key?("HTTPX_DEBUG") ? $stderr : nil,
|
37
|
-
:debug_level => (ENV["HTTPX_DEBUG"] || 1).to_i,
|
38
|
-
:ssl => {},
|
39
|
-
:http2_settings => { settings_enable_push: 0 },
|
40
|
-
:fallback_protocol => "http/1.1",
|
41
|
-
:timeout => Timeout.new,
|
42
|
-
:headers => {},
|
43
|
-
:window_size => WINDOW_SIZE,
|
44
|
-
:body_threshold_size => MAX_BODY_THRESHOLD_SIZE,
|
45
|
-
:request_class => Class.new(Request),
|
46
|
-
:response_class => Class.new(Response),
|
47
|
-
:headers_class => Class.new(Headers),
|
48
|
-
:request_body_class => Class.new(Request::Body),
|
49
|
-
:response_body_class => Class.new(Response::Body),
|
50
|
-
:connection_class => Class.new(Connection),
|
51
|
-
:transport => nil,
|
52
|
-
:transport_options => nil,
|
53
|
-
:addresses => nil,
|
54
|
-
:persistent => false,
|
55
|
-
:resolver_class => (ENV["HTTPX_RESOLVER"] || :native).to_sym,
|
56
|
-
:resolver_options => { cache: true },
|
57
|
-
}
|
58
|
-
|
59
|
-
defaults.merge!(options)
|
79
|
+
defaults = DEFAULT_OPTIONS.merge(options)
|
60
80
|
defaults.each do |(k, v)|
|
61
81
|
next if v.nil?
|
62
82
|
|
63
|
-
|
83
|
+
begin
|
84
|
+
__send__(:"#{k}=", v)
|
85
|
+
rescue NoMethodError
|
86
|
+
raise Error, "unknown option: #{k}"
|
87
|
+
end
|
64
88
|
end
|
65
89
|
end
|
66
90
|
|
67
|
-
def_option(:
|
91
|
+
def_option(:origin, <<-OUT)
|
92
|
+
URI(value)
|
93
|
+
OUT
|
94
|
+
|
95
|
+
def_option(:headers, <<-OUT)
|
68
96
|
if self.headers
|
69
|
-
self.headers.merge(
|
97
|
+
self.headers.merge(value)
|
70
98
|
else
|
71
|
-
Headers.new(
|
99
|
+
Headers.new(value)
|
72
100
|
end
|
73
|
-
|
101
|
+
OUT
|
74
102
|
|
75
|
-
def_option(:timeout)
|
76
|
-
|
77
|
-
|
103
|
+
def_option(:timeout, <<-OUT)
|
104
|
+
timeouts = Hash[value]
|
105
|
+
|
106
|
+
if timeouts.key?(:loop_timeout)
|
107
|
+
warn ":loop_timeout is deprecated, use :operation_timeout instead"
|
108
|
+
timeouts[:operation_timeout] = timeouts.delete(:loop_timeout)
|
109
|
+
end
|
78
110
|
|
79
|
-
|
80
|
-
|
111
|
+
timeouts
|
112
|
+
OUT
|
81
113
|
|
82
|
-
|
83
|
-
|
114
|
+
def_option(:max_concurrent_requests, <<-OUT)
|
115
|
+
raise Error, ":max_concurrent_requests must be positive" unless value.positive?
|
84
116
|
|
85
|
-
|
86
|
-
|
117
|
+
value
|
118
|
+
OUT
|
87
119
|
|
88
|
-
|
89
|
-
|
120
|
+
def_option(:max_requests, <<-OUT)
|
121
|
+
raise Error, ":max_requests must be positive" unless value.positive?
|
90
122
|
|
91
|
-
|
92
|
-
|
93
|
-
end
|
123
|
+
value
|
124
|
+
OUT
|
94
125
|
|
95
|
-
def_option(:
|
96
|
-
Integer(
|
97
|
-
|
126
|
+
def_option(:window_size, <<-OUT)
|
127
|
+
Integer(value)
|
128
|
+
OUT
|
129
|
+
|
130
|
+
def_option(:body_threshold_size, <<-OUT)
|
131
|
+
Integer(value)
|
132
|
+
OUT
|
98
133
|
|
99
|
-
def_option(:transport)
|
100
|
-
transport =
|
101
|
-
raise Error, "
|
134
|
+
def_option(:transport, <<-OUT)
|
135
|
+
transport = value.to_s
|
136
|
+
raise Error, "\#{transport} is an unsupported transport type" unless IO.registry.key?(transport)
|
102
137
|
|
103
138
|
transport
|
104
|
-
|
139
|
+
OUT
|
105
140
|
|
106
|
-
def_option(:addresses)
|
107
|
-
Array(
|
108
|
-
|
141
|
+
def_option(:addresses, <<-OUT)
|
142
|
+
Array(value)
|
143
|
+
OUT
|
109
144
|
|
110
145
|
%w[
|
111
146
|
params form json body ssl http2_settings
|
@@ -32,9 +32,8 @@ module HTTPX
|
|
32
32
|
class << self
|
33
33
|
attr_reader :credentials, :region
|
34
34
|
|
35
|
-
def load_dependencies(
|
35
|
+
def load_dependencies(_klass)
|
36
36
|
require "aws-sdk-core"
|
37
|
-
klass.plugin(:aws_sigv4)
|
38
37
|
|
39
38
|
client = Class.new(Seahorse::Client::Base) do
|
40
39
|
@identifier = :httpx
|
@@ -50,6 +49,10 @@ module HTTPX
|
|
50
49
|
@region = client.config[:region]
|
51
50
|
end
|
52
51
|
|
52
|
+
def configure(klass)
|
53
|
+
klass.plugin(:aws_sigv4)
|
54
|
+
end
|
55
|
+
|
53
56
|
def extra_options(options)
|
54
57
|
options.merge(max_concurrent_requests: 1)
|
55
58
|
end
|
@@ -143,10 +143,10 @@ module HTTPX
|
|
143
143
|
class << self
|
144
144
|
def extra_options(options)
|
145
145
|
Class.new(options.class) do
|
146
|
-
def_option(:sigv4_signer)
|
147
|
-
|
148
|
-
|
149
|
-
end.new
|
146
|
+
def_option(:sigv4_signer, <<-OUT)
|
147
|
+
value.is_a?(#{Signer}) ? value : #{Signer}.new(value)
|
148
|
+
OUT
|
149
|
+
end.new(options)
|
150
150
|
end
|
151
151
|
|
152
152
|
def load_dependencies(klass)
|
@@ -8,9 +8,14 @@ module HTTPX
|
|
8
8
|
# https://gitlab.com/honeyryderchuck/httpx/wikis/Authentication#basic-authentication
|
9
9
|
#
|
10
10
|
module BasicAuthentication
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
class << self
|
12
|
+
def load_dependencies(_klass)
|
13
|
+
require "base64"
|
14
|
+
end
|
15
|
+
|
16
|
+
def configure(klass)
|
17
|
+
klass.plugin(:authentication)
|
18
|
+
end
|
14
19
|
end
|
15
20
|
|
16
21
|
module InstanceMethods
|
@@ -25,18 +25,18 @@ module HTTPX
|
|
25
25
|
end
|
26
26
|
|
27
27
|
Class.new(options.class) do
|
28
|
-
def_option(:compression_threshold_size)
|
29
|
-
bytes = Integer(
|
28
|
+
def_option(:compression_threshold_size, <<-OUT)
|
29
|
+
bytes = Integer(value)
|
30
30
|
raise Error, ":expect_threshold_size must be positive" unless bytes.positive?
|
31
31
|
|
32
32
|
bytes
|
33
|
-
|
33
|
+
OUT
|
34
34
|
|
35
|
-
def_option(:encodings)
|
36
|
-
raise Error, ":encodings must be a registry" unless
|
35
|
+
def_option(:encodings, <<-OUT)
|
36
|
+
raise Error, ":encodings must be a registry" unless value.respond_to?(:registry)
|
37
37
|
|
38
|
-
|
39
|
-
|
38
|
+
value
|
39
|
+
OUT
|
40
40
|
end.new(options).merge(encodings: encodings)
|
41
41
|
end
|
42
42
|
end
|
@@ -66,7 +66,7 @@ module HTTPX
|
|
66
66
|
|
67
67
|
@body = Encoder.new(@body, options.encodings.registry(encoding).deflater)
|
68
68
|
end
|
69
|
-
@headers["content-length"] = @body.bytesize unless
|
69
|
+
@headers["content-length"] = @body.bytesize unless unbounded_body?
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
@@ -5,12 +5,12 @@ module HTTPX
|
|
5
5
|
module Compression
|
6
6
|
module Brotli
|
7
7
|
class << self
|
8
|
-
def load_dependencies(
|
9
|
-
klass.plugin(:compression)
|
8
|
+
def load_dependencies(_klass)
|
10
9
|
require "brotli"
|
11
10
|
end
|
12
11
|
|
13
12
|
def configure(klass)
|
13
|
+
klass.plugin(:compression)
|
14
14
|
klass.default_options.encodings.register "br", self
|
15
15
|
end
|
16
16
|
end
|
@@ -18,12 +18,13 @@ module HTTPX
|
|
18
18
|
module Deflater
|
19
19
|
module_function
|
20
20
|
|
21
|
-
def deflate(raw, buffer, chunk_size:)
|
21
|
+
def deflate(raw, buffer = "".b, chunk_size: 16_384)
|
22
22
|
while (chunk = raw.read(chunk_size))
|
23
23
|
compressed = ::Brotli.deflate(chunk)
|
24
24
|
buffer << compressed
|
25
25
|
yield compressed if block_given?
|
26
26
|
end
|
27
|
+
buffer
|
27
28
|
end
|
28
29
|
end
|
29
30
|
|
@@ -4,20 +4,20 @@ module HTTPX
|
|
4
4
|
module Plugins
|
5
5
|
module Compression
|
6
6
|
module Deflate
|
7
|
-
def self.load_dependencies(
|
7
|
+
def self.load_dependencies(_klass)
|
8
8
|
require "stringio"
|
9
9
|
require "zlib"
|
10
|
-
klass.plugin(:"compression/gzip")
|
11
10
|
end
|
12
11
|
|
13
12
|
def self.configure(klass)
|
13
|
+
klass.plugin(:"compression/gzip")
|
14
14
|
klass.default_options.encodings.register "deflate", self
|
15
15
|
end
|
16
16
|
|
17
17
|
module Deflater
|
18
18
|
module_function
|
19
19
|
|
20
|
-
def deflate(raw, buffer, chunk_size:)
|
20
|
+
def deflate(raw, buffer = "".b, chunk_size: 16_384)
|
21
21
|
deflater = Zlib::Deflate.new
|
22
22
|
while (chunk = raw.read(chunk_size))
|
23
23
|
compressed = deflater.deflate(chunk)
|
@@ -27,6 +27,7 @@ module HTTPX
|
|
27
27
|
last = deflater.finish
|
28
28
|
buffer << last
|
29
29
|
yield last if block_given?
|
30
|
+
buffer
|
30
31
|
ensure
|
31
32
|
deflater.close if deflater
|
32
33
|
end
|
@@ -19,7 +19,7 @@ module HTTPX
|
|
19
19
|
@compressed_chunk = "".b
|
20
20
|
end
|
21
21
|
|
22
|
-
def deflate(raw, buffer, chunk_size:)
|
22
|
+
def deflate(raw, buffer = "".b, chunk_size: 16_384)
|
23
23
|
gzip = Zlib::GzipWriter.new(self)
|
24
24
|
|
25
25
|
begin
|
@@ -38,6 +38,7 @@ module HTTPX
|
|
38
38
|
|
39
39
|
buffer << compressed
|
40
40
|
yield compressed if block_given?
|
41
|
+
buffer
|
41
42
|
end
|
42
43
|
|
43
44
|
private
|
@@ -20,13 +20,9 @@ module HTTPX
|
|
20
20
|
|
21
21
|
def self.extra_options(options)
|
22
22
|
Class.new(options.class) do
|
23
|
-
def_option(:cookies)
|
24
|
-
|
25
|
-
|
26
|
-
else
|
27
|
-
Jar.new(cookies)
|
28
|
-
end
|
29
|
-
end
|
23
|
+
def_option(:cookies, <<-OUT)
|
24
|
+
value.is_a?(#{Jar}) ? value : #{Jar}.new(value)
|
25
|
+
OUT
|
30
26
|
end.new(options)
|
31
27
|
end
|
32
28
|
|
@@ -14,11 +14,11 @@ module HTTPX
|
|
14
14
|
|
15
15
|
def self.extra_options(options)
|
16
16
|
Class.new(options.class) do
|
17
|
-
def_option(:digest)
|
18
|
-
raise Error, ":digest must be a Digest" unless
|
17
|
+
def_option(:digest, <<-OUT)
|
18
|
+
raise Error, ":digest must be a Digest" unless value.is_a?(#{Digest})
|
19
19
|
|
20
|
-
|
21
|
-
|
20
|
+
value
|
21
|
+
OUT
|
22
22
|
end.new(options)
|
23
23
|
end
|
24
24
|
|
data/lib/httpx/plugins/expect.rb
CHANGED
@@ -16,19 +16,19 @@ module HTTPX
|
|
16
16
|
|
17
17
|
def self.extra_options(options)
|
18
18
|
Class.new(options.class) do
|
19
|
-
def_option(:expect_timeout)
|
20
|
-
seconds = Integer(
|
19
|
+
def_option(:expect_timeout, <<-OUT)
|
20
|
+
seconds = Integer(value)
|
21
21
|
raise Error, ":expect_timeout must be positive" unless seconds.positive?
|
22
22
|
|
23
23
|
seconds
|
24
|
-
|
24
|
+
OUT
|
25
25
|
|
26
|
-
def_option(:expect_threshold_size)
|
27
|
-
bytes = Integer(
|
26
|
+
def_option(:expect_threshold_size, <<-OUT)
|
27
|
+
bytes = Integer(value)
|
28
28
|
raise Error, ":expect_threshold_size must be positive" unless bytes.positive?
|
29
29
|
|
30
30
|
bytes
|
31
|
-
|
31
|
+
OUT
|
32
32
|
end.new(options).merge(expect_timeout: EXPECT_TIMEOUT)
|
33
33
|
end
|
34
34
|
|
@@ -19,12 +19,12 @@ module HTTPX
|
|
19
19
|
|
20
20
|
def self.extra_options(options)
|
21
21
|
Class.new(options.class) do
|
22
|
-
def_option(:max_redirects)
|
23
|
-
num = Integer(
|
22
|
+
def_option(:max_redirects, <<-OUT)
|
23
|
+
num = Integer(value)
|
24
24
|
raise Error, ":max_redirects must be positive" if num.negative?
|
25
25
|
|
26
26
|
num
|
27
|
-
|
27
|
+
OUT
|
28
28
|
|
29
29
|
def_option(:follow_insecure_redirects)
|
30
30
|
end.new(options)
|