httpx 0.4.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/httpx/adapters/faraday.rb +27 -24
- data/lib/httpx/connection.rb +6 -6
- data/lib/httpx/errors.rb +9 -0
- data/lib/httpx/plugins/authentication.rb +3 -1
- data/lib/httpx/plugins/basic_authentication.rb +4 -3
- data/lib/httpx/plugins/compression.rb +3 -1
- data/lib/httpx/plugins/compression/brotli.rb +1 -1
- data/lib/httpx/plugins/cookies.rb +2 -0
- data/lib/httpx/plugins/digest_authentication.rb +3 -2
- data/lib/httpx/plugins/follow_redirects.rb +3 -1
- data/lib/httpx/plugins/h2c.rb +3 -2
- data/lib/httpx/plugins/multipart.rb +2 -0
- data/lib/httpx/plugins/persistent.rb +4 -2
- data/lib/httpx/plugins/proxy.rb +3 -1
- data/lib/httpx/plugins/proxy/ssh.rb +16 -2
- data/lib/httpx/plugins/push_promise.rb +2 -0
- data/lib/httpx/plugins/retries.rb +4 -2
- data/lib/httpx/resolver/native.rb +16 -8
- data/lib/httpx/response.rb +3 -2
- data/lib/httpx/session.rb +5 -4
- data/lib/httpx/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cdf61781fa437f8bf02932b38f029d56f25443690eee087fb09974c5d48595a3
|
4
|
+
data.tar.gz: 75ab23803f01f6c52bcc6f754a93c799efce99b5892c9a4f0815c6254a3e022c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 57ae0b1d04da8d0e19951a704a40d9c136785281fb5ec2677aaac6b54e98baab0542ad4c8d40553270af8b120d6cf856678bd62554fe1cab7192bfdc26ee08f2
|
7
|
+
data.tar.gz: 1e0f59ecd050838021578981d3ea1f3fa467671ef6c7efc740770cb33462ec81afa7e6a55bbfa2814cd19dacff0bf0e887c6b24ecea405c5440daf369074f766
|
@@ -18,6 +18,31 @@ module Faraday
|
|
18
18
|
}
|
19
19
|
[meth, env.url, request_options]
|
20
20
|
end
|
21
|
+
|
22
|
+
def options_from_env(env)
|
23
|
+
timeout_options = {
|
24
|
+
connect_timeout: env.request.open_timeout,
|
25
|
+
operation_timeout: env.request.timeout,
|
26
|
+
}.reject { |_, v| v.nil? }
|
27
|
+
|
28
|
+
options = {
|
29
|
+
ssl: {},
|
30
|
+
timeout: timeout_options,
|
31
|
+
}
|
32
|
+
|
33
|
+
options[:ssl][:verify_mode] = OpenSSL::SSL::VERIFY_PEER if env.ssl.verify
|
34
|
+
options[:ssl][:ca_file] = env.ssl.ca_file if env.ssl.ca_file
|
35
|
+
options[:ssl][:ca_path] = env.ssl.ca_path if env.ssl.ca_path
|
36
|
+
options[:ssl][:cert_store] = env.ssl.cert_store if env.ssl.cert_store
|
37
|
+
options[:ssl][:cert] = env.ssl.client_cert if env.ssl.client_cert
|
38
|
+
options[:ssl][:key] = env.ssl.client_key if env.ssl.client_key
|
39
|
+
options[:ssl][:ssl_version] = env.ssl.version if env.ssl.version
|
40
|
+
options[:ssl][:verify_depth] = env.ssl.verify_depth if env.ssl.verify_depth
|
41
|
+
options[:ssl][:min_version] = env.ssl.min_version if env.ssl.min_version
|
42
|
+
options[:ssl][:max_version] = env.ssl.max_version if env.ssl.max_version
|
43
|
+
|
44
|
+
options
|
45
|
+
end
|
21
46
|
end
|
22
47
|
|
23
48
|
include RequestMixin
|
@@ -109,19 +134,9 @@ module Faraday
|
|
109
134
|
requests = @handlers.map { |handler| build_request(handler.env) }
|
110
135
|
env = @handlers.last.env
|
111
136
|
|
112
|
-
timeout_options = {
|
113
|
-
connect_timeout: env.request.open_timeout,
|
114
|
-
operation_timeout: env.request.timeout,
|
115
|
-
}.reject { |_, v| v.nil? }
|
116
|
-
|
117
|
-
options = {
|
118
|
-
ssl: env.ssl,
|
119
|
-
timeout: timeout_options,
|
120
|
-
}
|
121
|
-
|
122
137
|
proxy_options = { uri: env.request.proxy }
|
123
138
|
|
124
|
-
session = @session.with(
|
139
|
+
session = @session.with(options_from_env(env))
|
125
140
|
session = session.plugin(:proxy).with_proxy(proxy_options) if env.request.proxy
|
126
141
|
|
127
142
|
responses = session.request(requests)
|
@@ -159,19 +174,7 @@ module Faraday
|
|
159
174
|
|
160
175
|
request_options = build_request(env)
|
161
176
|
|
162
|
-
|
163
|
-
connect_timeout: env.request.open_timeout,
|
164
|
-
operation_timeout: env.request.timeout,
|
165
|
-
}.reject { |_, v| v.nil? }
|
166
|
-
|
167
|
-
options = {
|
168
|
-
ssl: env.ssl,
|
169
|
-
timeout: timeout_options,
|
170
|
-
}
|
171
|
-
|
172
|
-
proxy_options = { uri: env.request.proxy }
|
173
|
-
|
174
|
-
session = @session.with(options)
|
177
|
+
session = @session.with(options_from_env(env))
|
175
178
|
session = session.plugin(:proxy).with_proxy(proxy_options) if env.request.proxy
|
176
179
|
response = session.__send__(*request_options)
|
177
180
|
response.raise_for_status unless response.is_a?(::HTTPX::Response)
|
data/lib/httpx/connection.rb
CHANGED
@@ -177,8 +177,8 @@ module HTTPX
|
|
177
177
|
end
|
178
178
|
|
179
179
|
def send(request)
|
180
|
-
if @
|
181
|
-
emit(:response, request, @
|
180
|
+
if @error
|
181
|
+
emit(:response, request, ErrorResponse.new(request, @error, @options))
|
182
182
|
elsif @parser && !@write_buffer.full?
|
183
183
|
request.headers["alt-used"] = @origin.authority if match_altsvcs?(request.uri)
|
184
184
|
parser.send(request)
|
@@ -297,7 +297,7 @@ module HTTPX
|
|
297
297
|
when MisdirectedRequestError
|
298
298
|
emit(:uncoalesce, request.uri)
|
299
299
|
else
|
300
|
-
response = ErrorResponse.new(ex, @options)
|
300
|
+
response = ErrorResponse.new(request, ex, @options)
|
301
301
|
request.emit(:response, response)
|
302
302
|
end
|
303
303
|
end
|
@@ -306,7 +306,7 @@ module HTTPX
|
|
306
306
|
def transition(nextstate)
|
307
307
|
case nextstate
|
308
308
|
when :idle
|
309
|
-
@
|
309
|
+
@error = nil
|
310
310
|
@timeout_threshold = @options.timeout.connect_timeout
|
311
311
|
@timeout = @timeout_threshold
|
312
312
|
when :open
|
@@ -363,9 +363,9 @@ module HTTPX
|
|
363
363
|
end
|
364
364
|
|
365
365
|
parser.handle_error(e) if @parser && parser.respond_to?(:handle_error)
|
366
|
-
@
|
366
|
+
@error = e
|
367
367
|
@pending.each do |request, _|
|
368
|
-
request.emit(:response, @
|
368
|
+
request.emit(:response, ErrorResponse.new(request, @error, @options))
|
369
369
|
end
|
370
370
|
end
|
371
371
|
end
|
data/lib/httpx/errors.rb
CHANGED
@@ -26,6 +26,15 @@ module HTTPX
|
|
26
26
|
|
27
27
|
ResolveError = Class.new(Error)
|
28
28
|
|
29
|
+
NativeResolveError = Class.new(ResolveError) do
|
30
|
+
attr_reader :connection, :host
|
31
|
+
def initialize(connection, host, message = "Can't resolve #{host}")
|
32
|
+
@connection = connection
|
33
|
+
@host = host
|
34
|
+
super(message)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
29
38
|
HTTPError = Class.new(Error) do
|
30
39
|
attr_reader :response
|
31
40
|
|
@@ -3,9 +3,11 @@
|
|
3
3
|
module HTTPX
|
4
4
|
module Plugins
|
5
5
|
#
|
6
|
-
# This plugin adds a shim
|
6
|
+
# This plugin adds a shim +authentication+ method to the session, which will fill
|
7
7
|
# the HTTP Authorization header.
|
8
8
|
#
|
9
|
+
# https://gitlab.com/honeyryderchuck/httpx/wikis/Authentication#authentication
|
10
|
+
#
|
9
11
|
module Authentication
|
10
12
|
module InstanceMethods
|
11
13
|
def authentication(token)
|
@@ -3,11 +3,12 @@
|
|
3
3
|
module HTTPX
|
4
4
|
module Plugins
|
5
5
|
#
|
6
|
-
# This plugin adds helper methods to implement HTTP Basic Auth
|
7
|
-
#
|
6
|
+
# This plugin adds helper methods to implement HTTP Basic Auth (https://tools.ietf.org/html/rfc7617)
|
7
|
+
#
|
8
|
+
# https://gitlab.com/honeyryderchuck/httpx/wikis/Authentication#basic-authentication
|
8
9
|
#
|
9
10
|
module BasicAuthentication
|
10
|
-
def self.load_dependencies(klass
|
11
|
+
def self.load_dependencies(klass)
|
11
12
|
require "base64"
|
12
13
|
klass.plugin(:authentication)
|
13
14
|
end
|
@@ -10,9 +10,11 @@ module HTTPX
|
|
10
10
|
#
|
11
11
|
# It supports both *gzip* and *deflate*.
|
12
12
|
#
|
13
|
+
# https://gitlab.com/honeyryderchuck/httpx/wikis/Compression
|
14
|
+
#
|
13
15
|
module Compression
|
14
16
|
extend Registry
|
15
|
-
def self.load_dependencies(klass
|
17
|
+
def self.load_dependencies(klass)
|
16
18
|
klass.plugin(:"compression/gzip")
|
17
19
|
klass.plugin(:"compression/deflate")
|
18
20
|
end
|
@@ -3,8 +3,9 @@
|
|
3
3
|
module HTTPX
|
4
4
|
module Plugins
|
5
5
|
#
|
6
|
-
# This plugin adds helper methods to implement HTTP Digest Auth
|
7
|
-
#
|
6
|
+
# This plugin adds helper methods to implement HTTP Digest Auth (https://tools.ietf.org/html/rfc7616)
|
7
|
+
#
|
8
|
+
# https://gitlab.com/honeyryderchuck/httpx/wikis/Authentication#authentication
|
8
9
|
#
|
9
10
|
module DigestAuthentication
|
10
11
|
DigestError = Class.new(Error)
|
@@ -11,6 +11,8 @@ module HTTPX
|
|
11
11
|
#
|
12
12
|
# It also doesn't follow insecure redirects (https -> http) by default (see *follow_insecure_redirects*).
|
13
13
|
#
|
14
|
+
# https://gitlab.com/honeyryderchuck/httpx/wikis/Follow-Redirects
|
15
|
+
#
|
14
16
|
module FollowRedirects
|
15
17
|
MAX_REDIRECTS = 3
|
16
18
|
REDIRECT_STATUS = (300..399).freeze
|
@@ -54,7 +56,7 @@ module HTTPX
|
|
54
56
|
retry_request.uri.scheme == "http"
|
55
57
|
error = InsecureRedirectError.new(retry_request.uri.to_s)
|
56
58
|
error.set_backtrace(caller)
|
57
|
-
return ErrorResponse.new(error, options)
|
59
|
+
return ErrorResponse.new(request, error, options)
|
58
60
|
end
|
59
61
|
|
60
62
|
connection = find_connection(retry_request, connections, options)
|
data/lib/httpx/plugins/h2c.rb
CHANGED
@@ -3,9 +3,10 @@
|
|
3
3
|
module HTTPX
|
4
4
|
module Plugins
|
5
5
|
#
|
6
|
-
# This plugin adds support for upgrading a plaintext HTTP/1.1 connection to HTTP/2
|
6
|
+
# This plugin adds support for upgrading a plaintext HTTP/1.1 connection to HTTP/2
|
7
|
+
# (https://tools.ietf.org/html/rfc7540#section-3.2)
|
7
8
|
#
|
8
|
-
# https://
|
9
|
+
# https://gitlab.com/honeyryderchuck/httpx/wikis/Follow-Redirects
|
9
10
|
#
|
10
11
|
module H2C
|
11
12
|
def self.load_dependencies(*)
|
@@ -15,9 +15,11 @@ module HTTPX
|
|
15
15
|
# This plugin is also not recommendable when connecting to >9000 (like, a lot) different origins.
|
16
16
|
# So when you use this, make sure that you don't fall into this trap.
|
17
17
|
#
|
18
|
+
# https://gitlab.com/honeyryderchuck/httpx/wikis/Persistent
|
19
|
+
#
|
18
20
|
module Persistent
|
19
|
-
def self.load_dependencies(klass
|
20
|
-
klass.plugin(:retries
|
21
|
+
def self.load_dependencies(klass)
|
22
|
+
klass.plugin(:retries, max_retries: 1, retry_change_requests: true)
|
21
23
|
end
|
22
24
|
|
23
25
|
def self.extra_options(options)
|
data/lib/httpx/plugins/proxy.rb
CHANGED
@@ -14,6 +14,8 @@ module HTTPX
|
|
14
14
|
# * Socks4/4a proxies
|
15
15
|
# * Socks5 proxies
|
16
16
|
#
|
17
|
+
# https://gitlab.com/honeyryderchuck/httpx/wikis/Proxy
|
18
|
+
#
|
17
19
|
module Proxy
|
18
20
|
Error = Class.new(Error)
|
19
21
|
PROXY_ERRORS = [TimeoutError, IOError, SystemCallError, Error].freeze
|
@@ -47,7 +49,7 @@ module HTTPX
|
|
47
49
|
end
|
48
50
|
|
49
51
|
class << self
|
50
|
-
def configure(klass
|
52
|
+
def configure(klass)
|
51
53
|
klass.plugin(:"proxy/http")
|
52
54
|
klass.plugin(:"proxy/socks4")
|
53
55
|
klass.plugin(:"proxy/socks5")
|
@@ -6,8 +6,7 @@ module HTTPX
|
|
6
6
|
module Plugins
|
7
7
|
module Proxy
|
8
8
|
module SSH
|
9
|
-
def self.load_dependencies(
|
10
|
-
# klass.plugin(:proxy)
|
9
|
+
def self.load_dependencies(*)
|
11
10
|
require "net/ssh/gateway"
|
12
11
|
end
|
13
12
|
|
@@ -74,6 +73,21 @@ module HTTPX
|
|
74
73
|
end
|
75
74
|
end
|
76
75
|
end
|
76
|
+
|
77
|
+
module ConnectionMethods
|
78
|
+
def match?(uri, options)
|
79
|
+
return super unless @options.proxy
|
80
|
+
|
81
|
+
super && @options.proxy == options.proxy
|
82
|
+
end
|
83
|
+
|
84
|
+
# should not coalesce connections here, as the IP is the IP of the proxy
|
85
|
+
def coalescable?(*)
|
86
|
+
return super unless @options.proxy
|
87
|
+
|
88
|
+
false
|
89
|
+
end
|
90
|
+
end
|
77
91
|
end
|
78
92
|
end
|
79
93
|
register_plugin :"proxy/ssh", Proxy::SSH
|
@@ -8,6 +8,8 @@ module HTTPX
|
|
8
8
|
# In order to benefit from this, requests are sent one at a time, so that
|
9
9
|
# no push responses are received after corresponding request has been sent.
|
10
10
|
#
|
11
|
+
# https://gitlab.com/honeyryderchuck/httpx/wikis/Server-Push
|
12
|
+
#
|
11
13
|
module PushPromise
|
12
14
|
def self.extra_options(options)
|
13
15
|
options.merge(http2_settings: { settings_enable_push: 1 },
|
@@ -5,6 +5,8 @@ module HTTPX
|
|
5
5
|
#
|
6
6
|
# This plugin adds support for retrying requests when certain errors happen.
|
7
7
|
#
|
8
|
+
# https://gitlab.com/honeyryderchuck/httpx/wikis/Retries
|
9
|
+
#
|
8
10
|
module Retries
|
9
11
|
MAX_RETRIES = 3
|
10
12
|
# TODO: pass max_retries in a configure/load block
|
@@ -31,7 +33,7 @@ module HTTPX
|
|
31
33
|
end
|
32
34
|
|
33
35
|
def_option(:retry_change_requests)
|
34
|
-
end.new(options)
|
36
|
+
end.new(options).merge(max_retries: MAX_RETRIES)
|
35
37
|
end
|
36
38
|
|
37
39
|
module InstanceMethods
|
@@ -71,7 +73,7 @@ module HTTPX
|
|
71
73
|
|
72
74
|
def initialize(*args)
|
73
75
|
super
|
74
|
-
@retries = @options.max_retries
|
76
|
+
@retries = @options.max_retries
|
75
77
|
end
|
76
78
|
end
|
77
79
|
end
|
@@ -76,13 +76,22 @@ module HTTPX
|
|
76
76
|
consume
|
77
77
|
end
|
78
78
|
nil
|
79
|
-
rescue Errno::EHOSTUNREACH
|
79
|
+
rescue Errno::EHOSTUNREACH,
|
80
|
+
NativeResolveError => e
|
80
81
|
@ns_index += 1
|
81
82
|
if @ns_index < @nameserver.size
|
83
|
+
log(label: "resolver: ") do
|
84
|
+
"failed resolving on nameserver #{@nameserver[@ns_index - 1]} (#{e.message})"
|
85
|
+
end
|
82
86
|
transition(:idle)
|
83
87
|
else
|
84
|
-
|
88
|
+
if e.respond_to?(:connection) &&
|
89
|
+
e.respond_to?(:host)
|
85
90
|
emit_resolve_error(connection, host, e)
|
91
|
+
else
|
92
|
+
@queries.each do |host, connection|
|
93
|
+
emit_resolve_error(connection, host, e)
|
94
|
+
end
|
86
95
|
end
|
87
96
|
end
|
88
97
|
end
|
@@ -141,8 +150,7 @@ module HTTPX
|
|
141
150
|
@timeouts[host].shift
|
142
151
|
if @timeouts[host].empty?
|
143
152
|
@timeouts.delete(host)
|
144
|
-
|
145
|
-
return
|
153
|
+
raise NativeResolveError.new(connection, host)
|
146
154
|
else
|
147
155
|
connections << connection
|
148
156
|
log(label: "resolver: ") do
|
@@ -188,8 +196,9 @@ module HTTPX
|
|
188
196
|
rescue Resolv::DNS::DecodeError => e
|
189
197
|
hostname, connection = @queries.first
|
190
198
|
if @_record_types[hostname].empty?
|
191
|
-
|
192
|
-
|
199
|
+
ex = NativeResolveError.new(connection, hostname, e.message)
|
200
|
+
ex.set_backtrace(e.backtrace)
|
201
|
+
raise ex
|
193
202
|
end
|
194
203
|
end
|
195
204
|
|
@@ -198,8 +207,7 @@ module HTTPX
|
|
198
207
|
@_record_types[hostname].shift
|
199
208
|
if @_record_types[hostname].empty?
|
200
209
|
@_record_types.delete(hostname)
|
201
|
-
|
202
|
-
return
|
210
|
+
raise NativeResolveError.new(connection, hostname)
|
203
211
|
end
|
204
212
|
else
|
205
213
|
address = addresses.first
|
data/lib/httpx/response.rb
CHANGED
@@ -238,9 +238,10 @@ module HTTPX
|
|
238
238
|
class ErrorResponse
|
239
239
|
include Loggable
|
240
240
|
|
241
|
-
attr_reader :error
|
241
|
+
attr_reader :request, :error
|
242
242
|
|
243
|
-
def initialize(error, options)
|
243
|
+
def initialize(request, error, options)
|
244
|
+
@request = request
|
244
245
|
@error = error
|
245
246
|
@options = Options.new(options)
|
246
247
|
log_exception(@error)
|
data/lib/httpx/session.rb
CHANGED
@@ -203,14 +203,15 @@ module HTTPX
|
|
203
203
|
klass.instance_variable_set(:@plugins, @plugins.dup)
|
204
204
|
end
|
205
205
|
|
206
|
-
def plugin(pl,
|
206
|
+
def plugin(pl, options = nil, &block)
|
207
207
|
# raise Error, "Cannot add a plugin to a frozen config" if frozen?
|
208
208
|
pl = Plugins.load_plugin(pl) if pl.is_a?(Symbol)
|
209
209
|
unless @plugins.include?(pl)
|
210
210
|
@plugins << pl
|
211
|
-
pl.load_dependencies(self,
|
211
|
+
pl.load_dependencies(self, &block) if pl.respond_to?(:load_dependencies)
|
212
212
|
@default_options = @default_options.dup
|
213
|
-
@default_options = pl.extra_options(@default_options) if pl.respond_to?(:extra_options)
|
213
|
+
@default_options = pl.extra_options(@default_options, &block) if pl.respond_to?(:extra_options)
|
214
|
+
@default_options = @default_options.merge(options) if options
|
214
215
|
|
215
216
|
include(pl::InstanceMethods) if defined?(pl::InstanceMethods)
|
216
217
|
extend(pl::ClassMethods) if defined?(pl::ClassMethods)
|
@@ -227,7 +228,7 @@ module HTTPX
|
|
227
228
|
opts.response_body_class.__send__(:include, pl::ResponseBodyMethods) if defined?(pl::ResponseBodyMethods)
|
228
229
|
opts.response_body_class.extend(pl::ResponseBodyClassMethods) if defined?(pl::ResponseBodyClassMethods)
|
229
230
|
opts.connection_class.__send__(:include, pl::ConnectionMethods) if defined?(pl::ConnectionMethods)
|
230
|
-
pl.configure(self,
|
231
|
+
pl.configure(self, &block) if pl.respond_to?(:configure)
|
231
232
|
|
232
233
|
@default_options.freeze
|
233
234
|
end
|
data/lib/httpx/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: httpx
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tiago Cardoso
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-06-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: http-2
|