faraday 0.16.0 → 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 (54) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.md +1 -1
  3. data/README.md +347 -18
  4. data/lib/faraday/adapter/em_http.rb +99 -142
  5. data/lib/faraday/adapter/em_http_ssl_patch.rb +17 -23
  6. data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +15 -18
  7. data/lib/faraday/adapter/em_synchrony.rb +60 -104
  8. data/lib/faraday/adapter/excon.rb +55 -100
  9. data/lib/faraday/adapter/httpclient.rb +39 -61
  10. data/lib/faraday/adapter/net_http.rb +51 -104
  11. data/lib/faraday/adapter/net_http_persistent.rb +27 -48
  12. data/lib/faraday/adapter/patron.rb +35 -54
  13. data/lib/faraday/adapter/rack.rb +12 -28
  14. data/lib/faraday/adapter/test.rb +53 -86
  15. data/lib/faraday/adapter/typhoeus.rb +1 -4
  16. data/lib/faraday/adapter.rb +22 -36
  17. data/lib/faraday/autoload.rb +36 -47
  18. data/lib/faraday/connection.rb +179 -321
  19. data/lib/faraday/error.rb +33 -67
  20. data/lib/faraday/middleware.rb +28 -4
  21. data/lib/faraday/options.rb +186 -35
  22. data/lib/faraday/parameters.rb +197 -4
  23. data/lib/faraday/rack_builder.rb +56 -67
  24. data/lib/faraday/request/authorization.rb +30 -42
  25. data/lib/faraday/request/basic_authentication.rb +7 -14
  26. data/lib/faraday/request/instrumentation.rb +27 -45
  27. data/lib/faraday/request/multipart.rb +48 -79
  28. data/lib/faraday/request/retry.rb +170 -197
  29. data/lib/faraday/request/token_authentication.rb +10 -15
  30. data/lib/faraday/request/url_encoded.rb +23 -41
  31. data/lib/faraday/request.rb +36 -68
  32. data/lib/faraday/response/logger.rb +69 -22
  33. data/lib/faraday/response/raise_error.rb +14 -36
  34. data/lib/faraday/response.rb +16 -23
  35. data/lib/faraday/upload_io.rb +67 -0
  36. data/lib/faraday/utils.rb +245 -28
  37. data/lib/faraday.rb +175 -93
  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/encoders/flat_params_encoder.rb +0 -94
  42. data/lib/faraday/encoders/nested_params_encoder.rb +0 -171
  43. data/lib/faraday/file_part.rb +0 -128
  44. data/lib/faraday/logging/formatter.rb +0 -92
  45. data/lib/faraday/middleware_registry.rb +0 -129
  46. data/lib/faraday/options/connection_options.rb +0 -22
  47. data/lib/faraday/options/env.rb +0 -181
  48. data/lib/faraday/options/proxy_options.rb +0 -28
  49. data/lib/faraday/options/request_options.rb +0 -21
  50. data/lib/faraday/options/ssl_options.rb +0 -59
  51. data/lib/faraday/param_part.rb +0 -53
  52. data/lib/faraday/utils/headers.rb +0 -139
  53. data/lib/faraday/utils/params_hash.rb +0 -61
  54. data/spec/external_adapters/faraday_specs_setup.rb +0 -14
data/lib/faraday/utils.rb CHANGED
@@ -1,12 +1,193 @@
1
- # frozen_string_literal: true
2
-
3
- require 'faraday/utils/headers'
4
- require 'faraday/utils/params_hash'
1
+ require 'thread'
5
2
 
6
3
  module Faraday
7
- # Utils contains various static helper methods.
8
4
  module Utils
9
- module_function
5
+ extend self
6
+
7
+ # Adapted from Rack::Utils::HeaderHash
8
+ class Headers < ::Hash
9
+ def self.from(value)
10
+ new(value)
11
+ end
12
+
13
+ def self.allocate
14
+ new_self = super
15
+ new_self.initialize_names
16
+ new_self
17
+ end
18
+
19
+ def initialize(hash = nil)
20
+ super()
21
+ @names = {}
22
+ self.update(hash || {})
23
+ end
24
+
25
+ def initialize_names
26
+ @names = {}
27
+ end
28
+
29
+ # on dup/clone, we need to duplicate @names hash
30
+ def initialize_copy(other)
31
+ super
32
+ @names = other.names.dup
33
+ end
34
+
35
+ # need to synchronize concurrent writes to the shared KeyMap
36
+ keymap_mutex = Mutex.new
37
+
38
+ # symbol -> string mapper + cache
39
+ KeyMap = Hash.new do |map, key|
40
+ value = if key.respond_to?(:to_str)
41
+ key
42
+ else
43
+ key.to_s.split('_'). # :user_agent => %w(user agent)
44
+ each { |w| w.capitalize! }. # => %w(User Agent)
45
+ join('-') # => "User-Agent"
46
+ end
47
+ keymap_mutex.synchronize { map[key] = value }
48
+ end
49
+ KeyMap[:etag] = "ETag"
50
+
51
+ def [](k)
52
+ k = KeyMap[k]
53
+ super(k) || super(@names[k.downcase])
54
+ end
55
+
56
+ def []=(k, v)
57
+ k = KeyMap[k]
58
+ k = (@names[k.downcase] ||= k)
59
+ # join multiple values with a comma
60
+ v = v.to_ary.join(', ') if v.respond_to? :to_ary
61
+ super(k, v)
62
+ end
63
+
64
+ def fetch(k, *args, &block)
65
+ k = KeyMap[k]
66
+ key = @names.fetch(k.downcase, k)
67
+ super(key, *args, &block)
68
+ end
69
+
70
+ def delete(k)
71
+ k = KeyMap[k]
72
+ if k = @names[k.downcase]
73
+ @names.delete k.downcase
74
+ super(k)
75
+ end
76
+ end
77
+
78
+ def include?(k)
79
+ @names.include? k.downcase
80
+ end
81
+
82
+ alias_method :has_key?, :include?
83
+ alias_method :member?, :include?
84
+ alias_method :key?, :include?
85
+
86
+ def merge!(other)
87
+ other.each { |k, v| self[k] = v }
88
+ self
89
+ end
90
+ alias_method :update, :merge!
91
+
92
+ def merge(other)
93
+ hash = dup
94
+ hash.merge! other
95
+ end
96
+
97
+ def replace(other)
98
+ clear
99
+ @names.clear
100
+ self.update other
101
+ self
102
+ end
103
+
104
+ def to_hash() ::Hash.new.update(self) end
105
+
106
+ def parse(header_string)
107
+ return unless header_string && !header_string.empty?
108
+
109
+ headers = header_string.split(/\r\n/)
110
+
111
+ # Find the last set of response headers.
112
+ start_index = headers.rindex { |x| x.match(/^HTTP\//) } || 0
113
+ last_response = headers.slice(start_index, headers.size)
114
+
115
+ last_response.
116
+ tap { |a| a.shift if a.first.index('HTTP/') == 0 }. # drop the HTTP status line
117
+ map { |h| h.split(/:\s*/, 2) }.reject { |p| p[0].nil? }. # split key and value, ignore blank lines
118
+ each { |key, value|
119
+ # join multiple values with a comma
120
+ if self[key]
121
+ self[key] << ', ' << value
122
+ else
123
+ self[key] = value
124
+ end
125
+ }
126
+ end
127
+
128
+ protected
129
+
130
+ def names
131
+ @names
132
+ end
133
+ end
134
+
135
+ # hash with stringified keys
136
+ class ParamsHash < Hash
137
+ def [](key)
138
+ super(convert_key(key))
139
+ end
140
+
141
+ def []=(key, value)
142
+ super(convert_key(key), value)
143
+ end
144
+
145
+ def delete(key)
146
+ super(convert_key(key))
147
+ end
148
+
149
+ def include?(key)
150
+ super(convert_key(key))
151
+ end
152
+
153
+ alias_method :has_key?, :include?
154
+ alias_method :member?, :include?
155
+ alias_method :key?, :include?
156
+
157
+ def update(params)
158
+ params.each do |key, value|
159
+ self[key] = value
160
+ end
161
+ self
162
+ end
163
+ alias_method :merge!, :update
164
+
165
+ def merge(params)
166
+ dup.update(params)
167
+ end
168
+
169
+ def replace(other)
170
+ clear
171
+ update(other)
172
+ end
173
+
174
+ def merge_query(query, encoder = nil)
175
+ if query && !query.empty?
176
+ update((encoder || Utils.default_params_encoder).decode(query))
177
+ end
178
+ self
179
+ end
180
+
181
+ def to_query(encoder = nil)
182
+ (encoder || Utils.default_params_encoder).encode(self)
183
+ end
184
+
185
+ private
186
+
187
+ def convert_key(key)
188
+ key.to_s
189
+ end
190
+ end
10
191
 
11
192
  def build_query(params)
12
193
  FlatParamsEncoder.encode(params)
@@ -16,19 +197,17 @@ module Faraday
16
197
  NestedParamsEncoder.encode(params)
17
198
  end
18
199
 
19
- ESCAPE_RE = /[^a-zA-Z0-9 .~_-]/.freeze
200
+ ESCAPE_RE = /[^a-zA-Z0-9 .~_-]/
20
201
 
21
- def escape(str)
22
- str.to_s.gsub(ESCAPE_RE) do |match|
202
+ def escape(s)
203
+ s.to_s.gsub(ESCAPE_RE) {|match|
23
204
  '%' + match.unpack('H2' * match.bytesize).join('%').upcase
24
- end.tr(' ', '+')
205
+ }.tr(' ', '+')
25
206
  end
26
207
 
27
- def unescape(str)
28
- CGI.unescape str.to_s
29
- end
208
+ def unescape(s) CGI.unescape s.to_s end
30
209
 
31
- DEFAULT_SEP = /[&;] */n.freeze
210
+ DEFAULT_SEP = /[&;] */n
32
211
 
33
212
  # Adapted from Rack
34
213
  def parse_query(query)
@@ -47,18 +226,55 @@ module Faraday
47
226
  attr_writer :default_params_encoder
48
227
  end
49
228
 
229
+ # Stolen from Rack
230
+ def normalize_params(params, name, v = nil)
231
+ name =~ %r(\A[\[\]]*([^\[\]]+)\]*)
232
+ k = $1 || ''
233
+ after = $' || ''
234
+
235
+ return if k.empty?
236
+
237
+ if after == ""
238
+ if params[k]
239
+ params[k] = Array[params[k]] unless params[k].kind_of?(Array)
240
+ params[k] << v
241
+ else
242
+ params[k] = v
243
+ end
244
+ elsif after == "[]"
245
+ params[k] ||= []
246
+ raise TypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array)
247
+ params[k] << v
248
+ elsif after =~ %r(^\[\]\[([^\[\]]+)\]$) || after =~ %r(^\[\](.+)$)
249
+ child_key = $1
250
+ params[k] ||= []
251
+ raise TypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array)
252
+ if params[k].last.is_a?(Hash) && !params[k].last.key?(child_key)
253
+ normalize_params(params[k].last, child_key, v)
254
+ else
255
+ params[k] << normalize_params({}, child_key, v)
256
+ end
257
+ else
258
+ params[k] ||= {}
259
+ raise TypeError, "expected Hash (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Hash)
260
+ params[k] = normalize_params(params[k], after, v)
261
+ end
262
+
263
+ return params
264
+ end
265
+
50
266
  # Normalize URI() behavior across Ruby versions
51
267
  #
52
268
  # url - A String or URI.
53
269
  #
54
270
  # Returns a parsed URI.
55
- def URI(url) # rubocop:disable Naming/MethodName
271
+ def URI(url)
56
272
  if url.respond_to?(:host)
57
273
  url
58
274
  elsif url.respond_to?(:to_str)
59
275
  default_uri_parser.call(url)
60
276
  else
61
- raise ArgumentError, 'bad argument (expected URI object or URI string)'
277
+ raise ArgumentError, "bad argument (expected URI object or URI string)"
62
278
  end
63
279
  end
64
280
 
@@ -71,28 +287,27 @@ module Faraday
71
287
 
72
288
  def default_uri_parser=(parser)
73
289
  @default_uri_parser = if parser.respond_to?(:call) || parser.nil?
74
- parser
75
- else
76
- parser.method(:parse)
77
- end
290
+ parser
291
+ else
292
+ parser.method(:parse)
293
+ end
78
294
  end
79
295
 
80
- # Receives a String or URI and returns just
81
- # the path with the query string sorted.
296
+ # Receives a String or URI and returns just the path with the query string sorted.
82
297
  def normalize_path(url)
83
298
  url = URI(url)
84
299
  (url.path.start_with?('/') ? url.path : '/' + url.path) +
85
- (url.query ? "?#{sort_query_params(url.query)}" : '')
300
+ (url.query ? "?#{sort_query_params(url.query)}" : "")
86
301
  end
87
302
 
88
303
  # Recursive hash update
89
304
  def deep_merge!(target, hash)
90
305
  hash.each do |key, value|
91
- target[key] = if value.is_a?(Hash) && target[key].is_a?(Hash)
92
- deep_merge(target[key], value)
93
- else
94
- value
95
- end
306
+ if Hash === value and Hash === target[key]
307
+ target[key] = deep_merge(target[key], value)
308
+ else
309
+ target[key] = value
310
+ end
96
311
  end
97
312
  target
98
313
  end
@@ -102,6 +317,8 @@ module Faraday
102
317
  deep_merge!(source.dup, hash)
103
318
  end
104
319
 
320
+ protected
321
+
105
322
  def sort_query_params(query)
106
323
  query.split('&').sort.join('&')
107
324
  end
data/lib/faraday.rb CHANGED
@@ -1,153 +1,129 @@
1
- # frozen_string_literal: true
2
-
1
+ require 'thread'
3
2
  require 'cgi'
4
3
  require 'set'
5
4
  require 'forwardable'
6
- require 'faraday/middleware_registry'
7
- require 'faraday/dependency_loader'
8
5
 
9
- # This is the main namespace for Faraday.
6
+ # Public: This is the main namespace for Faraday. You can either use it to
7
+ # create Faraday::Connection objects, or access it directly.
10
8
  #
11
- # It provides methods to create {Connection} objects, and HTTP-related
12
- # methods to use directly.
9
+ # Examples
13
10
  #
14
- # @example Helpful class methods for easy usage
15
11
  # Faraday.get "http://faraday.com"
16
12
  #
17
- # @example Helpful class method `.new` to create {Connection} objects.
18
13
  # conn = Faraday.new "http://faraday.com"
19
14
  # conn.get '/'
20
15
  #
21
16
  module Faraday
22
- VERSION = '0.16.0'
23
- METHODS_WITH_QUERY = %w[get head delete connect trace].freeze
24
- METHODS_WITH_BODY = %w[post put patch].freeze
17
+ VERSION = "0.17.0"
25
18
 
26
19
  class << self
27
- # The root path that Faraday is being loaded from.
28
- #
29
- # This is the root from where the libraries are auto-loaded.
30
- #
31
- # @return [String]
20
+ # Public: Gets or sets the root path that Faraday is being loaded from.
21
+ # This is the root from where the libraries are auto-loaded from.
32
22
  attr_accessor :root_path
33
23
 
34
- # Gets or sets the path that the Faraday libs are loaded from.
35
- # @return [String]
24
+ # Public: Gets or sets the path that the Faraday libs are loaded from.
36
25
  attr_accessor :lib_path
37
26
 
38
- # @overload default_adapter
39
- # Gets the Symbol key identifying a default Adapter to use
40
- # for the default {Faraday::Connection}. Defaults to `:net_http`.
41
- # @return [Symbol] the default adapter
42
- # @overload default_adapter=(adapter)
43
- # Updates default adapter while resetting {.default_connection}.
44
- # @return [Symbol] the new default_adapter.
27
+ # Public: Gets or sets the Symbol key identifying a default Adapter to use
28
+ # for the default Faraday::Connection.
45
29
  attr_reader :default_adapter
46
30
 
47
- # Documented below, see default_connection
31
+ # Public: Sets the default Faraday::Connection for simple scripts that
32
+ # access the Faraday constant directly.
33
+ #
34
+ # Faraday.get "https://faraday.com"
48
35
  attr_writer :default_connection
49
36
 
50
- # Tells Faraday to ignore the environment proxy (http_proxy).
51
- # Defaults to `false`.
52
- # @return [Boolean]
37
+ # Public: Tells faraday to ignore the environment proxy (http_proxy).
53
38
  attr_accessor :ignore_env_proxy
54
39
 
55
- # Initializes a new {Connection}.
56
- #
57
- # @param url [String,Hash] The optional String base URL to use as a prefix
58
- # for all requests. Can also be the options Hash. Any of these
59
- # values will be set on every request made, unless overridden
60
- # for a specific request.
61
- # @param options [Hash]
62
- # @option options [String] :url Base URL
63
- # @option options [Hash] :params Hash of unencoded URI query params.
64
- # @option options [Hash] :headers Hash of unencoded HTTP headers.
65
- # @option options [Hash] :request Hash of request options.
66
- # @option options [Hash] :ssl Hash of SSL options.
67
- # @option options [Hash] :proxy Hash of Proxy options.
68
- # @return [Faraday::Connection]
69
- #
70
- # @example With an URL argument
40
+ # Public: Initializes a new Faraday::Connection.
41
+ #
42
+ # url - The optional String base URL to use as a prefix for all
43
+ # requests. Can also be the options Hash.
44
+ # options - The optional Hash used to configure this Faraday::Connection.
45
+ # Any of these values will be set on every request made, unless
46
+ # overridden for a specific request.
47
+ # :url - String base URL.
48
+ # :params - Hash of URI query unencoded key/value pairs.
49
+ # :headers - Hash of unencoded HTTP header key/value pairs.
50
+ # :request - Hash of request options.
51
+ # :ssl - Hash of SSL options.
52
+ # :proxy - Hash of Proxy options.
53
+ #
54
+ # Examples
55
+ #
71
56
  # Faraday.new 'http://faraday.com'
72
- # # => Faraday::Connection to http://faraday.com
73
- #
74
- # @example With an URL argument and an options hash
75
- # Faraday.new 'http://faraday.com', params: { page: 1 }
76
- # # => Faraday::Connection to http://faraday.com?page=1
77
- #
78
- # @example With everything in an options hash
79
- # Faraday.new url: 'http://faraday.com',
80
- # params: { page: 1 }
81
- # # => Faraday::Connection to http://faraday.com?page=1
82
- def new(url = nil, options = {}, &block)
83
- options = default_connection_options.merge(options)
57
+ #
58
+ # # http://faraday.com?page=1
59
+ # Faraday.new 'http://faraday.com', :params => {:page => 1}
60
+ #
61
+ # # same
62
+ #
63
+ # Faraday.new :url => 'http://faraday.com',
64
+ # :params => {:page => 1}
65
+ #
66
+ # Returns a Faraday::Connection.
67
+ def new(url = nil, options = nil)
68
+ block = block_given? ? Proc.new : nil
69
+ options = options ? default_connection_options.merge(options) : default_connection_options
84
70
  Faraday::Connection.new(url, options, &block)
85
71
  end
86
72
 
87
- # @private
88
73
  # Internal: Requires internal Faraday libraries.
89
74
  #
90
- # @param libs [Array] one or more relative String names to Faraday classes.
91
- # @return [void]
75
+ # *libs - One or more relative String names to Faraday classes.
76
+ #
77
+ # Returns nothing.
92
78
  def require_libs(*libs)
93
79
  libs.each do |lib|
94
80
  require "#{lib_path}/#{lib}"
95
81
  end
96
82
  end
97
83
 
98
- alias require_lib require_libs
99
-
100
- # Documented elsewhere, see default_adapter reader
84
+ # Public: Updates default adapter while resetting
85
+ # #default_connection.
86
+ #
87
+ # Returns the new default_adapter.
101
88
  def default_adapter=(adapter)
102
89
  @default_connection = nil
103
90
  @default_adapter = adapter
104
91
  end
105
92
 
106
- def respond_to_missing?(symbol, include_private = false)
93
+ alias require_lib require_libs
94
+
95
+ def respond_to?(symbol, include_private = false)
107
96
  default_connection.respond_to?(symbol, include_private) || super
108
97
  end
109
98
 
110
- private
111
-
99
+ private
112
100
  # Internal: Proxies method calls on the Faraday constant to
113
- # .default_connection.
101
+ # #default_connection.
114
102
  def method_missing(name, *args, &block)
115
- if default_connection.respond_to?(name)
116
- default_connection.send(name, *args, &block)
117
- else
118
- super
119
- end
103
+ default_connection.send(name, *args, &block)
120
104
  end
121
105
  end
122
106
 
123
107
  self.ignore_env_proxy = false
124
- self.root_path = File.expand_path __dir__
125
- self.lib_path = File.expand_path 'faraday', __dir__
108
+ self.root_path = File.expand_path "..", __FILE__
109
+ self.lib_path = File.expand_path "../faraday", __FILE__
126
110
  self.default_adapter = :net_http
127
111
 
128
- # @overload default_connection
129
- # Gets the default connection used for simple scripts.
130
- # @return [Faraday::Connection] a connection configured with
131
- # the default_adapter.
132
- # @overload default_connection=(connection)
133
- # @param connection [Faraday::Connection]
134
- # Sets the default {Faraday::Connection} for simple scripts that
135
- # access the Faraday constant directly, such as
136
- # <code>Faraday.get "https://faraday.com"</code>.
112
+ # Gets the default connection used for simple scripts.
113
+ #
114
+ # Returns a Faraday::Connection, configured with the #default_adapter.
137
115
  def self.default_connection
138
116
  @default_connection ||= Connection.new(default_connection_options)
139
117
  end
140
118
 
141
- # Gets the default connection options used when calling {Faraday#new}.
119
+ # Gets the default connection options used when calling Faraday#new.
142
120
  #
143
- # @return [Faraday::ConnectionOptions]
121
+ # Returns a Faraday::ConnectionOptions.
144
122
  def self.default_connection_options
145
123
  @default_connection_options ||= ConnectionOptions.new
146
124
  end
147
125
 
148
- # Sets the default options used when calling {Faraday#new}.
149
- #
150
- # @param options [Hash, Faraday::ConnectionOptions]
126
+ # Public: Sets the default options used when calling Faraday#new.
151
127
  def self.default_connection_options=(options)
152
128
  @default_connection = nil
153
129
  @default_connection_options = ConnectionOptions.from(options)
@@ -158,9 +134,115 @@ module Faraday
158
134
  Timer = Timeout
159
135
  end
160
136
 
161
- require_libs 'utils', 'options', 'connection', 'rack_builder', 'parameters',
162
- 'middleware', 'adapter', 'request', 'response', 'error',
163
- 'file_part', 'param_part'
137
+ # Public: Adds the ability for other modules to register and lookup
138
+ # middleware classes.
139
+ module MiddlewareRegistry
140
+ # Public: Register middleware class(es) on the current module.
141
+ #
142
+ # mapping - A Hash mapping Symbol keys to classes. Classes can be expressed
143
+ # as fully qualified constant, or a Proc that will be lazily
144
+ # called to return the former.
145
+ #
146
+ # Examples
147
+ #
148
+ # module Faraday
149
+ # class Whatever
150
+ # # Middleware looked up by :foo returns Faraday::Whatever::Foo.
151
+ # register_middleware :foo => Foo
152
+ #
153
+ # # Middleware looked up by :bar returns Faraday::Whatever.const_get(:Bar)
154
+ # register_middleware :bar => :Bar
155
+ #
156
+ # # Middleware looked up by :baz requires 'baz' and returns Faraday::Whatever.const_get(:Baz)
157
+ # register_middleware :baz => [:Baz, 'baz']
158
+ # end
159
+ # end
160
+ #
161
+ # Returns nothing.
162
+ def register_middleware(autoload_path = nil, mapping = nil)
163
+ if mapping.nil?
164
+ mapping = autoload_path
165
+ autoload_path = nil
166
+ end
167
+ middleware_mutex do
168
+ @middleware_autoload_path = autoload_path if autoload_path
169
+ (@registered_middleware ||= {}).update(mapping)
170
+ end
171
+ end
164
172
 
165
- require_lib 'autoload' unless ENV['FARADAY_NO_AUTOLOAD']
173
+ # Public: Lookup middleware class with a registered Symbol shortcut.
174
+ #
175
+ # key - The Symbol key for the registered middleware.
176
+ #
177
+ # Examples
178
+ #
179
+ # module Faraday
180
+ # class Whatever
181
+ # register_middleware :foo => Foo
182
+ # end
183
+ # end
184
+ #
185
+ # Faraday::Whatever.lookup_middleware(:foo)
186
+ # # => Faraday::Whatever::Foo
187
+ #
188
+ # Returns a middleware Class.
189
+ def lookup_middleware(key)
190
+ load_middleware(key) ||
191
+ raise(Faraday::Error.new("#{key.inspect} is not registered on #{self}"))
192
+ end
193
+
194
+ def middleware_mutex(&block)
195
+ @middleware_mutex ||= begin
196
+ require 'monitor'
197
+ Monitor.new
198
+ end
199
+ @middleware_mutex.synchronize(&block)
200
+ end
201
+
202
+ def fetch_middleware(key)
203
+ defined?(@registered_middleware) && @registered_middleware[key]
204
+ end
205
+
206
+ def load_middleware(key)
207
+ value = fetch_middleware(key)
208
+ case value
209
+ when Module
210
+ value
211
+ when Symbol, String
212
+ middleware_mutex do
213
+ @registered_middleware[key] = const_get(value)
214
+ end
215
+ when Proc
216
+ middleware_mutex do
217
+ @registered_middleware[key] = value.call
218
+ end
219
+ when Array
220
+ middleware_mutex do
221
+ const, path = value
222
+ if root = @middleware_autoload_path
223
+ path = "#{root}/#{path}"
224
+ end
225
+ require(path)
226
+ @registered_middleware[key] = const
227
+ end
228
+ load_middleware(key)
229
+ end
230
+ end
231
+ end
232
+
233
+ def self.const_missing(name)
234
+ if name.to_sym == :Builder
235
+ warn "Faraday::Builder is now Faraday::RackBuilder."
236
+ const_set name, RackBuilder
237
+ else
238
+ super
239
+ end
240
+ end
241
+
242
+ require_libs "utils", "options", "connection", "rack_builder", "parameters",
243
+ "middleware", "adapter", "request", "response", "upload_io", "error"
244
+
245
+ if !ENV["FARADAY_NO_AUTOLOAD"]
246
+ require_lib 'autoload'
247
+ end
166
248
  end