faraday 2.0.0 → 2.7.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 (39) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +81 -3
  3. data/LICENSE.md +1 -1
  4. data/README.md +1 -6
  5. data/examples/client_spec.rb +40 -18
  6. data/examples/client_test.rb +47 -21
  7. data/lib/faraday/adapter/test.rb +41 -7
  8. data/lib/faraday/adapter.rb +2 -2
  9. data/lib/faraday/connection.rb +34 -34
  10. data/lib/faraday/encoders/nested_params_encoder.rb +11 -4
  11. data/lib/faraday/logging/formatter.rb +17 -3
  12. data/lib/faraday/middleware.rb +3 -0
  13. data/lib/faraday/middleware_registry.rb +19 -1
  14. data/lib/faraday/options/env.rb +18 -0
  15. data/lib/faraday/options/ssl_options.rb +11 -1
  16. data/lib/faraday/rack_builder.rb +2 -2
  17. data/lib/faraday/request/authorization.rb +8 -3
  18. data/lib/faraday/request/url_encoded.rb +3 -1
  19. data/lib/faraday/request.rb +1 -1
  20. data/lib/faraday/response/logger.rb +4 -0
  21. data/lib/faraday/utils/headers.rb +6 -1
  22. data/lib/faraday/version.rb +1 -1
  23. data/lib/faraday.rb +8 -2
  24. data/spec/faraday/adapter/test_spec.rb +36 -0
  25. data/spec/faraday/connection_spec.rb +48 -42
  26. data/spec/faraday/middleware_registry_spec.rb +31 -0
  27. data/spec/faraday/middleware_spec.rb +18 -0
  28. data/spec/faraday/options/env_spec.rb +6 -0
  29. data/spec/faraday/params_encoders/nested_spec.rb +8 -0
  30. data/spec/faraday/rack_builder_spec.rb +27 -12
  31. data/spec/faraday/request/authorization_spec.rb +35 -0
  32. data/spec/faraday/request/url_encoded_spec.rb +12 -1
  33. data/spec/faraday/request_spec.rb +5 -4
  34. data/spec/faraday/response/logger_spec.rb +28 -0
  35. data/spec/faraday/utils/headers_spec.rb +22 -4
  36. data/spec/faraday/utils_spec.rb +2 -1
  37. data/spec/support/shared_examples/adapter.rb +2 -1
  38. data/spec/support/shared_examples/request_method.rb +17 -3
  39. metadata +24 -3
@@ -6,9 +6,9 @@ module Faraday
6
6
  #
7
7
  # @example
8
8
  #
9
- # conn = Faraday::Connection.new 'http://sushi.com'
9
+ # conn = Faraday::Connection.new 'http://httpbingo.org'
10
10
  #
11
- # # GET http://sushi.com/nigiri
11
+ # # GET http://httpbingo.org/nigiri
12
12
  # conn.get 'nigiri'
13
13
  # # => #<Faraday::Response>
14
14
  #
@@ -130,10 +130,10 @@ module Faraday
130
130
  # Makes a GET HTTP request without a body.
131
131
  # @!scope class
132
132
  #
133
- # @param url [String] The optional String base URL to use as a prefix for
133
+ # @param url [String, URI, nil] The optional String base URL to use as a prefix for
134
134
  # all requests. Can also be the options Hash.
135
- # @param params [Hash] Hash of URI query unencoded key/value pairs.
136
- # @param headers [Hash] unencoded HTTP header key/value pairs.
135
+ # @param params [Hash, nil] Hash of URI query unencoded key/value pairs.
136
+ # @param headers [Hash, nil] unencoded HTTP header key/value pairs.
137
137
  #
138
138
  # @example
139
139
  # conn.get '/items', { page: 1 }, :accept => 'application/json'
@@ -152,10 +152,10 @@ module Faraday
152
152
  # Makes a HEAD HTTP request without a body.
153
153
  # @!scope class
154
154
  #
155
- # @param url [String] The optional String base URL to use as a prefix for
155
+ # @param url [String, URI, nil] The optional String base URL to use as a prefix for
156
156
  # all requests. Can also be the options Hash.
157
- # @param params [Hash] Hash of URI query unencoded key/value pairs.
158
- # @param headers [Hash] unencoded HTTP header key/value pairs.
157
+ # @param params [Hash, nil] Hash of URI query unencoded key/value pairs.
158
+ # @param headers [Hash, nil] unencoded HTTP header key/value pairs.
159
159
  #
160
160
  # @example
161
161
  # conn.head '/items/1'
@@ -167,10 +167,10 @@ module Faraday
167
167
  # Makes a DELETE HTTP request without a body.
168
168
  # @!scope class
169
169
  #
170
- # @param url [String] The optional String base URL to use as a prefix for
170
+ # @param url [String, URI, nil] The optional String base URL to use as a prefix for
171
171
  # all requests. Can also be the options Hash.
172
- # @param params [Hash] Hash of URI query unencoded key/value pairs.
173
- # @param headers [Hash] unencoded HTTP header key/value pairs.
172
+ # @param params [Hash, nil] Hash of URI query unencoded key/value pairs.
173
+ # @param headers [Hash, nil] unencoded HTTP header key/value pairs.
174
174
  #
175
175
  # @example
176
176
  # conn.delete '/items/1'
@@ -182,10 +182,10 @@ module Faraday
182
182
  # Makes a TRACE HTTP request without a body.
183
183
  # @!scope class
184
184
  #
185
- # @param url [String] The optional String base URL to use as a prefix for
185
+ # @param url [String, URI, nil] The optional String base URL to use as a prefix for
186
186
  # all requests. Can also be the options Hash.
187
- # @param params [Hash] Hash of URI query unencoded key/value pairs.
188
- # @param headers [Hash] unencoded HTTP header key/value pairs.
187
+ # @param params [Hash, nil] Hash of URI query unencoded key/value pairs.
188
+ # @param headers [Hash, nil] unencoded HTTP header key/value pairs.
189
189
  #
190
190
  # @example
191
191
  # conn.connect '/items/1'
@@ -210,9 +210,9 @@ module Faraday
210
210
  #
211
211
  # @overload options(url, params = nil, headers = nil)
212
212
  # Makes an OPTIONS HTTP request to the given URL.
213
- # @param url [String] String base URL to sue as a prefix for all requests.
214
- # @param params [Hash] Hash of URI query unencoded key/value pairs.
215
- # @param headers [Hash] unencoded HTTP header key/value pairs.
213
+ # @param url [String, URI, nil] String base URL to sue as a prefix for all requests.
214
+ # @param params [Hash, nil] Hash of URI query unencoded key/value pairs.
215
+ # @param headers [Hash, nil] unencoded HTTP header key/value pairs.
216
216
  #
217
217
  # @example
218
218
  # conn.options '/items/1'
@@ -233,10 +233,10 @@ module Faraday
233
233
  # Makes a POST HTTP request with a body.
234
234
  # @!scope class
235
235
  #
236
- # @param url [String] The optional String base URL to use as a prefix for
236
+ # @param url [String, URI, nil] The optional String base URL to use as a prefix for
237
237
  # all requests. Can also be the options Hash.
238
- # @param body [String] body for the request.
239
- # @param headers [Hash] unencoded HTTP header key/value pairs.
238
+ # @param body [String, nil] body for the request.
239
+ # @param headers [Hash, nil] unencoded HTTP header key/value pairs.
240
240
  #
241
241
  # @example
242
242
  # conn.post '/items', data, content_type: 'application/json'
@@ -255,10 +255,10 @@ module Faraday
255
255
  # Makes a PUT HTTP request with a body.
256
256
  # @!scope class
257
257
  #
258
- # @param url [String] The optional String base URL to use as a prefix for
258
+ # @param url [String, URI, nil] The optional String base URL to use as a prefix for
259
259
  # all requests. Can also be the options Hash.
260
- # @param body [String] body for the request.
261
- # @param headers [Hash] unencoded HTTP header key/value pairs.
260
+ # @param body [String, nil] body for the request.
261
+ # @param headers [Hash, nil] unencoded HTTP header key/value pairs.
262
262
  #
263
263
  # @example
264
264
  # # TODO: Make it a PUT example
@@ -349,11 +349,11 @@ module Faraday
349
349
  # @example
350
350
  #
351
351
  # conn = Faraday::Connection.new { ... }
352
- # conn.url_prefix = "https://sushi.com/api"
352
+ # conn.url_prefix = "https://httpbingo.org/api"
353
353
  # conn.scheme # => https
354
354
  # conn.path_prefix # => "/api"
355
355
  #
356
- # conn.get("nigiri?page=2") # accesses https://sushi.com/api/nigiri
356
+ # conn.get("nigiri?page=2") # accesses https://httpbingo.org/api/nigiri
357
357
  def url_prefix=(url, encoder = nil)
358
358
  uri = @url_prefix = Utils.URI(url)
359
359
  self.path_prefix = uri.path
@@ -390,20 +390,20 @@ module Faraday
390
390
  # Takes a relative url for a request and combines it with the defaults
391
391
  # set on the connection instance.
392
392
  #
393
- # @param url [String]
393
+ # @param url [String, URI, nil]
394
394
  # @param extra_params [Hash]
395
395
  #
396
396
  # @example
397
397
  # conn = Faraday::Connection.new { ... }
398
- # conn.url_prefix = "https://sushi.com/api?token=abc"
398
+ # conn.url_prefix = "https://httpbingo.org/api?token=abc"
399
399
  # conn.scheme # => https
400
400
  # conn.path_prefix # => "/api"
401
401
  #
402
402
  # conn.build_url("nigiri?page=2")
403
- # # => https://sushi.com/api/nigiri?token=abc&page=2
403
+ # # => https://httpbingo.org/api/nigiri?token=abc&page=2
404
404
  #
405
405
  # conn.build_url("nigiri", page: 2)
406
- # # => https://sushi.com/api/nigiri?token=abc&page=2
406
+ # # => https://httpbingo.org/api/nigiri?token=abc&page=2
407
407
  #
408
408
  def build_url(url = nil, extra_params = nil)
409
409
  uri = build_exclusive_url(url)
@@ -423,10 +423,10 @@ module Faraday
423
423
  # Builds and runs the Faraday::Request.
424
424
  #
425
425
  # @param method [Symbol] HTTP method.
426
- # @param url [String, URI] String or URI to access.
427
- # @param body [Object] The request body that will eventually be converted to
426
+ # @param url [String, URI, nil] String or URI to access.
427
+ # @param body [String, nil] The request body that will eventually be converted to
428
428
  # a string.
429
- # @param headers [Hash] unencoded HTTP header key/value pairs.
429
+ # @param headers [Hash, nil] unencoded HTTP header key/value pairs.
430
430
  #
431
431
  # @return [Faraday::Response]
432
432
  def run_request(method, url, body, headers)
@@ -462,7 +462,7 @@ module Faraday
462
462
 
463
463
  # Build an absolute URL based on url_prefix.
464
464
  #
465
- # @param url [String, URI]
465
+ # @param url [String, URI, nil]
466
466
  # @param params [Faraday::Utils::ParamsHash] A Faraday::Utils::ParamsHash to
467
467
  # replace the query values
468
468
  # of the resulting url (default: nil).
@@ -537,7 +537,7 @@ module Faraday
537
537
  end
538
538
 
539
539
  def find_default_proxy
540
- uri = ENV['http_proxy']
540
+ uri = ENV.fetch('http_proxy', nil)
541
541
  return unless uri && !uri.empty?
542
542
 
543
543
  uri = "http://#{uri}" unless uri.match?(/^http/i)
@@ -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
@@ -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
@@ -1,14 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'pp'
4
-
5
3
  module Faraday
6
4
  module Logging
7
5
  # Serves as an integration point to customize logging
8
6
  class Formatter
9
7
  extend Forwardable
10
8
 
11
- DEFAULT_OPTIONS = { headers: true, bodies: false,
9
+ DEFAULT_OPTIONS = { headers: true, bodies: false, errors: false,
12
10
  log_level: :info }.freeze
13
11
 
14
12
  def initialize(logger:, options:)
@@ -37,6 +35,18 @@ module Faraday
37
35
  log_body('response', env[:body]) if env[:body] && log_body?(:response)
38
36
  end
39
37
 
38
+ def error(error)
39
+ return unless log_errors?
40
+
41
+ error_log = proc { error.full_message }
42
+ public_send(log_level, 'error', &error_log)
43
+
44
+ log_headers('error', error.response_headers) if error.respond_to?(:response_headers) && log_headers?(:error)
45
+ return unless error.respond_to?(:response_body) && error.response_body && log_body?(:error)
46
+
47
+ log_body('error', error.response_body)
48
+ end
49
+
40
50
  def filter(filter_word, filter_replacement)
41
51
  @filter.push([filter_word, filter_replacement])
42
52
  end
@@ -77,6 +87,10 @@ module Faraday
77
87
  end
78
88
  end
79
89
 
90
+ def log_errors?
91
+ @options[:errors]
92
+ end
93
+
80
94
  def apply_filters(output)
81
95
  @filter.each do |pattern, replacement|
82
96
  output = output.to_s.gsub(pattern, replacement)
@@ -17,6 +17,9 @@ module Faraday
17
17
  app.call(env).on_complete do |environment|
18
18
  on_complete(environment) if respond_to?(:on_complete)
19
19
  end
20
+ rescue StandardError => e
21
+ on_error(e) if respond_to?(:on_error)
22
+ raise
20
23
  end
21
24
 
22
25
  def close
@@ -53,13 +53,31 @@ module Faraday
53
53
  # Faraday::Middleware.lookup_middleware(:foo)
54
54
  # # => Faraday::Whatever
55
55
  def lookup_middleware(key)
56
- registered_middleware[key] ||
56
+ load_middleware(key) ||
57
57
  raise(Faraday::Error, "#{key.inspect} is not registered on #{self}")
58
58
  end
59
59
 
60
+ private
61
+
60
62
  def middleware_mutex(&block)
61
63
  @middleware_mutex ||= Monitor.new
62
64
  @middleware_mutex.synchronize(&block)
63
65
  end
66
+
67
+ def load_middleware(key)
68
+ value = registered_middleware[key]
69
+ case value
70
+ when Module
71
+ value
72
+ when Symbol, String
73
+ middleware_mutex do
74
+ @registered_middleware[key] = const_get(value)
75
+ end
76
+ when Proc
77
+ middleware_mutex do
78
+ @registered_middleware[key] = value.call
79
+ end
80
+ end
81
+ end
64
82
  end
65
83
  end
@@ -157,6 +157,24 @@ module Faraday
157
157
  %(#<#{self.class}#{attrs.join(' ')}>)
158
158
  end
159
159
 
160
+ def stream_response?
161
+ request.stream_response?
162
+ end
163
+
164
+ def stream_response(&block)
165
+ size = 0
166
+ yielded = false
167
+ block_result = block.call do |chunk| # rubocop:disable Performance/RedundantBlockCall
168
+ if chunk.bytesize.positive? || size.positive?
169
+ yielded = true
170
+ size += chunk.bytesize
171
+ request.on_data.call(chunk, size, self)
172
+ end
173
+ end
174
+ request.on_data.call(+'', 0, self) unless yielded
175
+ block_result
176
+ end
177
+
160
178
  # @private
161
179
  def custom_members
162
180
  @custom_members ||= {}
@@ -6,6 +6,10 @@ module Faraday
6
6
  # @!attribute verify
7
7
  # @return [Boolean] whether to verify SSL certificates or not
8
8
  #
9
+ # @!attribute verify_hostname
10
+ # @return [Boolean] whether to enable hostname verification on server certificates
11
+ # during the handshake or not (see https://github.com/ruby/openssl/pull/60)
12
+ #
9
13
  # @!attribute ca_file
10
14
  # @return [String] CA file
11
15
  #
@@ -41,7 +45,8 @@ module Faraday
41
45
  #
42
46
  # @!attribute max_version
43
47
  # @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,
48
+ class SSLOptions < Options.new(:verify, :verify_hostname,
49
+ :ca_file, :ca_path, :verify_mode,
45
50
  :cert_store, :client_cert, :client_key,
46
51
  :certificate, :private_key, :verify_depth,
47
52
  :version, :min_version, :max_version)
@@ -55,5 +60,10 @@ module Faraday
55
60
  def disable?
56
61
  !verify?
57
62
  end
63
+
64
+ # @return [Boolean] true if should verify_hostname
65
+ def verify_hostname?
66
+ verify_hostname != false
67
+ end
58
68
  end
59
69
  end
@@ -8,7 +8,7 @@ module Faraday
8
8
  # middleware stack (heavily inspired by Rack).
9
9
  #
10
10
  # @example
11
- # Faraday::Connection.new(url: 'http://sushi.com') do |builder|
11
+ # Faraday::Connection.new(url: 'http://httpbingo.org') do |builder|
12
12
  # builder.request :url_encoded # Faraday::Request::UrlEncoded
13
13
  # builder.adapter :net_http # Faraday::Adapter::NetHttp
14
14
  # end
@@ -73,7 +73,7 @@ module Faraday
73
73
  def build
74
74
  raise_if_locked
75
75
  block_given? ? yield(self) : request(:url_encoded)
76
- adapter(Faraday.default_adapter) unless @adapter
76
+ adapter(Faraday.default_adapter, **Faraday.default_adapter_options) unless @adapter
77
77
  end
78
78
 
79
79
  def [](idx)
@@ -23,22 +23,27 @@ module Faraday
23
23
  def on_request(env)
24
24
  return if env.request_headers[KEY]
25
25
 
26
- env.request_headers[KEY] = header_from(@type, *@params)
26
+ env.request_headers[KEY] = header_from(@type, env, *@params)
27
27
  end
28
28
 
29
29
  private
30
30
 
31
31
  # @param type [String, Symbol]
32
+ # @param env [Faraday::Env]
32
33
  # @param params [Array]
33
34
  # @return [String] a header value
34
- def header_from(type, *params)
35
+ def header_from(type, env, *params)
35
36
  if type.to_s.casecmp('basic').zero? && params.size == 2
36
37
  Utils.basic_header_from(*params)
37
38
  elsif params.size != 1
38
39
  raise ArgumentError, "Unexpected params received (got #{params.size} instead of 1)"
39
40
  else
40
41
  value = params.first
41
- value = value.call if value.is_a?(Proc) || value.respond_to?(:call)
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
42
47
  "#{type} #{value}"
43
48
  end
44
49
  end
@@ -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]
@@ -21,7 +21,7 @@ module Faraday
21
21
  # @!attribute headers
22
22
  # @return [Faraday::Utils::Headers] headers
23
23
  # @!attribute body
24
- # @return [Hash] body
24
+ # @return [String] body
25
25
  # @!attribute options
26
26
  # @return [RequestOptions] options
27
27
  #
@@ -26,6 +26,10 @@ module Faraday
26
26
  def on_complete(env)
27
27
  @formatter.response(env)
28
28
  end
29
+
30
+ def on_error(error)
31
+ @formatter.error(error) if @formatter.respond_to?(:error)
32
+ end
29
33
  end
30
34
  end
31
35
  end
@@ -132,7 +132,12 @@ module Faraday
132
132
 
133
133
  # Join multiple values with a comma.
134
134
  def add_parsed(key, value)
135
- self[key] ? self[key] << ', ' << value : self[key] = value
135
+ if key?(key)
136
+ self[key] = self[key].to_s
137
+ self[key] << ', ' << value
138
+ else
139
+ self[key] = value
140
+ end
136
141
  end
137
142
  end
138
143
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Faraday
4
- VERSION = '2.0.0'
4
+ VERSION = '2.7.0'
5
5
  end
data/lib/faraday.rb CHANGED
@@ -17,7 +17,7 @@ require 'faraday/middleware'
17
17
  require 'faraday/adapter'
18
18
  require 'faraday/request'
19
19
  require 'faraday/response'
20
-
20
+ require 'faraday/net_http'
21
21
  # This is the main namespace for Faraday.
22
22
  #
23
23
  # It provides methods to create {Connection} objects, and HTTP-related
@@ -47,13 +47,17 @@ module Faraday
47
47
 
48
48
  # @overload default_adapter
49
49
  # Gets the Symbol key identifying a default Adapter to use
50
- # for the default {Faraday::Connection}. Defaults to `:test`.
50
+ # for the default {Faraday::Connection}. Defaults to `:net_http`.
51
51
  # @return [Symbol] the default adapter
52
52
  # @overload default_adapter=(adapter)
53
53
  # Updates default adapter while resetting {.default_connection}.
54
54
  # @return [Symbol] the new default_adapter.
55
55
  attr_reader :default_adapter
56
56
 
57
+ # Option for the default_adapter
58
+ # @return [Hash] default_adapter options
59
+ attr_accessor :default_adapter_options
60
+
57
61
  # Documented below, see default_connection
58
62
  attr_writer :default_connection
59
63
 
@@ -148,4 +152,6 @@ module Faraday
148
152
  self.ignore_env_proxy = false
149
153
  self.root_path = File.expand_path __dir__
150
154
  self.lib_path = File.expand_path 'faraday', __dir__
155
+ self.default_adapter = :net_http
156
+ self.default_adapter_options = {}
151
157
  end
@@ -373,5 +373,41 @@ RSpec.describe Faraday::Adapter::Test do
373
373
  it_behaves_like 'does not raise NotFound even when headers do not satisfy the strict check', '/with_user_agent', { authorization: 'Bearer m_ck', user_agent: 'My Agent' }
374
374
  it_behaves_like 'does not raise NotFound even when headers do not satisfy the strict check', '/with_user_agent', { authorization: 'Bearer m_ck', user_agent: 'My Agent', x_special: 'special' }
375
375
  end
376
+
377
+ describe 'body_match?' do
378
+ let(:stubs) do
379
+ described_class::Stubs.new do |stubs|
380
+ stubs.post('/no_check') { [200, {}, 'ok'] }
381
+ stubs.post('/with_string', 'abc') { [200, {}, 'ok'] }
382
+ stubs.post(
383
+ '/with_proc',
384
+ ->(request_body) { JSON.parse(request_body, symbolize_names: true) == { x: '!', a: [{ m: [{ a: true }], n: 123 }] } },
385
+ { content_type: 'application/json' }
386
+ ) do
387
+ [200, {}, 'ok']
388
+ end
389
+ end
390
+ end
391
+
392
+ context 'when trying without any args for body' do
393
+ subject(:without_body) { connection.post('/no_check') }
394
+
395
+ it { expect(without_body.status).to eq 200 }
396
+ end
397
+
398
+ context 'when trying with string body stubs' do
399
+ subject(:with_string) { connection.post('/with_string', 'abc') }
400
+
401
+ it { expect(with_string.status).to eq 200 }
402
+ end
403
+
404
+ context 'when trying with proc body stubs' do
405
+ subject(:with_proc) do
406
+ connection.post('/with_proc', JSON.dump(a: [{ n: 123, m: [{ a: true }] }], x: '!'), { 'Content-Type' => 'application/json' })
407
+ end
408
+
409
+ it { expect(with_proc.status).to eq 200 }
410
+ end
411
+ end
376
412
  end
377
413
  end