faraday 1.4.1 → 2.14.2

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 (94) 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 +67 -13
  7. data/examples/client_test.rb +81 -16
  8. data/lib/faraday/adapter/test.rb +117 -52
  9. data/lib/faraday/adapter.rb +12 -20
  10. data/lib/faraday/connection.rb +86 -134
  11. data/lib/faraday/encoders/flat_params_encoder.rb +3 -2
  12. data/lib/faraday/encoders/nested_params_encoder.rb +15 -7
  13. data/lib/faraday/error.rb +65 -15
  14. data/lib/faraday/logging/formatter.rb +30 -17
  15. data/lib/faraday/middleware.rb +44 -3
  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 +88 -65
  19. data/lib/faraday/options/proxy_options.rb +17 -6
  20. data/lib/faraday/options/request_options.rb +8 -7
  21. data/lib/faraday/options/ssl_options.rb +62 -45
  22. data/lib/faraday/options.rb +8 -7
  23. data/lib/faraday/rack_builder.rb +46 -47
  24. data/lib/faraday/request/authorization.rb +37 -38
  25. data/lib/faraday/request/instrumentation.rb +5 -1
  26. data/lib/faraday/request/json.rb +70 -0
  27. data/lib/faraday/request/url_encoded.rb +5 -1
  28. data/lib/faraday/request.rb +20 -37
  29. data/lib/faraday/response/json.rb +74 -0
  30. data/lib/faraday/response/logger.rb +13 -7
  31. data/lib/faraday/response/raise_error.rb +45 -18
  32. data/lib/faraday/response.rb +15 -21
  33. data/lib/faraday/utils/headers.rb +18 -7
  34. data/lib/faraday/utils.rb +11 -7
  35. data/lib/faraday/version.rb +1 -1
  36. data/lib/faraday.rb +12 -32
  37. data/spec/faraday/adapter/test_spec.rb +182 -0
  38. data/spec/faraday/connection_spec.rb +219 -92
  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 +163 -2
  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 +42 -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 +54 -24
  48. data/spec/faraday/request/instrumentation_spec.rb +5 -7
  49. data/spec/faraday/request/json_spec.rb +199 -0
  50. data/spec/faraday/request/url_encoded_spec.rb +12 -2
  51. data/spec/faraday/request_spec.rb +14 -15
  52. data/spec/faraday/response/json_spec.rb +206 -0
  53. data/spec/faraday/response/logger_spec.rb +84 -5
  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 +66 -2
  58. data/spec/faraday_spec.rb +10 -4
  59. data/spec/spec_helper.rb +6 -5
  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 +27 -81
  66. data/lib/faraday/adapter/em_http.rb +0 -289
  67. data/lib/faraday/adapter/em_http_ssl_patch.rb +0 -62
  68. data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +0 -69
  69. data/lib/faraday/adapter/em_synchrony.rb +0 -153
  70. data/lib/faraday/adapter/httpclient.rb +0 -152
  71. data/lib/faraday/adapter/patron.rb +0 -132
  72. data/lib/faraday/adapter/rack.rb +0 -75
  73. data/lib/faraday/adapter/typhoeus.rb +0 -15
  74. data/lib/faraday/autoload.rb +0 -92
  75. data/lib/faraday/dependency_loader.rb +0 -37
  76. data/lib/faraday/file_part.rb +0 -128
  77. data/lib/faraday/param_part.rb +0 -53
  78. data/lib/faraday/request/basic_authentication.rb +0 -20
  79. data/lib/faraday/request/multipart.rb +0 -106
  80. data/lib/faraday/request/retry.rb +0 -239
  81. data/lib/faraday/request/token_authentication.rb +0 -20
  82. data/spec/faraday/adapter/em_http_spec.rb +0 -47
  83. data/spec/faraday/adapter/em_synchrony_spec.rb +0 -16
  84. data/spec/faraday/adapter/excon_spec.rb +0 -49
  85. data/spec/faraday/adapter/httpclient_spec.rb +0 -73
  86. data/spec/faraday/adapter/net_http_spec.rb +0 -64
  87. data/spec/faraday/adapter/patron_spec.rb +0 -18
  88. data/spec/faraday/adapter/rack_spec.rb +0 -8
  89. data/spec/faraday/adapter/typhoeus_spec.rb +0 -7
  90. data/spec/faraday/composite_read_io_spec.rb +0 -80
  91. data/spec/faraday/request/multipart_spec.rb +0 -302
  92. data/spec/faraday/request/retry_spec.rb +0 -242
  93. data/spec/faraday/response/middleware_spec.rb +0 -68
  94. data/spec/support/webmock_rack_app.rb +0 -68
@@ -1,51 +1,63 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Faraday
4
- # SSL-related options.
5
- #
6
- # @!attribute verify
7
- # @return [Boolean] whether to verify SSL certificates or not
8
- #
9
- # @!attribute ca_file
10
- # @return [String] CA file
11
- #
12
- # @!attribute ca_path
13
- # @return [String] CA path
14
- #
15
- # @!attribute verify_mode
16
- # @return [Integer] Any `OpenSSL::SSL::` constant (see https://ruby-doc.org/stdlib-2.5.1/libdoc/openssl/rdoc/OpenSSL/SSL.html)
17
- #
18
- # @!attribute cert_store
19
- # @return [OpenSSL::X509::Store] certificate store
20
- #
21
- # @!attribute client_cert
22
- # @return [String, OpenSSL::X509::Certificate] client certificate
23
- #
24
- # @!attribute client_key
25
- # @return [String, OpenSSL::PKey::RSA, OpenSSL::PKey::DSA] client key
26
- #
27
- # @!attribute certificate
28
- # @return [OpenSSL::X509::Certificate] certificate (Excon only)
29
- #
30
- # @!attribute private_key
31
- # @return [OpenSSL::PKey::RSA, OpenSSL::PKey::DSA] private key (Excon only)
32
- #
33
- # @!attribute verify_depth
34
- # @return [Integer] maximum depth for the certificate chain verification
35
- #
36
- # @!attribute version
37
- # @return [String, Symbol] SSL version (see https://ruby-doc.org/stdlib-2.5.1/libdoc/openssl/rdoc/OpenSSL/SSL/SSLContext.html#method-i-ssl_version-3D)
38
- #
39
- # @!attribute min_version
40
- # @return [String, Symbol] minimum SSL version (see https://ruby-doc.org/stdlib-2.5.1/libdoc/openssl/rdoc/OpenSSL/SSL/SSLContext.html#method-i-min_version-3D)
41
- #
42
- # @!attribute max_version
43
- # @return [String, Symbol] maximum SSL version (see https://ruby-doc.org/stdlib-2.5.1/libdoc/openssl/rdoc/OpenSSL/SSL/SSLContext.html#method-i-max_version-3D)
44
- class SSLOptions < Options.new(:verify, :ca_file, :ca_path, :verify_mode,
45
- :cert_store, :client_cert, :client_key,
46
- :certificate, :private_key, :verify_depth,
47
- :version, :min_version, :max_version)
48
-
4
+ # @!parse
5
+ # # SSL-related options.
6
+ # #
7
+ # # @!attribute verify
8
+ # # @return [Boolean] whether to verify SSL certificates or not
9
+ # #
10
+ # # @!attribute verify_hostname
11
+ # # @return [Boolean] whether to enable hostname verification on server certificates
12
+ # # during the handshake or not (see https://github.com/ruby/openssl/pull/60)
13
+ # #
14
+ # # @!attribute hostname
15
+ # # @return [String] Server hostname used for SNI (see https://ruby-doc.org/stdlib-2.5.1/libdoc/openssl/rdoc/OpenSSL/SSL/SSLSocket.html#method-i-hostname-3D)
16
+ # #
17
+ # # @!attribute ca_file
18
+ # # @return [String] CA file
19
+ # #
20
+ # # @!attribute ca_path
21
+ # # @return [String] CA path
22
+ # #
23
+ # # @!attribute verify_mode
24
+ # # @return [Integer] Any `OpenSSL::SSL::` constant (see https://ruby-doc.org/stdlib-2.5.1/libdoc/openssl/rdoc/OpenSSL/SSL.html)
25
+ # #
26
+ # # @!attribute cert_store
27
+ # # @return [OpenSSL::X509::Store] certificate store
28
+ # #
29
+ # # @!attribute client_cert
30
+ # # @return [String, OpenSSL::X509::Certificate] client certificate
31
+ # #
32
+ # # @!attribute client_key
33
+ # # @return [String, OpenSSL::PKey::RSA, OpenSSL::PKey::DSA] client key
34
+ # #
35
+ # # @!attribute certificate
36
+ # # @return [OpenSSL::X509::Certificate] certificate (Excon only)
37
+ # #
38
+ # # @!attribute private_key
39
+ # # @return [OpenSSL::PKey::RSA, OpenSSL::PKey::DSA] private key (Excon only)
40
+ # #
41
+ # # @!attribute verify_depth
42
+ # # @return [Integer] maximum depth for the certificate chain verification
43
+ # #
44
+ # # @!attribute version
45
+ # # @return [String, Symbol] SSL version (see https://ruby-doc.org/stdlib-2.5.1/libdoc/openssl/rdoc/OpenSSL/SSL/SSLContext.html#method-i-ssl_version-3D)
46
+ # #
47
+ # # @!attribute min_version
48
+ # # @return [String, Symbol] minimum SSL version (see https://ruby-doc.org/stdlib-2.5.1/libdoc/openssl/rdoc/OpenSSL/SSL/SSLContext.html#method-i-min_version-3D)
49
+ # #
50
+ # # @!attribute max_version
51
+ # # @return [String, Symbol] maximum SSL version (see https://ruby-doc.org/stdlib-2.5.1/libdoc/openssl/rdoc/OpenSSL/SSL/SSLContext.html#method-i-max_version-3D)
52
+ # #
53
+ # # @!attribute ciphers
54
+ # # @return [String] cipher list in OpenSSL format (see https://ruby-doc.org/stdlib-2.5.1/libdoc/openssl/rdoc/OpenSSL/SSL/SSLContext.html#method-i-ciphers-3D)
55
+ # class SSLOptions < Options; end
56
+ SSLOptions = Options.new(:verify, :verify_hostname, :hostname,
57
+ :ca_file, :ca_path, :verify_mode,
58
+ :cert_store, :client_cert, :client_key,
59
+ :certificate, :private_key, :verify_depth,
60
+ :version, :min_version, :max_version, :ciphers) do
49
61
  # @return [Boolean] true if should verify
50
62
  def verify?
51
63
  verify != false
@@ -55,5 +67,10 @@ module Faraday
55
67
  def disable?
56
68
  !verify?
57
69
  end
70
+
71
+ # @return [Boolean] true if should verify_hostname
72
+ def verify_hostname?
73
+ verify_hostname != false
74
+ end
58
75
  end
59
76
  end
@@ -30,7 +30,7 @@ module Faraday
30
30
  new_value = value
31
31
  end
32
32
 
33
- send("#{key}=", new_value) unless new_value.nil?
33
+ send(:"#{key}=", new_value) unless new_value.nil?
34
34
  end
35
35
  self
36
36
  end
@@ -38,7 +38,7 @@ module Faraday
38
38
  # Public
39
39
  def delete(key)
40
40
  value = send(key)
41
- send("#{key}=", nil)
41
+ send(:"#{key}=", nil)
42
42
  value
43
43
  end
44
44
 
@@ -57,7 +57,7 @@ module Faraday
57
57
  else
58
58
  other_value
59
59
  end
60
- send("#{key}=", new_value) unless new_value.nil?
60
+ send(:"#{key}=", new_value) unless new_value.nil?
61
61
  end
62
62
  self
63
63
  end
@@ -104,7 +104,7 @@ module Faraday
104
104
 
105
105
  # Public
106
106
  def each_key(&block)
107
- return to_enum(:each_key) unless block_given?
107
+ return to_enum(:each_key) unless block
108
108
 
109
109
  keys.each(&block)
110
110
  end
@@ -118,7 +118,7 @@ module Faraday
118
118
 
119
119
  # Public
120
120
  def each_value(&block)
121
- return to_enum(:each_value) unless block_given?
121
+ return to_enum(:each_value) unless block
122
122
 
123
123
  values.each(&block)
124
124
  end
@@ -168,12 +168,13 @@ module Faraday
168
168
  end
169
169
 
170
170
  def self.memoized(key, &block)
171
- unless block_given?
171
+ unless block
172
172
  raise ArgumentError, '#memoized must be called with a block'
173
173
  end
174
174
 
175
175
  memoized_attributes[key.to_sym] = block
176
176
  class_eval <<-RUBY, __FILE__, __LINE__ + 1
177
+ remove_method(key) if method_defined?(key, false)
177
178
  def #{key}() self[:#{key}]; end
178
179
  RUBY
179
180
  end
@@ -185,7 +186,7 @@ module Faraday
185
186
  def [](key)
186
187
  key = key.to_sym
187
188
  if (method = self.class.memoized_attributes[key])
188
- super(key) || (self[key] = instance_eval(&method))
189
+ super || (self[key] = instance_eval(&method))
189
190
  else
190
191
  super
191
192
  end
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'ruby2_keywords'
4
3
  require 'faraday/adapter_registry'
5
4
 
6
5
  module Faraday
@@ -8,7 +7,7 @@ module Faraday
8
7
  # middleware stack (heavily inspired by Rack).
9
8
  #
10
9
  # @example
11
- # Faraday::Connection.new(url: 'http://sushi.com') do |builder|
10
+ # Faraday::Connection.new(url: 'http://httpbingo.org') do |builder|
12
11
  # builder.request :url_encoded # Faraday::Request::UrlEncoded
13
12
  # builder.adapter :net_http # Faraday::Adapter::NetHttp
14
13
  # end
@@ -16,6 +15,11 @@ module Faraday
16
15
  # Used to detect missing arguments
17
16
  NO_ARGUMENT = Object.new
18
17
 
18
+ LOCK_ERR = "can't modify middleware stack after making a request"
19
+ MISSING_ADAPTER_ERROR = "An attempt to run a request with a Faraday::Connection without adapter has been made.\n" \
20
+ "Please set Faraday.default_adapter or provide one when initializing the connection.\n" \
21
+ 'For more info, check https://lostisland.github.io/faraday/usage/.'
22
+
19
23
  attr_accessor :handlers
20
24
 
21
25
  # Error raised when trying to modify the stack after calling `lock!`
@@ -28,10 +32,11 @@ module Faraday
28
32
 
29
33
  attr_reader :name
30
34
 
31
- ruby2_keywords def initialize(klass, *args, &block)
35
+ def initialize(klass, *args, **kwargs, &block)
32
36
  @name = klass.to_s
33
37
  REGISTRY.set(klass) if klass.respond_to?(:name)
34
38
  @args = args
39
+ @kwargs = kwargs
35
40
  @block = block
36
41
  end
37
42
 
@@ -54,27 +59,26 @@ module Faraday
54
59
  end
55
60
 
56
61
  def build(app = nil)
57
- klass.new(app, *@args, &@block)
62
+ klass.new(app, *@args, **@kwargs, &@block)
58
63
  end
59
64
  end
60
65
 
61
- def initialize(handlers = [], adapter = nil, &block)
62
- @adapter = adapter
63
- @handlers = handlers
64
- if block_given?
65
- build(&block)
66
- elsif @handlers.empty?
67
- # default stack, if nothing else is configured
68
- request :url_encoded
69
- self.adapter Faraday.default_adapter
70
- end
66
+ def initialize(&block)
67
+ @adapter = nil
68
+ @handlers = []
69
+ build(&block)
71
70
  end
72
71
 
73
- def build(options = {})
72
+ def initialize_dup(original)
73
+ super
74
+ @adapter = original.adapter
75
+ @handlers = original.handlers.dup
76
+ end
77
+
78
+ def build
74
79
  raise_if_locked
75
- @handlers.clear unless options[:keep]
76
- yield(self) if block_given?
77
- adapter(Faraday.default_adapter) unless @adapter
80
+ block_given? ? yield(self) : request(:url_encoded)
81
+ adapter(Faraday.default_adapter, **Faraday.default_adapter_options) unless @adapter
78
82
  end
79
83
 
80
84
  def [](idx)
@@ -90,52 +94,52 @@ module Faraday
90
94
  @handlers.frozen?
91
95
  end
92
96
 
93
- ruby2_keywords def use(klass, *args, &block)
97
+ def use(klass, ...)
94
98
  if klass.is_a? Symbol
95
- use_symbol(Faraday::Middleware, klass, *args, &block)
99
+ use_symbol(Faraday::Middleware, klass, ...)
96
100
  else
97
101
  raise_if_locked
98
102
  raise_if_adapter(klass)
99
- @handlers << self.class::Handler.new(klass, *args, &block)
103
+ @handlers << self.class::Handler.new(klass, ...)
100
104
  end
101
105
  end
102
106
 
103
- ruby2_keywords def request(key, *args, &block)
104
- use_symbol(Faraday::Request, key, *args, &block)
107
+ def request(key, ...)
108
+ use_symbol(Faraday::Request, key, ...)
105
109
  end
106
110
 
107
- ruby2_keywords def response(key, *args, &block)
108
- use_symbol(Faraday::Response, key, *args, &block)
111
+ def response(...)
112
+ use_symbol(Faraday::Response, ...)
109
113
  end
110
114
 
111
- ruby2_keywords def adapter(klass = NO_ARGUMENT, *args, &block)
112
- return @adapter if klass == NO_ARGUMENT
115
+ def adapter(klass = NO_ARGUMENT, *args, **kwargs, &block)
116
+ return @adapter if klass == NO_ARGUMENT || klass.nil?
113
117
 
114
118
  klass = Faraday::Adapter.lookup_middleware(klass) if klass.is_a?(Symbol)
115
- @adapter = self.class::Handler.new(klass, *args, &block)
119
+ @adapter = self.class::Handler.new(klass, *args, **kwargs, &block)
116
120
  end
117
121
 
118
122
  ## methods to push onto the various positions in the stack:
119
123
 
120
- ruby2_keywords def insert(index, *args, &block)
124
+ def insert(index, ...)
121
125
  raise_if_locked
122
126
  index = assert_index(index)
123
- handler = self.class::Handler.new(*args, &block)
127
+ handler = self.class::Handler.new(...)
124
128
  @handlers.insert(index, handler)
125
129
  end
126
130
 
127
131
  alias insert_before insert
128
132
 
129
- ruby2_keywords def insert_after(index, *args, &block)
133
+ def insert_after(index, ...)
130
134
  index = assert_index(index)
131
- insert(index + 1, *args, &block)
135
+ insert(index + 1, ...)
132
136
  end
133
137
 
134
- ruby2_keywords def swap(index, *args, &block)
138
+ def swap(index, ...)
135
139
  raise_if_locked
136
140
  index = assert_index(index)
137
141
  @handlers.delete_at(index)
138
- insert(index, *args, &block)
142
+ insert(index, ...)
139
143
  end
140
144
 
141
145
  def delete(handler)
@@ -164,6 +168,7 @@ module Faraday
164
168
  def app
165
169
  @app ||= begin
166
170
  lock!
171
+ ensure_adapter!
167
172
  to_app
168
173
  end
169
174
  end
@@ -182,10 +187,6 @@ module Faraday
182
187
  @adapter == other.adapter
183
188
  end
184
189
 
185
- def dup
186
- self.class.new(@handlers.dup, @adapter.dup)
187
- end
188
-
189
190
  # ENV Keys
190
191
  # :http_method - a symbolized request HTTP method (:get, :post)
191
192
  # :body - the request body that will eventually be converted to a string.
@@ -215,28 +216,26 @@ module Faraday
215
216
 
216
217
  private
217
218
 
218
- LOCK_ERR = "can't modify middleware stack after making a request"
219
-
220
219
  def raise_if_locked
221
220
  raise StackLocked, LOCK_ERR if locked?
222
221
  end
223
222
 
224
223
  def raise_if_adapter(klass)
225
- return unless is_adapter?(klass)
224
+ return unless klass <= Faraday::Adapter
226
225
 
227
226
  raise 'Adapter should be set using the `adapter` method, not `use`'
228
227
  end
229
228
 
230
- def adapter_set?
231
- !@adapter.nil?
229
+ def ensure_adapter!
230
+ raise MISSING_ADAPTER_ERROR unless @adapter
232
231
  end
233
232
 
234
- def is_adapter?(klass) # rubocop:disable Naming/PredicateName
235
- klass <= Faraday::Adapter
233
+ def adapter_set?
234
+ !@adapter.nil?
236
235
  end
237
236
 
238
- ruby2_keywords def use_symbol(mod, key, *args, &block)
239
- use(mod.lookup_middleware(key), *args, &block)
237
+ def use_symbol(mod, key, ...)
238
+ use(mod.lookup_middleware(key), ...)
240
239
  end
241
240
 
242
241
  def assert_index(index)
@@ -4,52 +4,51 @@ module Faraday
4
4
  class Request
5
5
  # Request middleware for the Authorization HTTP header
6
6
  class Authorization < Faraday::Middleware
7
- unless defined?(::Faraday::Request::Authorization::KEY)
8
- KEY = 'Authorization'
9
- end
10
-
11
- # @param type [String, Symbol]
12
- # @param token [String, Symbol, Hash]
13
- # @return [String] a header value
14
- def self.header(type, token)
15
- case token
16
- when String, Symbol
17
- "#{type} #{token}"
18
- when Hash
19
- build_hash(type.to_s, token)
20
- else
21
- raise ArgumentError,
22
- "Can't build an Authorization #{type}" \
23
- "header from #{token.inspect}"
24
- end
25
- end
26
-
27
- # @param type [String]
28
- # @param hash [Hash]
29
- # @return [String] type followed by comma-separated key=value pairs
30
- # @api private
31
- def self.build_hash(type, hash)
32
- comma = ', '
33
- values = []
34
- hash.each do |key, value|
35
- values << "#{key}=#{value.to_s.inspect}"
36
- end
37
- "#{type} #{values * comma}"
38
- end
7
+ KEY = 'Authorization'
39
8
 
40
9
  # @param app [#call]
41
10
  # @param type [String, Symbol] Type of Authorization
42
- # @param token [String, Symbol, Hash] Token value for the Authorization
43
- def initialize(app, type, token)
44
- @header_value = self.class.header(type, token)
11
+ # @param params [Array<String, Proc, #call>] parameters to build the Authorization header.
12
+ # If the type is `:basic`, then these can be a login and password pair.
13
+ # Otherwise, a single value is expected that will be appended after the type.
14
+ # This value can be a proc or an object responding to `.call`, in which case
15
+ # it will be invoked on each request.
16
+ def initialize(app, type, *params)
17
+ @type = type
18
+ @params = params
45
19
  super(app)
46
20
  end
47
21
 
48
22
  # @param env [Faraday::Env]
49
- def call(env)
50
- env.request_headers[KEY] = @header_value unless env.request_headers[KEY]
51
- @app.call(env)
23
+ def on_request(env)
24
+ return if env.request_headers[KEY]
25
+
26
+ env.request_headers[KEY] = header_from(@type, env, *@params)
27
+ end
28
+
29
+ private
30
+
31
+ # @param type [String, Symbol]
32
+ # @param env [Faraday::Env]
33
+ # @param params [Array]
34
+ # @return [String] a header value
35
+ def header_from(type, env, *params)
36
+ if type.to_s.casecmp('basic').zero? && params.size == 2
37
+ Utils.basic_header_from(*params)
38
+ elsif params.size != 1
39
+ raise ArgumentError, "Unexpected params received (got #{params.size} instead of 1)"
40
+ else
41
+ value = params.first
42
+ if (value.is_a?(Proc) && value.arity == 1) || (value.respond_to?(:call) && value.method(:call).arity == 1)
43
+ value = value.call(env)
44
+ elsif value.is_a?(Proc) || value.respond_to?(:call)
45
+ value = value.call
46
+ end
47
+ "#{type} #{value}"
48
+ end
52
49
  end
53
50
  end
54
51
  end
55
52
  end
53
+
54
+ Faraday::Request.register_middleware(authorization: Faraday::Request::Authorization)
@@ -5,12 +5,14 @@ module Faraday
5
5
  # Middleware for instrumenting Requests.
6
6
  class Instrumentation < Faraday::Middleware
7
7
  # Options class used in Request::Instrumentation class.
8
- class Options < Faraday::Options.new(:name, :instrumenter)
8
+ Options = Faraday::Options.new(:name, :instrumenter) do
9
+ remove_method :name
9
10
  # @return [String]
10
11
  def name
11
12
  self[:name] ||= 'request.faraday'
12
13
  end
13
14
 
15
+ remove_method :instrumenter
14
16
  # @return [Class]
15
17
  def instrumenter
16
18
  self[:instrumenter] ||= ActiveSupport::Notifications
@@ -52,3 +54,5 @@ module Faraday
52
54
  end
53
55
  end
54
56
  end
57
+
58
+ Faraday::Request.register_middleware(instrumentation: Faraday::Request::Instrumentation)
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module Faraday
6
+ class Request
7
+ # Request middleware that encodes the body as JSON.
8
+ #
9
+ # Processes only requests with matching Content-type or those without a type.
10
+ # If a request doesn't have a type but has a body, it sets the Content-type
11
+ # to JSON MIME-type.
12
+ #
13
+ # Doesn't try to encode bodies that already are in string form.
14
+ class Json < Middleware
15
+ MIME_TYPE = 'application/json'
16
+ MIME_TYPE_REGEX = %r{^application/(vnd\..+\+)?json$}
17
+
18
+ def on_request(env)
19
+ match_content_type(env) do |data|
20
+ env[:body] = encode(data)
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ def encode(data)
27
+ if options[:encoder].is_a?(Array) && options[:encoder].size >= 2
28
+ options[:encoder][0].public_send(options[:encoder][1], data)
29
+ elsif options[:encoder].respond_to?(:dump)
30
+ options[:encoder].dump(data)
31
+ else
32
+ ::JSON.generate(data)
33
+ end
34
+ end
35
+
36
+ def match_content_type(env)
37
+ return unless process_request?(env)
38
+
39
+ env[:request_headers][CONTENT_TYPE] ||= MIME_TYPE
40
+ yield env[:body] unless env[:body].respond_to?(:to_str)
41
+ end
42
+
43
+ def process_request?(env)
44
+ type = request_type(env)
45
+ body?(env) && (type.empty? || type.match?(MIME_TYPE_REGEX))
46
+ end
47
+
48
+ def body?(env)
49
+ body = env[:body]
50
+ case body
51
+ when true, false
52
+ true
53
+ when nil
54
+ # NOTE: nil can be converted to `"null"`, but this middleware doesn't process `nil` for the compatibility.
55
+ false
56
+ else
57
+ !(body.respond_to?(:to_str) && body.empty?)
58
+ end
59
+ end
60
+
61
+ def request_type(env)
62
+ type = env[:request_headers][CONTENT_TYPE].to_s
63
+ type = type.split(';', 2).first if type.index(';')
64
+ type
65
+ end
66
+ end
67
+ end
68
+ end
69
+
70
+ Faraday::Request.register_middleware(json: Faraday::Request::Json)
@@ -31,7 +31,9 @@ module Faraday
31
31
  return unless process_request?(env)
32
32
 
33
33
  env.request_headers[CONTENT_TYPE] ||= self.class.mime_type
34
- yield(env.body) unless env.body.respond_to?(:to_str)
34
+ return if env.body.respond_to?(:to_str) || env.body.respond_to?(:read)
35
+
36
+ yield(env.body)
35
37
  end
36
38
 
37
39
  # @param env [Faraday::Env]
@@ -54,3 +56,5 @@ module Faraday
54
56
  end
55
57
  end
56
58
  end
59
+
60
+ Faraday::Request.register_middleware(url_encoded: Faraday::Request::UrlEncoded)