faraday 1.10.4 → 2.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.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +198 -4
  3. data/LICENSE.md +1 -1
  4. data/README.md +34 -20
  5. data/Rakefile +6 -1
  6. data/examples/client_spec.rb +41 -19
  7. data/examples/client_test.rb +48 -22
  8. data/lib/faraday/adapter/test.rb +62 -13
  9. data/lib/faraday/adapter.rb +6 -10
  10. data/lib/faraday/connection.rb +72 -150
  11. data/lib/faraday/encoders/flat_params_encoder.rb +2 -2
  12. data/lib/faraday/encoders/nested_params_encoder.rb +14 -7
  13. data/lib/faraday/error.rb +66 -10
  14. data/lib/faraday/logging/formatter.rb +30 -17
  15. data/lib/faraday/middleware.rb +43 -2
  16. data/lib/faraday/middleware_registry.rb +17 -63
  17. data/lib/faraday/options/connection_options.rb +7 -6
  18. data/lib/faraday/options/env.rb +85 -62
  19. data/lib/faraday/options/proxy_options.rb +11 -5
  20. data/lib/faraday/options/request_options.rb +7 -6
  21. data/lib/faraday/options/ssl_options.rb +62 -45
  22. data/lib/faraday/options.rb +7 -6
  23. data/lib/faraday/rack_builder.rb +44 -45
  24. data/lib/faraday/request/authorization.rb +33 -41
  25. data/lib/faraday/request/instrumentation.rb +5 -1
  26. data/lib/faraday/request/json.rb +18 -3
  27. data/lib/faraday/request/url_encoded.rb +5 -1
  28. data/lib/faraday/request.rb +15 -30
  29. data/lib/faraday/response/json.rb +25 -5
  30. data/lib/faraday/response/logger.rb +11 -3
  31. data/lib/faraday/response/raise_error.rb +45 -18
  32. data/lib/faraday/response.rb +14 -22
  33. data/lib/faraday/utils/headers.rb +15 -4
  34. data/lib/faraday/utils.rb +11 -7
  35. data/lib/faraday/version.rb +1 -1
  36. data/lib/faraday.rb +10 -45
  37. data/spec/faraday/adapter/test_spec.rb +65 -0
  38. data/spec/faraday/connection_spec.rb +165 -93
  39. data/spec/faraday/error_spec.rb +122 -7
  40. data/spec/faraday/middleware_registry_spec.rb +31 -0
  41. data/spec/faraday/middleware_spec.rb +161 -0
  42. data/spec/faraday/options/env_spec.rb +8 -2
  43. data/spec/faraday/options/options_spec.rb +1 -1
  44. data/spec/faraday/options/proxy_options_spec.rb +35 -0
  45. data/spec/faraday/params_encoders/nested_spec.rb +10 -1
  46. data/spec/faraday/rack_builder_spec.rb +26 -54
  47. data/spec/faraday/request/authorization_spec.rb +50 -28
  48. data/spec/faraday/request/instrumentation_spec.rb +5 -7
  49. data/spec/faraday/request/json_spec.rb +88 -0
  50. data/spec/faraday/request/url_encoded_spec.rb +12 -2
  51. data/spec/faraday/request_spec.rb +5 -15
  52. data/spec/faraday/response/json_spec.rb +93 -6
  53. data/spec/faraday/response/logger_spec.rb +83 -4
  54. data/spec/faraday/response/raise_error_spec.rb +133 -16
  55. data/spec/faraday/response_spec.rb +10 -1
  56. data/spec/faraday/utils/headers_spec.rb +31 -4
  57. data/spec/faraday/utils_spec.rb +65 -1
  58. data/spec/faraday_spec.rb +10 -4
  59. data/spec/spec_helper.rb +5 -6
  60. data/spec/support/fake_safe_buffer.rb +1 -1
  61. data/spec/support/faraday_middleware_subclasses.rb +18 -0
  62. data/spec/support/helper_methods.rb +0 -37
  63. data/spec/support/shared_examples/adapter.rb +2 -2
  64. data/spec/support/shared_examples/request_method.rb +22 -21
  65. metadata +24 -149
  66. data/lib/faraday/adapter/typhoeus.rb +0 -15
  67. data/lib/faraday/autoload.rb +0 -89
  68. data/lib/faraday/dependency_loader.rb +0 -39
  69. data/lib/faraday/deprecate.rb +0 -110
  70. data/lib/faraday/request/basic_authentication.rb +0 -20
  71. data/lib/faraday/request/token_authentication.rb +0 -20
  72. data/spec/faraday/adapter/em_http_spec.rb +0 -49
  73. data/spec/faraday/adapter/em_synchrony_spec.rb +0 -18
  74. data/spec/faraday/adapter/excon_spec.rb +0 -49
  75. data/spec/faraday/adapter/httpclient_spec.rb +0 -73
  76. data/spec/faraday/adapter/net_http_spec.rb +0 -64
  77. data/spec/faraday/adapter/patron_spec.rb +0 -18
  78. data/spec/faraday/adapter/rack_spec.rb +0 -8
  79. data/spec/faraday/adapter/typhoeus_spec.rb +0 -7
  80. data/spec/faraday/composite_read_io_spec.rb +0 -80
  81. data/spec/faraday/deprecate_spec.rb +0 -147
  82. data/spec/faraday/response/middleware_spec.rb +0 -68
  83. data/spec/support/webmock_rack_app.rb +0 -68
@@ -62,11 +62,17 @@ module Faraday
62
62
  end
63
63
 
64
64
  def encode_array(parent, value)
65
- new_parent = "#{parent}%5B%5D"
66
- return new_parent if value.empty?
65
+ return "#{parent}%5B%5D" if value.empty?
67
66
 
68
67
  buffer = +''
69
- value.each { |val| buffer << "#{encode_pair(new_parent, val)}&" }
68
+ value.each_with_index do |val, index|
69
+ new_parent = if @array_indices
70
+ "#{parent}%5B#{index}%5D"
71
+ else
72
+ "#{parent}%5B%5D"
73
+ end
74
+ buffer << "#{encode_pair(new_parent, val)}&"
75
+ end
70
76
  buffer.chop
71
77
  end
72
78
  end
@@ -96,13 +102,13 @@ module Faraday
96
102
 
97
103
  protected
98
104
 
99
- SUBKEYS_REGEX = /[^\[\]]+(?:\]?\[\])?/.freeze
105
+ SUBKEYS_REGEX = /[^\[\]]+(?:\]?\[\])?/
100
106
 
101
107
  def decode_pair(key, value, context)
102
108
  subkeys = key.scan(SUBKEYS_REGEX)
103
109
  subkeys.each_with_index do |subkey, i|
104
110
  is_array = subkey =~ /[\[\]]+\Z/
105
- subkey = $` if is_array
111
+ subkey = Regexp.last_match.pre_match if is_array
106
112
  last_subkey = i == subkeys.length - 1
107
113
 
108
114
  context = prepare_context(context, subkey, is_array, last_subkey)
@@ -124,7 +130,7 @@ module Faraday
124
130
  value_type = is_array ? Array : Hash
125
131
  if context[subkey] && !context[subkey].is_a?(value_type)
126
132
  raise TypeError, "expected #{value_type.name} " \
127
- "(got #{context[subkey].class.name}) for param `#{subkey}'"
133
+ "(got #{context[subkey].class.name}) for param `#{subkey}'"
128
134
  end
129
135
 
130
136
  context[subkey] ||= value_type.new
@@ -161,7 +167,7 @@ module Faraday
161
167
  # for your requests.
162
168
  module NestedParamsEncoder
163
169
  class << self
164
- attr_accessor :sort_params
170
+ attr_accessor :sort_params, :array_indices
165
171
 
166
172
  extend Forwardable
167
173
  def_delegators :'Faraday::Utils', :escape, :unescape
@@ -169,6 +175,7 @@ module Faraday
169
175
 
170
176
  # Useful default for OAuth and caching.
171
177
  @sort_params = true
178
+ @array_indices = false
172
179
 
173
180
  extend EncodeMethods
174
181
  extend DecodeMethods
data/lib/faraday/error.rb CHANGED
@@ -6,7 +6,7 @@ module Faraday
6
6
  class Error < StandardError
7
7
  attr_reader :response, :wrapped_exception
8
8
 
9
- def initialize(exc, response = nil)
9
+ def initialize(exc = nil, response = nil)
10
10
  @wrapped_exception = nil unless defined?(@wrapped_exception)
11
11
  @response = nil unless defined?(@response)
12
12
  super(exc_msg_and_response!(exc, response))
@@ -29,15 +29,21 @@ module Faraday
29
29
  end
30
30
 
31
31
  def response_status
32
- @response[:status] if @response
32
+ return unless @response
33
+
34
+ @response.is_a?(Faraday::Response) ? @response.status : @response[:status]
33
35
  end
34
36
 
35
37
  def response_headers
36
- @response[:headers] if @response
38
+ return unless @response
39
+
40
+ @response.is_a?(Faraday::Response) ? @response.headers : @response[:headers]
37
41
  end
38
42
 
39
43
  def response_body
40
- @response[:body] if @response
44
+ return unless @response
45
+
46
+ @response.is_a?(Faraday::Response) ? @response.body : @response[:body]
41
47
  end
42
48
 
43
49
  protected
@@ -52,6 +58,7 @@ module Faraday
52
58
  # :body - Optional string HTTP response body.
53
59
  # :request - Hash
54
60
  # :method - Symbol with the request HTTP method.
61
+ # :url - URI object with the url requested.
55
62
  # :url_path - String with the url path requested.
56
63
  # :params - String key/value hash of query params
57
64
  # present in the request.
@@ -72,12 +79,46 @@ module Faraday
72
79
 
73
80
  # Pulls out potential parent exception and response hash.
74
81
  def exc_msg_and_response(exc, response = nil)
75
- return [exc, exc.message, response] if exc.respond_to?(:backtrace)
82
+ case exc
83
+ when Exception
84
+ [exc, exc.message, response]
85
+ when Hash
86
+ [nil, build_error_message_from_hash(exc), exc]
87
+ when Faraday::Env
88
+ [nil, build_error_message_from_env(exc), exc]
89
+ else
90
+ [nil, exc.to_s, response]
91
+ end
92
+ end
93
+
94
+ private
95
+
96
+ def build_error_message_from_hash(hash)
97
+ # Be defensive with external Hash objects - they might be missing keys
98
+ status = hash.fetch(:status, nil)
99
+ request = hash.fetch(:request, nil)
100
+
101
+ return fallback_error_message(status) if request.nil?
102
+
103
+ method = request.fetch(:method, nil)
104
+ url = request.fetch(:url, nil)
105
+ build_status_error_message(status, method, url)
106
+ end
107
+
108
+ def build_error_message_from_env(env)
109
+ # Faraday::Env is internal - we can make reasonable assumptions about its structure
110
+ build_status_error_message(env.status, env.method, env.url)
111
+ end
76
112
 
77
- return [nil, "the server responded with status #{exc[:status]}", exc] \
78
- if exc.respond_to?(:each_key)
113
+ def build_status_error_message(status, method, url)
114
+ method_str = method ? method.to_s.upcase : ''
115
+ url_str = url ? url.to_s : ''
116
+ "the server responded with status #{status} for #{method_str} #{url_str}"
117
+ end
79
118
 
80
- [nil, exc.to_s, response]
119
+ def fallback_error_message(status)
120
+ "the server responded with status #{status} - method and url are not available " \
121
+ 'due to include_request: false on Faraday::Response::RaiseError middleware'
81
122
  end
82
123
  end
83
124
 
@@ -105,12 +146,23 @@ module Faraday
105
146
  class ProxyAuthError < ClientError
106
147
  end
107
148
 
149
+ # Raised by Faraday::Response::RaiseError in case of a 408 response.
150
+ class RequestTimeoutError < ClientError
151
+ end
152
+
108
153
  # Raised by Faraday::Response::RaiseError in case of a 409 response.
109
154
  class ConflictError < ClientError
110
155
  end
111
156
 
112
157
  # Raised by Faraday::Response::RaiseError in case of a 422 response.
113
- class UnprocessableEntityError < ClientError
158
+ class UnprocessableContentError < ClientError
159
+ end
160
+
161
+ # Used to provide compatibility with legacy error name.
162
+ UnprocessableEntityError = UnprocessableContentError
163
+
164
+ # Raised by Faraday::Response::RaiseError in case of a 429 response.
165
+ class TooManyRequestsError < ClientError
114
166
  end
115
167
 
116
168
  # Faraday server error class. Represents 5xx status responses.
@@ -140,7 +192,11 @@ module Faraday
140
192
  class SSLError < Error
141
193
  end
142
194
 
143
- # Raised by FaradayMiddleware::ResponseMiddleware
195
+ # Raised by middlewares that parse the response, like the JSON response middleware.
144
196
  class ParsingError < Error
145
197
  end
198
+
199
+ # Raised by Faraday::Middleware and subclasses when invalid default_options are used
200
+ class InitializationError < Error
201
+ end
146
202
  end
@@ -1,41 +1,54 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'pp'
3
+ require 'pp' # This require is necessary for Hash#pretty_inspect to work, do not remove it, people rely on it.
4
+
4
5
  module Faraday
5
6
  module Logging
6
7
  # Serves as an integration point to customize logging
7
8
  class Formatter
8
9
  extend Forwardable
9
10
 
10
- DEFAULT_OPTIONS = { headers: true, bodies: false,
11
+ DEFAULT_OPTIONS = { headers: true, bodies: false, errors: false,
11
12
  log_level: :info }.freeze
12
13
 
13
14
  def initialize(logger:, options:)
14
15
  @logger = logger
15
- @filter = []
16
16
  @options = DEFAULT_OPTIONS.merge(options)
17
+ unless %i[debug info warn error fatal].include?(@options[:log_level])
18
+ @options[:log_level] = :info
19
+ end
20
+ @filter = []
17
21
  end
18
22
 
19
23
  def_delegators :@logger, :debug, :info, :warn, :error, :fatal
20
24
 
21
25
  def request(env)
22
- request_log = proc do
23
- "#{env.method.upcase} #{apply_filters(env.url.to_s)}"
26
+ public_send(log_level) do
27
+ "request: #{env.method.upcase} #{apply_filters(env.url.to_s)}"
24
28
  end
25
- public_send(log_level, 'request', &request_log)
26
29
 
27
30
  log_headers('request', env.request_headers) if log_headers?(:request)
28
31
  log_body('request', env[:body]) if env[:body] && log_body?(:request)
29
32
  end
30
33
 
31
34
  def response(env)
32
- status = proc { "Status #{env.status}" }
33
- public_send(log_level, 'response', &status)
35
+ public_send(log_level) { "response: Status #{env.status}" }
34
36
 
35
37
  log_headers('response', env.response_headers) if log_headers?(:response)
36
38
  log_body('response', env[:body]) if env[:body] && log_body?(:response)
37
39
  end
38
40
 
41
+ def exception(exc)
42
+ return unless log_errors?
43
+
44
+ public_send(log_level) { "error: #{exc.full_message}" }
45
+
46
+ log_headers('error', exc.response_headers) if exc.respond_to?(:response_headers) && log_headers?(:error)
47
+ return unless exc.respond_to?(:response_body) && exc.response_body && log_body?(:error)
48
+
49
+ log_body('error', exc.response_body)
50
+ end
51
+
39
52
  def filter(filter_word, filter_replacement)
40
53
  @filter.push([filter_word, filter_replacement])
41
54
  end
@@ -43,12 +56,14 @@ module Faraday
43
56
  private
44
57
 
45
58
  def dump_headers(headers)
59
+ return if headers.nil?
60
+
46
61
  headers.map { |k, v| "#{k}: #{v.inspect}" }.join("\n")
47
62
  end
48
63
 
49
64
  def dump_body(body)
50
65
  if body.respond_to?(:to_str)
51
- body.to_str
66
+ body.to_str.encode(Encoding::UTF_8, undef: :replace, invalid: :replace)
52
67
  else
53
68
  pretty_inspect(body)
54
69
  end
@@ -76,6 +91,10 @@ module Faraday
76
91
  end
77
92
  end
78
93
 
94
+ def log_errors?
95
+ @options[:errors]
96
+ end
97
+
79
98
  def apply_filters(output)
80
99
  @filter.each do |pattern, replacement|
81
100
  output = output.to_s.gsub(pattern, replacement)
@@ -84,21 +103,15 @@ module Faraday
84
103
  end
85
104
 
86
105
  def log_level
87
- unless %i[debug info warn error fatal].include?(@options[:log_level])
88
- return :info
89
- end
90
-
91
106
  @options[:log_level]
92
107
  end
93
108
 
94
109
  def log_headers(type, headers)
95
- headers_log = proc { apply_filters(dump_headers(headers)) }
96
- public_send(log_level, type, &headers_log)
110
+ public_send(log_level) { "#{type}: #{apply_filters(dump_headers(headers))}" }
97
111
  end
98
112
 
99
113
  def log_body(type, body)
100
- body_log = proc { apply_filters(dump_body(body)) }
101
- public_send(log_level, type, &body_log)
114
+ public_send(log_level) { "#{type}: #{apply_filters(dump_body(body))}" }
102
115
  end
103
116
  end
104
117
  end
@@ -1,16 +1,54 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'monitor'
4
+
3
5
  module Faraday
4
6
  # Middleware is the basic base class of any Faraday middleware.
5
7
  class Middleware
6
8
  extend MiddlewareRegistry
7
- extend DependencyLoader
8
9
 
9
10
  attr_reader :app, :options
10
11
 
12
+ DEFAULT_OPTIONS = {}.freeze
13
+ LOCK = Mutex.new
14
+
11
15
  def initialize(app = nil, options = {})
12
16
  @app = app
13
- @options = options
17
+ @options = self.class.default_options.merge(options)
18
+ end
19
+
20
+ class << self
21
+ # Faraday::Middleware::default_options= allows user to set default options at the Faraday::Middleware
22
+ # class level.
23
+ #
24
+ # @example Set the Faraday::Response::RaiseError option, `include_request` to `false`
25
+ # my_app/config/initializers/my_faraday_middleware.rb
26
+ #
27
+ # Faraday::Response::RaiseError.default_options = { include_request: false }
28
+ #
29
+ def default_options=(options = {})
30
+ validate_default_options(options)
31
+ LOCK.synchronize do
32
+ @default_options = default_options.merge(options)
33
+ end
34
+ end
35
+
36
+ # default_options attr_reader that initializes class instance variable
37
+ # with the values of any Faraday::Middleware defaults, and merges with
38
+ # subclass defaults
39
+ def default_options
40
+ @default_options ||= DEFAULT_OPTIONS.merge(self::DEFAULT_OPTIONS)
41
+ end
42
+
43
+ private
44
+
45
+ def validate_default_options(options)
46
+ invalid_keys = options.keys.reject { |opt| self::DEFAULT_OPTIONS.key?(opt) }
47
+ return unless invalid_keys.any?
48
+
49
+ raise(Faraday::InitializationError,
50
+ "Invalid options provided. Keys not found in #{self}::DEFAULT_OPTIONS: #{invalid_keys.join(', ')}")
51
+ end
14
52
  end
15
53
 
16
54
  def call(env)
@@ -18,6 +56,9 @@ module Faraday
18
56
  app.call(env).on_complete do |environment|
19
57
  on_complete(environment) if respond_to?(:on_complete)
20
58
  end
59
+ rescue StandardError => e
60
+ on_error(e) if respond_to?(:on_error)
61
+ raise
21
62
  end
22
63
 
23
64
  def close
@@ -6,59 +6,26 @@ module Faraday
6
6
  # Adds the ability for other modules to register and lookup
7
7
  # middleware classes.
8
8
  module MiddlewareRegistry
9
+ def registered_middleware
10
+ @registered_middleware ||= {}
11
+ end
12
+
9
13
  # Register middleware class(es) on the current module.
10
14
  #
11
- # @param autoload_path [String] Middleware autoload path
12
- # @param mapping [Hash{
13
- # Symbol => Module,
14
- # Symbol => Array<Module, Symbol, String>,
15
- # }] Middleware mapping from a lookup symbol to a reference to the
16
- # middleware.
17
- # Classes can be expressed as:
18
- # - a fully qualified constant
19
- # - a Symbol
20
- # - a Proc that will be lazily called to return the former
21
- # - an array is given, its first element is the constant or symbol,
22
- # and its second is a file to `require`.
15
+ # @param mappings [Hash] Middleware mappings from a lookup symbol to a middleware class.
23
16
  # @return [void]
24
17
  #
25
18
  # @example Lookup by a constant
26
19
  #
27
20
  # module Faraday
28
- # class Whatever
21
+ # class Whatever < Middleware
29
22
  # # Middleware looked up by :foo returns Faraday::Whatever::Foo.
30
- # register_middleware foo: Foo
31
- # end
32
- # end
33
- #
34
- # @example Lookup by a symbol
35
- #
36
- # module Faraday
37
- # class Whatever
38
- # # Middleware looked up by :bar returns
39
- # # Faraday::Whatever.const_get(:Bar)
40
- # register_middleware bar: :Bar
41
- # end
42
- # end
43
- #
44
- # @example Lookup by a symbol and string in an array
45
- #
46
- # module Faraday
47
- # class Whatever
48
- # # Middleware looked up by :baz requires 'baz' and returns
49
- # # Faraday::Whatever.const_get(:Baz)
50
- # register_middleware baz: [:Baz, 'baz']
23
+ # register_middleware(foo: Whatever)
51
24
  # end
52
25
  # end
53
- #
54
- def register_middleware(autoload_path = nil, mapping = nil)
55
- if mapping.nil?
56
- mapping = autoload_path
57
- autoload_path = nil
58
- end
26
+ def register_middleware(**mappings)
59
27
  middleware_mutex do
60
- @middleware_autoload_path = autoload_path if autoload_path
61
- (@registered_middleware ||= {}).update(mapping)
28
+ registered_middleware.update(mappings)
62
29
  end
63
30
  end
64
31
 
@@ -66,7 +33,7 @@ module Faraday
66
33
  #
67
34
  # @param key [Symbol] key for the registered middleware.
68
35
  def unregister_middleware(key)
69
- @registered_middleware.delete(key)
36
+ registered_middleware.delete(key)
70
37
  end
71
38
 
72
39
  # Lookup middleware class with a registered Symbol shortcut.
@@ -78,30 +45,27 @@ module Faraday
78
45
  # @example
79
46
  #
80
47
  # module Faraday
81
- # class Whatever
82
- # register_middleware foo: Foo
48
+ # class Whatever < Middleware
49
+ # register_middleware(foo: Whatever)
83
50
  # end
84
51
  # end
85
52
  #
86
- # Faraday::Whatever.lookup_middleware(:foo)
87
- # # => Faraday::Whatever::Foo
88
- #
53
+ # Faraday::Middleware.lookup_middleware(:foo)
54
+ # # => Faraday::Whatever
89
55
  def lookup_middleware(key)
90
56
  load_middleware(key) ||
91
57
  raise(Faraday::Error, "#{key.inspect} is not registered on #{self}")
92
58
  end
93
59
 
60
+ private
61
+
94
62
  def middleware_mutex(&block)
95
63
  @middleware_mutex ||= Monitor.new
96
64
  @middleware_mutex.synchronize(&block)
97
65
  end
98
66
 
99
- def fetch_middleware(key)
100
- defined?(@registered_middleware) && @registered_middleware[key]
101
- end
102
-
103
67
  def load_middleware(key)
104
- value = fetch_middleware(key)
68
+ value = registered_middleware[key]
105
69
  case value
106
70
  when Module
107
71
  value
@@ -113,16 +77,6 @@ module Faraday
113
77
  middleware_mutex do
114
78
  @registered_middleware[key] = value.call
115
79
  end
116
- when Array
117
- middleware_mutex do
118
- const, path = value
119
- if (root = @middleware_autoload_path)
120
- path = "#{root}/#{path}"
121
- end
122
- require(path)
123
- @registered_middleware[key] = const
124
- end
125
- load_middleware(key)
126
80
  end
127
81
  end
128
82
  end
@@ -1,12 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Faraday
4
- # ConnectionOptions contains the configurable properties for a Faraday
5
- # connection object.
6
- class ConnectionOptions < Options.new(:request, :proxy, :ssl, :builder, :url,
7
- :parallel_manager, :params, :headers,
8
- :builder_class)
9
-
4
+ # @!parse
5
+ # # ConnectionOptions contains the configurable properties for a Faraday
6
+ # # connection object.
7
+ # class ConnectionOptions < Options; end
8
+ ConnectionOptions = Options.new(:request, :proxy, :ssl, :builder, :url,
9
+ :parallel_manager, :params, :headers,
10
+ :builder_class) do
10
11
  options request: RequestOptions, ssl: SSLOptions
11
12
 
12
13
  memoized(:request) { self.class.options_for(:request).new }