faraday 0.16.2 → 0.17.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/LICENSE.md +1 -1
- data/README.md +347 -18
- data/lib/faraday.rb +175 -93
- data/lib/faraday/adapter.rb +22 -36
- data/lib/faraday/adapter/em_http.rb +99 -142
- data/lib/faraday/adapter/em_http_ssl_patch.rb +17 -23
- data/lib/faraday/adapter/em_synchrony.rb +60 -104
- data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +15 -18
- data/lib/faraday/adapter/excon.rb +55 -100
- data/lib/faraday/adapter/httpclient.rb +39 -61
- data/lib/faraday/adapter/net_http.rb +51 -104
- data/lib/faraday/adapter/net_http_persistent.rb +27 -48
- data/lib/faraday/adapter/patron.rb +35 -54
- data/lib/faraday/adapter/rack.rb +12 -28
- data/lib/faraday/adapter/test.rb +53 -86
- data/lib/faraday/adapter/typhoeus.rb +1 -4
- data/lib/faraday/autoload.rb +36 -47
- data/lib/faraday/connection.rb +179 -321
- data/lib/faraday/error.rb +32 -80
- data/lib/faraday/middleware.rb +28 -4
- data/lib/faraday/options.rb +186 -35
- data/lib/faraday/parameters.rb +197 -4
- data/lib/faraday/rack_builder.rb +56 -67
- data/lib/faraday/request.rb +36 -68
- data/lib/faraday/request/authorization.rb +30 -42
- data/lib/faraday/request/basic_authentication.rb +7 -14
- data/lib/faraday/request/instrumentation.rb +27 -45
- data/lib/faraday/request/multipart.rb +48 -79
- data/lib/faraday/request/retry.rb +170 -197
- data/lib/faraday/request/token_authentication.rb +10 -15
- data/lib/faraday/request/url_encoded.rb +23 -41
- data/lib/faraday/response.rb +16 -23
- data/lib/faraday/response/logger.rb +69 -22
- data/lib/faraday/response/raise_error.rb +14 -36
- data/lib/faraday/upload_io.rb +67 -0
- data/lib/faraday/utils.rb +245 -28
- metadata +5 -22
- data/lib/faraday/adapter_registry.rb +0 -28
- data/lib/faraday/dependency_loader.rb +0 -37
- data/lib/faraday/deprecated_class.rb +0 -28
- data/lib/faraday/encoders/flat_params_encoder.rb +0 -94
- data/lib/faraday/encoders/nested_params_encoder.rb +0 -171
- data/lib/faraday/file_part.rb +0 -128
- data/lib/faraday/logging/formatter.rb +0 -92
- data/lib/faraday/middleware_registry.rb +0 -129
- data/lib/faraday/options/connection_options.rb +0 -22
- data/lib/faraday/options/env.rb +0 -181
- data/lib/faraday/options/proxy_options.rb +0 -28
- data/lib/faraday/options/request_options.rb +0 -21
- data/lib/faraday/options/ssl_options.rb +0 -59
- data/lib/faraday/param_part.rb +0 -53
- data/lib/faraday/utils/headers.rb +0 -139
- data/lib/faraday/utils/params_hash.rb +0 -61
- data/spec/external_adapters/faraday_specs_setup.rb +0 -14
data/lib/faraday/request.rb
CHANGED
@@ -1,9 +1,6 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
1
|
module Faraday
|
4
|
-
# Used to setup
|
2
|
+
# Used to setup urls, params, headers, and the request body in a sane manner.
|
5
3
|
#
|
6
|
-
# @example
|
7
4
|
# @connection.post do |req|
|
8
5
|
# req.url 'http://localhost', 'a' => '1' # 'http://localhost?a=1'
|
9
6
|
# req.headers['b'] = '2' # Header
|
@@ -12,53 +9,25 @@ module Faraday
|
|
12
9
|
# req.body = 'abc'
|
13
10
|
# end
|
14
11
|
#
|
15
|
-
# @!attribute method
|
16
|
-
# @return [Symbol] the HTTP method of the Request
|
17
|
-
# @!attribute path
|
18
|
-
# @return [URI, String] the path
|
19
|
-
# @!attribute params
|
20
|
-
# @return [Hash] query parameters
|
21
|
-
# @!attribute headers
|
22
|
-
# @return [Faraday::Utils::Headers] headers
|
23
|
-
# @!attribute body
|
24
|
-
# @return [Hash] body
|
25
|
-
# @!attribute options
|
26
|
-
# @return [RequestOptions] options
|
27
|
-
#
|
28
|
-
# rubocop:disable Style/StructInheritance
|
29
12
|
class Request < Struct.new(:method, :path, :params, :headers, :body, :options)
|
30
|
-
# rubocop:enable Style/StructInheritance
|
31
|
-
|
32
13
|
extend MiddlewareRegistry
|
33
14
|
|
34
|
-
register_middleware File.expand_path('request',
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
],
|
43
|
-
token_auth: [
|
44
|
-
:TokenAuthentication,
|
45
|
-
'token_authentication'
|
46
|
-
],
|
47
|
-
instrumentation: [:Instrumentation, 'instrumentation']
|
15
|
+
register_middleware File.expand_path('../request', __FILE__),
|
16
|
+
:url_encoded => [:UrlEncoded, 'url_encoded'],
|
17
|
+
:multipart => [:Multipart, 'multipart'],
|
18
|
+
:retry => [:Retry, 'retry'],
|
19
|
+
:authorization => [:Authorization, 'authorization'],
|
20
|
+
:basic_auth => [:BasicAuthentication, 'basic_authentication'],
|
21
|
+
:token_auth => [:TokenAuthentication, 'token_authentication'],
|
22
|
+
:instrumentation => [:Instrumentation, 'instrumentation']
|
48
23
|
|
49
|
-
# @param request_method [String]
|
50
|
-
# @yield [request] for block customization, if block given
|
51
|
-
# @yieldparam request [Request]
|
52
|
-
# @return [Request]
|
53
24
|
def self.create(request_method)
|
54
25
|
new(request_method).tap do |request|
|
55
26
|
yield(request) if block_given?
|
56
27
|
end
|
57
28
|
end
|
58
29
|
|
59
|
-
# Replace params, preserving the existing hash type
|
60
|
-
#
|
61
|
-
# @param hash [Hash] new params
|
30
|
+
# Public: Replace params, preserving the existing hash type
|
62
31
|
def params=(hash)
|
63
32
|
if params
|
64
33
|
params.replace hash
|
@@ -67,9 +36,7 @@ module Faraday
|
|
67
36
|
end
|
68
37
|
end
|
69
38
|
|
70
|
-
# Replace request headers, preserving the existing hash type
|
71
|
-
#
|
72
|
-
# @param hash [Hash] new headers
|
39
|
+
# Public: Replace request headers, preserving the existing hash type
|
73
40
|
def headers=(hash)
|
74
41
|
if headers
|
75
42
|
headers.replace hash
|
@@ -78,14 +45,9 @@ module Faraday
|
|
78
45
|
end
|
79
46
|
end
|
80
47
|
|
81
|
-
# Update path and params.
|
82
|
-
#
|
83
|
-
# @param path [URI, String]
|
84
|
-
# @param params [Hash, nil]
|
85
|
-
# @return [void]
|
86
48
|
def url(path, params = nil)
|
87
49
|
if path.respond_to? :query
|
88
|
-
if
|
50
|
+
if query = path.query
|
89
51
|
path = path.dup
|
90
52
|
path.query = nil
|
91
53
|
end
|
@@ -99,35 +61,25 @@ module Faraday
|
|
99
61
|
self.params.update(params) if params
|
100
62
|
end
|
101
63
|
|
102
|
-
# @param key [Object] key to look up in headers
|
103
|
-
# @return [Object] value of the given header name
|
104
64
|
def [](key)
|
105
65
|
headers[key]
|
106
66
|
end
|
107
67
|
|
108
|
-
# @param key [Object] key of header to write
|
109
|
-
# @param value [Object] value of header
|
110
68
|
def []=(key, value)
|
111
69
|
headers[key] = value
|
112
70
|
end
|
113
71
|
|
114
|
-
# Marshal serialization support.
|
115
|
-
#
|
116
|
-
# @return [Hash] the hash ready to be serialized in Marshal.
|
117
72
|
def marshal_dump
|
118
73
|
{
|
119
|
-
method
|
120
|
-
body
|
121
|
-
headers
|
122
|
-
path
|
123
|
-
params
|
124
|
-
options
|
74
|
+
:method => method,
|
75
|
+
:body => body,
|
76
|
+
:headers => headers,
|
77
|
+
:path => path,
|
78
|
+
:params => params,
|
79
|
+
:options => options
|
125
80
|
}
|
126
81
|
end
|
127
82
|
|
128
|
-
# Marshal serialization support.
|
129
|
-
# Restores the instance variables according to the +serialised+.
|
130
|
-
# @param serialised [Hash] the serialised object.
|
131
83
|
def marshal_load(serialised)
|
132
84
|
self.method = serialised[:method]
|
133
85
|
self.body = serialised[:body]
|
@@ -137,10 +89,26 @@ module Faraday
|
|
137
89
|
self.options = serialised[:options]
|
138
90
|
end
|
139
91
|
|
140
|
-
#
|
92
|
+
# ENV Keys
|
93
|
+
# :method - a symbolized request method (:get, :post)
|
94
|
+
# :body - the request body that will eventually be converted to a string.
|
95
|
+
# :url - URI instance for the current request.
|
96
|
+
# :status - HTTP response status code
|
97
|
+
# :request_headers - hash of HTTP Headers to be sent to the server
|
98
|
+
# :response_headers - Hash of HTTP headers from the server
|
99
|
+
# :parallel_manager - sent if the connection is in parallel mode
|
100
|
+
# :request - Hash of options for configuring the request.
|
101
|
+
# :timeout - open/read timeout Integer in seconds
|
102
|
+
# :open_timeout - read timeout Integer in seconds
|
103
|
+
# :proxy - Hash of proxy options
|
104
|
+
# :uri - Proxy Server URI
|
105
|
+
# :user - Proxy server username
|
106
|
+
# :password - Proxy server password
|
107
|
+
# :ssl - Hash of options for configuring SSL requests.
|
141
108
|
def to_env(connection)
|
142
109
|
Env.new(method, body, connection.build_exclusive_url(path, params),
|
143
|
-
|
110
|
+
options, headers, connection.ssl, connection.parallel_manager)
|
144
111
|
end
|
145
112
|
end
|
146
113
|
end
|
114
|
+
|
@@ -1,53 +1,41 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
1
|
module Faraday
|
4
|
-
class Request
|
5
|
-
|
6
|
-
class Authorization < Faraday::Middleware
|
7
|
-
KEY = 'Authorization' unless defined? KEY
|
2
|
+
class Request::Authorization < Faraday::Middleware
|
3
|
+
KEY = "Authorization".freeze unless defined? KEY
|
8
4
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
else
|
19
|
-
raise ArgumentError,
|
20
|
-
"Can't build an Authorization #{type}" \
|
21
|
-
"header from #{token.inspect}"
|
22
|
-
end
|
5
|
+
# Public
|
6
|
+
def self.header(type, token)
|
7
|
+
case token
|
8
|
+
when String, Symbol
|
9
|
+
"#{type} #{token}"
|
10
|
+
when Hash
|
11
|
+
build_hash(type.to_s, token)
|
12
|
+
else
|
13
|
+
raise ArgumentError, "Can't build an Authorization #{type} header from #{token.inspect}"
|
23
14
|
end
|
15
|
+
end
|
24
16
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
values = []
|
32
|
-
hash.each do |key, value|
|
33
|
-
values << "#{key}=#{value.to_s.inspect}"
|
34
|
-
end
|
35
|
-
"#{type} #{values * comma}"
|
17
|
+
# Internal
|
18
|
+
def self.build_hash(type, hash)
|
19
|
+
comma = ", "
|
20
|
+
values = []
|
21
|
+
hash.each do |key, value|
|
22
|
+
values << "#{key}=#{value.to_s.inspect}"
|
36
23
|
end
|
24
|
+
"#{type} #{values * comma}"
|
25
|
+
end
|
37
26
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
@header_value = self.class.header(type, token)
|
43
|
-
super(app)
|
44
|
-
end
|
27
|
+
def initialize(app, type, token)
|
28
|
+
@header_value = self.class.header(type, token)
|
29
|
+
super(app)
|
30
|
+
end
|
45
31
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
@
|
32
|
+
# Public
|
33
|
+
def call(env)
|
34
|
+
unless env.request_headers[KEY]
|
35
|
+
env.request_headers[KEY] = @header_value
|
50
36
|
end
|
37
|
+
@app.call(env)
|
51
38
|
end
|
52
39
|
end
|
53
40
|
end
|
41
|
+
|
@@ -1,20 +1,13 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
1
|
require 'base64'
|
4
2
|
|
5
3
|
module Faraday
|
6
|
-
class Request
|
7
|
-
#
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
# @return [String] a Basic Authentication header line
|
13
|
-
def self.header(login, pass)
|
14
|
-
value = Base64.encode64([login, pass].join(':'))
|
15
|
-
value.delete!("\n")
|
16
|
-
super(:Basic, value)
|
17
|
-
end
|
4
|
+
class Request::BasicAuthentication < Request.load_middleware(:authorization)
|
5
|
+
# Public
|
6
|
+
def self.header(login, pass)
|
7
|
+
value = Base64.encode64([login, pass].join(':'))
|
8
|
+
value.gsub!("\n", '')
|
9
|
+
super(:Basic, value)
|
18
10
|
end
|
19
11
|
end
|
20
12
|
end
|
13
|
+
|
@@ -1,53 +1,35 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
1
|
module Faraday
|
4
|
-
class Request
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
class Options < Faraday::Options.new(:name, :instrumenter)
|
9
|
-
# @return [String]
|
10
|
-
def name
|
11
|
-
self[:name] ||= 'request.faraday'
|
12
|
-
end
|
13
|
-
|
14
|
-
# @return [Class]
|
15
|
-
def instrumenter
|
16
|
-
self[:instrumenter] ||= ActiveSupport::Notifications
|
17
|
-
end
|
2
|
+
class Request::Instrumentation < Faraday::Middleware
|
3
|
+
class Options < Faraday::Options.new(:name, :instrumenter)
|
4
|
+
def name
|
5
|
+
self[:name] ||= 'request.faraday'
|
18
6
|
end
|
19
7
|
|
20
|
-
|
21
|
-
|
22
|
-
# Measures time spent only for synchronous requests.
|
23
|
-
#
|
24
|
-
# @example Using ActiveSupport::Notifications to measure time spent
|
25
|
-
# for Faraday requests.
|
26
|
-
# ActiveSupport::Notifications
|
27
|
-
# .subscribe('request.faraday') do |name, starts, ends, _, env|
|
28
|
-
# url = env[:url]
|
29
|
-
# http_method = env[:method].to_s.upcase
|
30
|
-
# duration = ends - starts
|
31
|
-
# $stderr.puts '[%s] %s %s (%.3f s)' %
|
32
|
-
# [url.host, http_method, url.request_uri, duration]
|
33
|
-
# end
|
34
|
-
# @param app [#call]
|
35
|
-
# @param options [nil, Hash] Options hash
|
36
|
-
# @option options [String] :name ('request.faraday')
|
37
|
-
# Name of the instrumenter
|
38
|
-
# @option options [Class] :instrumenter (ActiveSupport::Notifications)
|
39
|
-
# Active Support instrumenter class.
|
40
|
-
def initialize(app, options = nil)
|
41
|
-
super(app)
|
42
|
-
@name, @instrumenter = Options.from(options)
|
43
|
-
.values_at(:name, :instrumenter)
|
8
|
+
def instrumenter
|
9
|
+
self[:instrumenter] ||= ActiveSupport::Notifications
|
44
10
|
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# Public: Instruments requests using Active Support.
|
14
|
+
#
|
15
|
+
# Measures time spent only for synchronous requests.
|
16
|
+
#
|
17
|
+
# Examples
|
18
|
+
#
|
19
|
+
# ActiveSupport::Notifications.subscribe('request.faraday') do |name, starts, ends, _, env|
|
20
|
+
# url = env[:url]
|
21
|
+
# http_method = env[:method].to_s.upcase
|
22
|
+
# duration = ends - starts
|
23
|
+
# $stderr.puts '[%s] %s %s (%.3f s)' % [url.host, http_method, url.request_uri, duration]
|
24
|
+
# end
|
25
|
+
def initialize(app, options = nil)
|
26
|
+
super(app)
|
27
|
+
@name, @instrumenter = Options.from(options).values_at(:name, :instrumenter)
|
28
|
+
end
|
45
29
|
|
46
|
-
|
47
|
-
|
48
|
-
@
|
49
|
-
@app.call(env)
|
50
|
-
end
|
30
|
+
def call(env)
|
31
|
+
@instrumenter.instrument(@name, env) do
|
32
|
+
@app.call(env)
|
51
33
|
end
|
52
34
|
end
|
53
35
|
end
|
@@ -1,97 +1,66 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require File.expand_path('url_encoded', __dir__)
|
1
|
+
require File.expand_path("../url_encoded", __FILE__)
|
4
2
|
require 'securerandom'
|
5
3
|
|
6
4
|
module Faraday
|
7
|
-
class Request
|
8
|
-
|
9
|
-
|
10
|
-
self.mime_type = 'multipart/form-data'
|
11
|
-
unless defined? DEFAULT_BOUNDARY_PREFIX
|
12
|
-
DEFAULT_BOUNDARY_PREFIX = '-----------RubyMultipartPost'
|
13
|
-
end
|
5
|
+
class Request::Multipart < Request::UrlEncoded
|
6
|
+
self.mime_type = 'multipart/form-data'.freeze
|
7
|
+
DEFAULT_BOUNDARY_PREFIX = "-----------RubyMultipartPost".freeze unless defined? DEFAULT_BOUNDARY_PREFIX
|
14
8
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
env.request.boundary ||= unique_boundary
|
21
|
-
env.request_headers[CONTENT_TYPE] +=
|
22
|
-
"; boundary=#{env.request.boundary}"
|
23
|
-
env.body = create_multipart(env, params)
|
24
|
-
end
|
25
|
-
@app.call env
|
9
|
+
def call(env)
|
10
|
+
match_content_type(env) do |params|
|
11
|
+
env.request.boundary ||= unique_boundary
|
12
|
+
env.request_headers[CONTENT_TYPE] += "; boundary=#{env.request.boundary}"
|
13
|
+
env.body = create_multipart(env, params)
|
26
14
|
end
|
15
|
+
@app.call env
|
16
|
+
end
|
27
17
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
end
|
18
|
+
def process_request?(env)
|
19
|
+
type = request_type(env)
|
20
|
+
env.body.respond_to?(:each_key) and !env.body.empty? and (
|
21
|
+
(type.empty? and has_multipart?(env.body)) or
|
22
|
+
type == self.class.mime_type
|
23
|
+
)
|
24
|
+
end
|
36
25
|
|
37
|
-
|
38
|
-
#
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
if obj.respond_to?(:each)
|
43
|
-
(obj.respond_to?(:values) ? obj.values : obj).each do |val|
|
44
|
-
return true if val.respond_to?(:content_type) || has_multipart?(val)
|
45
|
-
end
|
26
|
+
def has_multipart?(obj)
|
27
|
+
# string is an enum in 1.8, returning list of itself
|
28
|
+
if obj.respond_to?(:each) && !obj.is_a?(String)
|
29
|
+
(obj.respond_to?(:values) ? obj.values : obj).each do |val|
|
30
|
+
return true if (val.respond_to?(:content_type) || has_multipart?(val))
|
46
31
|
end
|
47
|
-
false
|
48
32
|
end
|
33
|
+
false
|
34
|
+
end
|
49
35
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
boundary
|
54
|
-
parts = process_params(params) do |key, value|
|
55
|
-
part(boundary, key, value)
|
56
|
-
end
|
57
|
-
parts << Faraday::Parts::EpiloguePart.new(boundary)
|
58
|
-
|
59
|
-
body = Faraday::CompositeReadIO.new(parts)
|
60
|
-
env.request_headers[Faraday::Env::ContentLength] = body.length.to_s
|
61
|
-
body
|
36
|
+
def create_multipart(env, params)
|
37
|
+
boundary = env.request.boundary
|
38
|
+
parts = process_params(params) do |key, value|
|
39
|
+
Faraday::Parts::Part.new(boundary, key, value)
|
62
40
|
end
|
41
|
+
parts << Faraday::Parts::EpiloguePart.new(boundary)
|
63
42
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
Faraday::Parts::Part.new(boundary, key, value)
|
69
|
-
end
|
70
|
-
end
|
43
|
+
body = Faraday::CompositeReadIO.new(parts)
|
44
|
+
env.request_headers[Faraday::Env::ContentLength] = body.length.to_s
|
45
|
+
return body
|
46
|
+
end
|
71
47
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
end
|
48
|
+
def unique_boundary
|
49
|
+
"#{DEFAULT_BOUNDARY_PREFIX}-#{SecureRandom.hex}"
|
50
|
+
end
|
76
51
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
def process_params(params, prefix = nil, pieces = nil, &block)
|
81
|
-
params.inject(pieces || []) do |all, (key, value)|
|
82
|
-
key = "#{prefix}[#{key}]" if prefix
|
52
|
+
def process_params(params, prefix = nil, pieces = nil, &block)
|
53
|
+
params.inject(pieces || []) do |all, (key, value)|
|
54
|
+
key = "#{prefix}[#{key}]" if prefix
|
83
55
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
all << block.call(key, value)
|
93
|
-
# rubocop:enable Performance/RedundantBlockCall
|
94
|
-
end
|
56
|
+
case value
|
57
|
+
when Array
|
58
|
+
values = value.inject([]) { |a,v| a << [nil, v] }
|
59
|
+
process_params(values, key, all, &block)
|
60
|
+
when Hash
|
61
|
+
process_params(value, key, all, &block)
|
62
|
+
else
|
63
|
+
all << block.call(key, value)
|
95
64
|
end
|
96
65
|
end
|
97
66
|
end
|