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.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.md +1 -1
  3. data/README.md +347 -18
  4. data/lib/faraday.rb +175 -93
  5. data/lib/faraday/adapter.rb +22 -36
  6. data/lib/faraday/adapter/em_http.rb +99 -142
  7. data/lib/faraday/adapter/em_http_ssl_patch.rb +17 -23
  8. data/lib/faraday/adapter/em_synchrony.rb +60 -104
  9. data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +15 -18
  10. data/lib/faraday/adapter/excon.rb +55 -100
  11. data/lib/faraday/adapter/httpclient.rb +39 -61
  12. data/lib/faraday/adapter/net_http.rb +51 -104
  13. data/lib/faraday/adapter/net_http_persistent.rb +27 -48
  14. data/lib/faraday/adapter/patron.rb +35 -54
  15. data/lib/faraday/adapter/rack.rb +12 -28
  16. data/lib/faraday/adapter/test.rb +53 -86
  17. data/lib/faraday/adapter/typhoeus.rb +1 -4
  18. data/lib/faraday/autoload.rb +36 -47
  19. data/lib/faraday/connection.rb +179 -321
  20. data/lib/faraday/error.rb +32 -80
  21. data/lib/faraday/middleware.rb +28 -4
  22. data/lib/faraday/options.rb +186 -35
  23. data/lib/faraday/parameters.rb +197 -4
  24. data/lib/faraday/rack_builder.rb +56 -67
  25. data/lib/faraday/request.rb +36 -68
  26. data/lib/faraday/request/authorization.rb +30 -42
  27. data/lib/faraday/request/basic_authentication.rb +7 -14
  28. data/lib/faraday/request/instrumentation.rb +27 -45
  29. data/lib/faraday/request/multipart.rb +48 -79
  30. data/lib/faraday/request/retry.rb +170 -197
  31. data/lib/faraday/request/token_authentication.rb +10 -15
  32. data/lib/faraday/request/url_encoded.rb +23 -41
  33. data/lib/faraday/response.rb +16 -23
  34. data/lib/faraday/response/logger.rb +69 -22
  35. data/lib/faraday/response/raise_error.rb +14 -36
  36. data/lib/faraday/upload_io.rb +67 -0
  37. data/lib/faraday/utils.rb +245 -28
  38. metadata +5 -22
  39. data/lib/faraday/adapter_registry.rb +0 -28
  40. data/lib/faraday/dependency_loader.rb +0 -37
  41. data/lib/faraday/deprecated_class.rb +0 -28
  42. data/lib/faraday/encoders/flat_params_encoder.rb +0 -94
  43. data/lib/faraday/encoders/nested_params_encoder.rb +0 -171
  44. data/lib/faraday/file_part.rb +0 -128
  45. data/lib/faraday/logging/formatter.rb +0 -92
  46. data/lib/faraday/middleware_registry.rb +0 -129
  47. data/lib/faraday/options/connection_options.rb +0 -22
  48. data/lib/faraday/options/env.rb +0 -181
  49. data/lib/faraday/options/proxy_options.rb +0 -28
  50. data/lib/faraday/options/request_options.rb +0 -21
  51. data/lib/faraday/options/ssl_options.rb +0 -59
  52. data/lib/faraday/param_part.rb +0 -53
  53. data/lib/faraday/utils/headers.rb +0 -139
  54. data/lib/faraday/utils/params_hash.rb +0 -61
  55. data/spec/external_adapters/faraday_specs_setup.rb +0 -14
@@ -1,9 +1,6 @@
1
- # frozen_string_literal: true
2
-
3
1
  module Faraday
4
- # Used to setup URLs, params, headers, and the request body in a sane manner.
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', __dir__),
35
- url_encoded: [:UrlEncoded, 'url_encoded'],
36
- multipart: [:Multipart, 'multipart'],
37
- retry: [:Retry, 'retry'],
38
- authorization: [:Authorization, 'authorization'],
39
- basic_auth: [
40
- :BasicAuthentication,
41
- 'basic_authentication'
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 (query = path.query)
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: method,
120
- body: body,
121
- headers: headers,
122
- path: path,
123
- params: params,
124
- options: 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
- # @return [Env] the Env for this Request
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
- options, headers, connection.ssl, connection.parallel_manager)
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
- # Request middleware for the Authorization HTTP header
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
- # @param type [String, Symbol]
10
- # @param token [String, Symbol, Hash]
11
- # @return [String] a header value
12
- def self.header(type, token)
13
- case token
14
- when String, Symbol
15
- "#{type} #{token}"
16
- when Hash
17
- build_hash(type.to_s, token)
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
- # @param type [String]
26
- # @param hash [Hash]
27
- # @return [String] type followed by comma-separated key=value pairs
28
- # @api private
29
- def self.build_hash(type, hash)
30
- comma = ', '
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
- # @param app [#call]
39
- # @param type [String, Symbol] Type of Authorization
40
- # @param token [String, Symbol, Hash] Token value for the Authorization
41
- def initialize(app, type, token)
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
- # @param env [Faraday::Env]
47
- def call(env)
48
- env.request_headers[KEY] = @header_value unless env.request_headers[KEY]
49
- @app.call(env)
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
- # Authorization middleware for Basic Authentication.
8
- class BasicAuthentication < load_middleware(:authorization)
9
- # @param login [String]
10
- # @param pass [String]
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
- # Middleware for instrumenting Requests.
6
- class Instrumentation < Faraday::Middleware
7
- # Options class used in Request::Instrumentation class.
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
- # Instruments requests using Active Support.
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
- # @param env [Faraday::Env]
47
- def call(env)
48
- @instrumenter.instrument(@name, env) do
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
- # frozen_string_literal: true
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
- # Middleware for supporting multi-part requests.
9
- class Multipart < UrlEncoded
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
- # Checks for files in the payload, otherwise leaves everything untouched.
16
- #
17
- # @param env [Faraday::Env]
18
- def call(env)
19
- match_content_type(env) do |params|
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
- # @param env [Faraday::Env]
29
- def process_request?(env)
30
- type = request_type(env)
31
- env.body.respond_to?(:each_key) && !env.body.empty? && (
32
- (type.empty? && has_multipart?(env.body)) ||
33
- (type == self.class.mime_type)
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
- # Returns true if obj is an enumerable with values that are multipart.
38
- #
39
- # @param obj [Object]
40
- # @return [Boolean]
41
- def has_multipart?(obj) # rubocop:disable Naming/PredicateName
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
- # @param env [Faraday::Env]
51
- # @param params [Hash]
52
- def create_multipart(env, params)
53
- boundary = env.request.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
- def part(boundary, key, value)
65
- if value.respond_to?(:to_part)
66
- value.to_part(boundary, key)
67
- else
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
- # @return [String]
73
- def unique_boundary
74
- "#{DEFAULT_BOUNDARY_PREFIX}-#{SecureRandom.hex}"
75
- end
48
+ def unique_boundary
49
+ "#{DEFAULT_BOUNDARY_PREFIX}-#{SecureRandom.hex}"
50
+ end
76
51
 
77
- # @param params [Hash]
78
- # @param prefix [String]
79
- # @param pieces [Array]
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
- case value
85
- when Array
86
- values = value.inject([]) { |a, v| a << [nil, v] }
87
- process_params(values, key, all, &block)
88
- when Hash
89
- process_params(value, key, all, &block)
90
- else
91
- # rubocop:disable Performance/RedundantBlockCall
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