faraday 2.9.0 → 2.12.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1 -1
- data/Rakefile +3 -0
- data/lib/faraday/adapter.rb +1 -1
- data/lib/faraday/connection.rb +15 -6
- data/lib/faraday/error.rb +4 -0
- data/lib/faraday/logging/formatter.rb +6 -6
- data/lib/faraday/middleware.rb +40 -1
- data/lib/faraday/options/env.rb +1 -1
- data/lib/faraday/options/ssl_options.rb +4 -1
- data/lib/faraday/rack_builder.rb +15 -15
- data/lib/faraday/response/json.rb +2 -1
- data/lib/faraday/response/raise_error.rb +17 -17
- data/lib/faraday/utils/headers.rb +8 -2
- data/lib/faraday/version.rb +1 -1
- data/spec/faraday/connection_spec.rb +2 -2
- data/spec/faraday/error_spec.rb +10 -2
- data/spec/faraday/middleware_spec.rb +143 -0
- data/spec/faraday/params_encoders/nested_spec.rb +2 -1
- data/spec/faraday/response/json_spec.rb +17 -0
- data/spec/faraday/response/logger_spec.rb +20 -0
- data/spec/faraday/response/raise_error_spec.rb +74 -10
- data/spec/faraday/utils/headers_spec.rb +9 -0
- data/spec/faraday/utils_spec.rb +2 -1
- data/spec/faraday_spec.rb +3 -1
- data/spec/support/faraday_middleware_subclasses.rb +18 -0
- metadata +40 -10
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: bfb424c45e703a33fd819b31c8ee41c9e4e30874b280530a19ce8ae320570ef9
         | 
| 4 | 
            +
              data.tar.gz: c1a1a5b7aab4f393908958701959f7b41fd303ca4da906c1b4c0581a13c590db
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 6d4d18e2006ac83dfd22aff834b4fe3c983bfbf578b6850944d35cfbb1ca40ba58ce07414821bc3e604ca3310c85500d5d2b8de7c33b0e6147f24484fcae688f
         | 
| 7 | 
            +
              data.tar.gz: 9cc8057d003f09a02bbdb9a29b920003beff58391c3bf86838ae61b2e9aaac4782d5764286f824b24d486e8dee202cc2d892ec3f658db6b710d5088d5836be3c
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -517,7 +517,7 @@ Breaking changes: | |
| 517 517 | 
             
            - Drop support for Ruby 1.8
         | 
| 518 518 |  | 
| 519 519 | 
             
            Features:
         | 
| 520 | 
            -
            - Include wrapped exception/ | 
| 520 | 
            +
            - Include wrapped exception/response in ClientErrors
         | 
| 521 521 | 
             
            - Add `response.reason_phrase`
         | 
| 522 522 | 
             
            - Provide option to selectively skip logging request/response headers
         | 
| 523 523 | 
             
            - Add regex support for pattern matching in `test` adapter
         | 
    
        data/Rakefile
    CHANGED
    
    
    
        data/lib/faraday/adapter.rb
    CHANGED
    
    
    
        data/lib/faraday/connection.rb
    CHANGED
    
    | @@ -314,15 +314,23 @@ module Faraday | |
| 314 314 | 
             
                #
         | 
| 315 315 | 
             
                # @yield a block to execute multiple requests.
         | 
| 316 316 | 
             
                # @return [void]
         | 
| 317 | 
            -
                def in_parallel(manager = nil)
         | 
| 317 | 
            +
                def in_parallel(manager = nil, &block)
         | 
| 318 318 | 
             
                  @parallel_manager = manager || default_parallel_manager do
         | 
| 319 319 | 
             
                    warn 'Warning: `in_parallel` called but no parallel-capable adapter ' \
         | 
| 320 320 | 
             
                         'on Faraday stack'
         | 
| 321 321 | 
             
                    warn caller[2, 10].join("\n")
         | 
| 322 322 | 
             
                    nil
         | 
| 323 323 | 
             
                  end
         | 
| 324 | 
            -
                  yield
         | 
| 325 | 
            -
             | 
| 324 | 
            +
                  return yield unless @parallel_manager
         | 
| 325 | 
            +
             | 
| 326 | 
            +
                  if @parallel_manager.respond_to?(:execute)
         | 
| 327 | 
            +
                    # Execute is the new method that is responsible for executing the block.
         | 
| 328 | 
            +
                    @parallel_manager.execute(&block)
         | 
| 329 | 
            +
                  else
         | 
| 330 | 
            +
                    # TODO: Old behaviour, deprecate and remove in 3.0
         | 
| 331 | 
            +
                    yield
         | 
| 332 | 
            +
                    @parallel_manager.run
         | 
| 333 | 
            +
                  end
         | 
| 326 334 | 
             
                ensure
         | 
| 327 335 | 
             
                  @parallel_manager = nil
         | 
| 328 336 | 
             
                end
         | 
| @@ -423,8 +431,8 @@ module Faraday | |
| 423 431 | 
             
                #
         | 
| 424 432 | 
             
                # @param method [Symbol] HTTP method.
         | 
| 425 433 | 
             
                # @param url [String, URI, nil] String or URI to access.
         | 
| 426 | 
            -
                # @param body [String, nil] The request body that will eventually be converted to
         | 
| 427 | 
            -
                #             a string.
         | 
| 434 | 
            +
                # @param body [String, Hash, Array, nil] The request body that will eventually be converted to
         | 
| 435 | 
            +
                #             a string; middlewares can be used to support more complex types.
         | 
| 428 436 | 
             
                # @param headers [Hash, nil] unencoded HTTP header key/value pairs.
         | 
| 429 437 | 
             
                #
         | 
| 430 438 | 
             
                # @return [Faraday::Response]
         | 
| @@ -473,7 +481,8 @@ module Faraday | |
| 473 481 | 
             
                  if url && !base.path.end_with?('/')
         | 
| 474 482 | 
             
                    base.path = "#{base.path}/" # ensure trailing slash
         | 
| 475 483 | 
             
                  end
         | 
| 476 | 
            -
                  url  | 
| 484 | 
            +
                  # Ensure relative url will be parsed correctly (such as `service:search` )
         | 
| 485 | 
            +
                  url = "./#{url}" if url.respond_to?(:start_with?) && !url.start_with?('http://', 'https://', '/', './', '../')
         | 
| 477 486 | 
             
                  uri = url ? base + url : base
         | 
| 478 487 | 
             
                  if params
         | 
| 479 488 | 
             
                    uri.query = params.to_query(params_encoder || options.params_encoder)
         | 
    
        data/lib/faraday/error.rb
    CHANGED
    
    | @@ -158,4 +158,8 @@ module Faraday | |
| 158 158 | 
             
              # Raised by middlewares that parse the response, like the JSON response middleware.
         | 
| 159 159 | 
             
              class ParsingError < Error
         | 
| 160 160 | 
             
              end
         | 
| 161 | 
            +
             | 
| 162 | 
            +
              # Raised by Faraday::Middleware and subclasses when invalid default_options are used
         | 
| 163 | 
            +
              class InitializationError < Error
         | 
| 164 | 
            +
              end
         | 
| 161 165 | 
             
            end
         | 
| @@ -23,8 +23,8 @@ module Faraday | |
| 23 23 | 
             
                  def_delegators :@logger, :debug, :info, :warn, :error, :fatal
         | 
| 24 24 |  | 
| 25 25 | 
             
                  def request(env)
         | 
| 26 | 
            -
                    public_send(log_level | 
| 27 | 
            -
                      "#{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)}"
         | 
| 28 28 | 
             
                    end
         | 
| 29 29 |  | 
| 30 30 | 
             
                    log_headers('request', env.request_headers) if log_headers?(:request)
         | 
| @@ -32,7 +32,7 @@ module Faraday | |
| 32 32 | 
             
                  end
         | 
| 33 33 |  | 
| 34 34 | 
             
                  def response(env)
         | 
| 35 | 
            -
                    public_send(log_level | 
| 35 | 
            +
                    public_send(log_level) { "response: Status #{env.status}" }
         | 
| 36 36 |  | 
| 37 37 | 
             
                    log_headers('response', env.response_headers) if log_headers?(:response)
         | 
| 38 38 | 
             
                    log_body('response', env[:body]) if env[:body] && log_body?(:response)
         | 
| @@ -41,7 +41,7 @@ module Faraday | |
| 41 41 | 
             
                  def exception(exc)
         | 
| 42 42 | 
             
                    return unless log_errors?
         | 
| 43 43 |  | 
| 44 | 
            -
                    public_send(log_level | 
| 44 | 
            +
                    public_send(log_level) { "error: #{exc.full_message}" }
         | 
| 45 45 |  | 
| 46 46 | 
             
                    log_headers('error', exc.response_headers) if exc.respond_to?(:response_headers) && log_headers?(:error)
         | 
| 47 47 | 
             
                    return unless exc.respond_to?(:response_body) && exc.response_body && log_body?(:error)
         | 
| @@ -107,11 +107,11 @@ module Faraday | |
| 107 107 | 
             
                  end
         | 
| 108 108 |  | 
| 109 109 | 
             
                  def log_headers(type, headers)
         | 
| 110 | 
            -
                    public_send(log_level | 
| 110 | 
            +
                    public_send(log_level) { "#{type}: #{apply_filters(dump_headers(headers))}" }
         | 
| 111 111 | 
             
                  end
         | 
| 112 112 |  | 
| 113 113 | 
             
                  def log_body(type, body)
         | 
| 114 | 
            -
                    public_send(log_level | 
| 114 | 
            +
                    public_send(log_level) { "#{type}: #{apply_filters(dump_body(body))}" }
         | 
| 115 115 | 
             
                  end
         | 
| 116 116 | 
             
                end
         | 
| 117 117 | 
             
              end
         | 
    
        data/lib/faraday/middleware.rb
    CHANGED
    
    | @@ -1,5 +1,7 @@ | |
| 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
         | 
| @@ -7,9 +9,46 @@ module Faraday | |
| 7 9 |  | 
| 8 10 | 
             
                attr_reader :app, :options
         | 
| 9 11 |  | 
| 12 | 
            +
                DEFAULT_OPTIONS = {}.freeze
         | 
| 13 | 
            +
                LOCK = Mutex.new
         | 
| 14 | 
            +
             | 
| 10 15 | 
             
                def initialize(app = nil, options = {})
         | 
| 11 16 | 
             
                  @app = app
         | 
| 12 | 
            -
                  @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
         | 
| 13 52 | 
             
                end
         | 
| 14 53 |  | 
| 15 54 | 
             
                def call(env)
         | 
    
        data/lib/faraday/options/env.rb
    CHANGED
    
    | @@ -169,7 +169,7 @@ module Faraday | |
| 169 169 | 
             
                def stream_response(&block)
         | 
| 170 170 | 
             
                  size = 0
         | 
| 171 171 | 
             
                  yielded = false
         | 
| 172 | 
            -
                  block_result = block.call do |chunk| | 
| 172 | 
            +
                  block_result = block.call do |chunk|
         | 
| 173 173 | 
             
                    if chunk.bytesize.positive? || size.positive?
         | 
| 174 174 | 
             
                      yielded = true
         | 
| 175 175 | 
             
                      size += chunk.bytesize
         | 
| @@ -46,12 +46,15 @@ module Faraday | |
| 46 46 | 
             
              #   #
         | 
| 47 47 | 
             
              #   # @!attribute max_version
         | 
| 48 48 | 
             
              #   #   @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)
         | 
| 49 | 
            +
              #   #
         | 
| 50 | 
            +
              #   # @!attribute ciphers
         | 
| 51 | 
            +
              #   #   @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)
         | 
| 49 52 | 
             
              #   class SSLOptions < Options; end
         | 
| 50 53 | 
             
              SSLOptions = Options.new(:verify, :verify_hostname,
         | 
| 51 54 | 
             
                                       :ca_file, :ca_path, :verify_mode,
         | 
| 52 55 | 
             
                                       :cert_store, :client_cert, :client_key,
         | 
| 53 56 | 
             
                                       :certificate, :private_key, :verify_depth,
         | 
| 54 | 
            -
                                       :version, :min_version, :max_version) do
         | 
| 57 | 
            +
                                       :version, :min_version, :max_version, :ciphers) do
         | 
| 55 58 | 
             
                # @return [Boolean] true if should verify
         | 
| 56 59 | 
             
                def verify?
         | 
| 57 60 | 
             
                  verify != false
         | 
    
        data/lib/faraday/rack_builder.rb
    CHANGED
    
    | @@ -88,22 +88,22 @@ module Faraday | |
| 88 88 | 
             
                  @handlers.frozen?
         | 
| 89 89 | 
             
                end
         | 
| 90 90 |  | 
| 91 | 
            -
                 | 
| 91 | 
            +
                def use(klass, ...)
         | 
| 92 92 | 
             
                  if klass.is_a? Symbol
         | 
| 93 | 
            -
                    use_symbol(Faraday::Middleware, klass,  | 
| 93 | 
            +
                    use_symbol(Faraday::Middleware, klass, ...)
         | 
| 94 94 | 
             
                  else
         | 
| 95 95 | 
             
                    raise_if_locked
         | 
| 96 96 | 
             
                    raise_if_adapter(klass)
         | 
| 97 | 
            -
                    @handlers << self.class::Handler.new(klass,  | 
| 97 | 
            +
                    @handlers << self.class::Handler.new(klass, ...)
         | 
| 98 98 | 
             
                  end
         | 
| 99 99 | 
             
                end
         | 
| 100 100 |  | 
| 101 | 
            -
                 | 
| 102 | 
            -
                  use_symbol(Faraday::Request, key,  | 
| 101 | 
            +
                def request(key, ...)
         | 
| 102 | 
            +
                  use_symbol(Faraday::Request, key, ...)
         | 
| 103 103 | 
             
                end
         | 
| 104 104 |  | 
| 105 | 
            -
                 | 
| 106 | 
            -
                  use_symbol(Faraday::Response,  | 
| 105 | 
            +
                def response(...)
         | 
| 106 | 
            +
                  use_symbol(Faraday::Response, ...)
         | 
| 107 107 | 
             
                end
         | 
| 108 108 |  | 
| 109 109 | 
             
                ruby2_keywords def adapter(klass = NO_ARGUMENT, *args, &block)
         | 
| @@ -115,25 +115,25 @@ module Faraday | |
| 115 115 |  | 
| 116 116 | 
             
                ## methods to push onto the various positions in the stack:
         | 
| 117 117 |  | 
| 118 | 
            -
                 | 
| 118 | 
            +
                def insert(index, ...)
         | 
| 119 119 | 
             
                  raise_if_locked
         | 
| 120 120 | 
             
                  index = assert_index(index)
         | 
| 121 | 
            -
                  handler = self.class::Handler.new( | 
| 121 | 
            +
                  handler = self.class::Handler.new(...)
         | 
| 122 122 | 
             
                  @handlers.insert(index, handler)
         | 
| 123 123 | 
             
                end
         | 
| 124 124 |  | 
| 125 125 | 
             
                alias insert_before insert
         | 
| 126 126 |  | 
| 127 | 
            -
                 | 
| 127 | 
            +
                def insert_after(index, ...)
         | 
| 128 128 | 
             
                  index = assert_index(index)
         | 
| 129 | 
            -
                  insert(index + 1,  | 
| 129 | 
            +
                  insert(index + 1, ...)
         | 
| 130 130 | 
             
                end
         | 
| 131 131 |  | 
| 132 | 
            -
                 | 
| 132 | 
            +
                def swap(index, ...)
         | 
| 133 133 | 
             
                  raise_if_locked
         | 
| 134 134 | 
             
                  index = assert_index(index)
         | 
| 135 135 | 
             
                  @handlers.delete_at(index)
         | 
| 136 | 
            -
                  insert(index,  | 
| 136 | 
            +
                  insert(index, ...)
         | 
| 137 137 | 
             
                end
         | 
| 138 138 |  | 
| 139 139 | 
             
                def delete(handler)
         | 
| @@ -237,8 +237,8 @@ module Faraday | |
| 237 237 | 
             
                  klass <= Faraday::Adapter
         | 
| 238 238 | 
             
                end
         | 
| 239 239 |  | 
| 240 | 
            -
                 | 
| 241 | 
            -
                  use(mod.lookup_middleware(key),  | 
| 240 | 
            +
                def use_symbol(mod, key, ...)
         | 
| 241 | 
            +
                  use(mod.lookup_middleware(key), ...)
         | 
| 242 242 | 
             
                end
         | 
| 243 243 |  | 
| 244 244 | 
             
                def assert_index(index)
         | 
| @@ -60,7 +60,8 @@ module Faraday | |
| 60 60 | 
             
                    @decoder_options =
         | 
| 61 61 | 
             
                      if @decoder_options.is_a?(Array) && @decoder_options.size >= 2
         | 
| 62 62 | 
             
                        @decoder_options.slice(0, 2)
         | 
| 63 | 
            -
                      elsif @decoder_options | 
| 63 | 
            +
                      elsif @decoder_options&.respond_to?(:load) # rubocop:disable Lint/RedundantSafeNavigation
         | 
| 64 | 
            +
                        # In some versions of Rails, `nil` responds to `load` - hence the safe navigation check above
         | 
| 64 65 | 
             
                        [@decoder_options, :load]
         | 
| 65 66 | 
             
                      else
         | 
| 66 67 | 
             
                        [::JSON, :parse]
         | 
| @@ -8,30 +8,30 @@ module Faraday | |
| 8 8 | 
             
                  # rubocop:disable Naming/ConstantName
         | 
| 9 9 | 
             
                  ClientErrorStatuses = (400...500)
         | 
| 10 10 | 
             
                  ServerErrorStatuses = (500...600)
         | 
| 11 | 
            +
                  ClientErrorStatusesWithCustomExceptions = {
         | 
| 12 | 
            +
                    400 => Faraday::BadRequestError,
         | 
| 13 | 
            +
                    401 => Faraday::UnauthorizedError,
         | 
| 14 | 
            +
                    403 => Faraday::ForbiddenError,
         | 
| 15 | 
            +
                    404 => Faraday::ResourceNotFound,
         | 
| 16 | 
            +
                    408 => Faraday::RequestTimeoutError,
         | 
| 17 | 
            +
                    409 => Faraday::ConflictError,
         | 
| 18 | 
            +
                    422 => Faraday::UnprocessableEntityError,
         | 
| 19 | 
            +
                    429 => Faraday::TooManyRequestsError
         | 
| 20 | 
            +
                  }.freeze
         | 
| 11 21 | 
             
                  # rubocop:enable Naming/ConstantName
         | 
| 12 22 |  | 
| 23 | 
            +
                  DEFAULT_OPTIONS = { include_request: true, allowed_statuses: [] }.freeze
         | 
| 24 | 
            +
             | 
| 13 25 | 
             
                  def on_complete(env)
         | 
| 26 | 
            +
                    return if Array(options[:allowed_statuses]).include?(env[:status])
         | 
| 27 | 
            +
             | 
| 14 28 | 
             
                    case env[:status]
         | 
| 15 | 
            -
                    when  | 
| 16 | 
            -
                      raise  | 
| 17 | 
            -
                    when 401
         | 
| 18 | 
            -
                      raise Faraday::UnauthorizedError, response_values(env)
         | 
| 19 | 
            -
                    when 403
         | 
| 20 | 
            -
                      raise Faraday::ForbiddenError, response_values(env)
         | 
| 21 | 
            -
                    when 404
         | 
| 22 | 
            -
                      raise Faraday::ResourceNotFound, response_values(env)
         | 
| 29 | 
            +
                    when *ClientErrorStatusesWithCustomExceptions.keys
         | 
| 30 | 
            +
                      raise ClientErrorStatusesWithCustomExceptions[env[:status]], response_values(env)
         | 
| 23 31 | 
             
                    when 407
         | 
| 24 32 | 
             
                      # mimic the behavior that we get with proxy requests with HTTPS
         | 
| 25 33 | 
             
                      msg = %(407 "Proxy Authentication Required")
         | 
| 26 34 | 
             
                      raise Faraday::ProxyAuthError.new(msg, response_values(env))
         | 
| 27 | 
            -
                    when 408
         | 
| 28 | 
            -
                      raise Faraday::RequestTimeoutError, response_values(env)
         | 
| 29 | 
            -
                    when 409
         | 
| 30 | 
            -
                      raise Faraday::ConflictError, response_values(env)
         | 
| 31 | 
            -
                    when 422
         | 
| 32 | 
            -
                      raise Faraday::UnprocessableEntityError, response_values(env)
         | 
| 33 | 
            -
                    when 429
         | 
| 34 | 
            -
                      raise Faraday::TooManyRequestsError, response_values(env)
         | 
| 35 35 | 
             
                    when ClientErrorStatuses
         | 
| 36 36 | 
             
                      raise Faraday::ClientError, response_values(env)
         | 
| 37 37 | 
             
                    when ServerErrorStatuses
         | 
| @@ -58,7 +58,7 @@ module Faraday | |
| 58 58 |  | 
| 59 59 | 
             
                    # Include the request data by default. If the middleware was explicitly
         | 
| 60 60 | 
             
                    # configured to _not_ include request data, then omit it.
         | 
| 61 | 
            -
                    return response unless options | 
| 61 | 
            +
                    return response unless options[:include_request]
         | 
| 62 62 |  | 
| 63 63 | 
             
                    response.merge(
         | 
| 64 64 | 
             
                      request: {
         | 
| @@ -62,10 +62,10 @@ module Faraday | |
| 62 62 | 
             
                    super(key, val)
         | 
| 63 63 | 
             
                  end
         | 
| 64 64 |  | 
| 65 | 
            -
                  def fetch(key,  | 
| 65 | 
            +
                  def fetch(key, ...)
         | 
| 66 66 | 
             
                    key = KeyMap[key]
         | 
| 67 67 | 
             
                    key = @names.fetch(key.downcase, key)
         | 
| 68 | 
            -
                    super(key,  | 
| 68 | 
            +
                    super(key, ...)
         | 
| 69 69 | 
             
                  end
         | 
| 70 70 |  | 
| 71 71 | 
             
                  def delete(key)
         | 
| @@ -77,6 +77,12 @@ module Faraday | |
| 77 77 | 
             
                    super(key)
         | 
| 78 78 | 
             
                  end
         | 
| 79 79 |  | 
| 80 | 
            +
                  def dig(key, *rest)
         | 
| 81 | 
            +
                    key = KeyMap[key]
         | 
| 82 | 
            +
                    key = @names.fetch(key.downcase, key)
         | 
| 83 | 
            +
                    super(key, *rest)
         | 
| 84 | 
            +
                  end
         | 
| 85 | 
            +
             | 
| 80 86 | 
             
                  def include?(key)
         | 
| 81 87 | 
             
                    @names.include? key.downcase
         | 
| 82 88 | 
             
                  end
         | 
    
        data/lib/faraday/version.rb
    CHANGED
    
    
| @@ -300,14 +300,14 @@ RSpec.describe Faraday::Connection do | |
| 300 300 | 
             
                  it 'joins url to base when used relative path' do
         | 
| 301 301 | 
             
                    conn = Faraday.new(url: url)
         | 
| 302 302 | 
             
                    uri = conn.build_exclusive_url('service:search?limit=400')
         | 
| 303 | 
            -
                    expect(uri.to_s).to eq('http://service.com/service | 
| 303 | 
            +
                    expect(uri.to_s).to eq('http://service.com/service:search?limit=400')
         | 
| 304 304 | 
             
                  end
         | 
| 305 305 |  | 
| 306 306 | 
             
                  it 'joins url to base when used with path prefix' do
         | 
| 307 307 | 
             
                    conn = Faraday.new(url: url)
         | 
| 308 308 | 
             
                    conn.path_prefix = '/api'
         | 
| 309 309 | 
             
                    uri = conn.build_exclusive_url('service:search?limit=400')
         | 
| 310 | 
            -
                    expect(uri.to_s).to eq('http://service.com/api/service | 
| 310 | 
            +
                    expect(uri.to_s).to eq('http://service.com/api/service:search?limit=400')
         | 
| 311 311 | 
             
                  end
         | 
| 312 312 | 
             
                end
         | 
| 313 313 |  | 
    
        data/spec/faraday/error_spec.rb
    CHANGED
    
    | @@ -24,7 +24,11 @@ RSpec.describe Faraday::Error do | |
| 24 24 | 
             
                  it { expect(subject.wrapped_exception).to be_nil }
         | 
| 25 25 | 
             
                  it { expect(subject.response).to eq(exception) }
         | 
| 26 26 | 
             
                  it { expect(subject.message).to eq('the server responded with status 400') }
         | 
| 27 | 
            -
                   | 
| 27 | 
            +
                  if RUBY_VERSION >= '3.4'
         | 
| 28 | 
            +
                    it { expect(subject.inspect).to eq('#<Faraday::Error response={status: 400}>') }
         | 
| 29 | 
            +
                  else
         | 
| 30 | 
            +
                    it { expect(subject.inspect).to eq('#<Faraday::Error response={:status=>400}>') }
         | 
| 31 | 
            +
                  end
         | 
| 28 32 | 
             
                  it { expect(subject.response_status).to eq(400) }
         | 
| 29 33 | 
             
                  it { expect(subject.response_headers).to be_nil }
         | 
| 30 34 | 
             
                  it { expect(subject.response_body).to be_nil }
         | 
| @@ -61,7 +65,11 @@ RSpec.describe Faraday::Error do | |
| 61 65 | 
             
                  it { expect(subject.wrapped_exception).to be_nil }
         | 
| 62 66 | 
             
                  it { expect(subject.response).to eq(response) }
         | 
| 63 67 | 
             
                  it { expect(subject.message).to eq('custom message') }
         | 
| 64 | 
            -
                   | 
| 68 | 
            +
                  if RUBY_VERSION >= '3.4'
         | 
| 69 | 
            +
                    it { expect(subject.inspect).to eq('#<Faraday::Error response={status: 400}>') }
         | 
| 70 | 
            +
                  else
         | 
| 71 | 
            +
                    it { expect(subject.inspect).to eq('#<Faraday::Error response={:status=>400}>') }
         | 
| 72 | 
            +
                  end
         | 
| 65 73 | 
             
                  it { expect(subject.response_status).to eq(400) }
         | 
| 66 74 | 
             
                  it { expect(subject.response_headers).to be_nil }
         | 
| 67 75 | 
             
                  it { expect(subject.response_body).to be_nil }
         | 
| @@ -67,4 +67,147 @@ RSpec.describe Faraday::Middleware do | |
| 67 67 | 
             
                  end
         | 
| 68 68 | 
             
                end
         | 
| 69 69 | 
             
              end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
              describe '::default_options' do
         | 
| 72 | 
            +
                let(:subclass_no_options) { FaradayMiddlewareSubclasses::SubclassNoOptions }
         | 
| 73 | 
            +
                let(:subclass_one_option) { FaradayMiddlewareSubclasses::SubclassOneOption }
         | 
| 74 | 
            +
                let(:subclass_two_options) { FaradayMiddlewareSubclasses::SubclassTwoOptions }
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                def build_conn(resp_middleware)
         | 
| 77 | 
            +
                  Faraday.new do |c|
         | 
| 78 | 
            +
                    c.adapter :test do |stub|
         | 
| 79 | 
            +
                      stub.get('/success') { [200, {}, 'ok'] }
         | 
| 80 | 
            +
                    end
         | 
| 81 | 
            +
                    c.response resp_middleware
         | 
| 82 | 
            +
                  end
         | 
| 83 | 
            +
                end
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                RSpec.shared_context 'reset @default_options' do
         | 
| 86 | 
            +
                  before(:each) do
         | 
| 87 | 
            +
                    FaradayMiddlewareSubclasses::SubclassNoOptions.instance_variable_set(:@default_options, nil)
         | 
| 88 | 
            +
                    FaradayMiddlewareSubclasses::SubclassOneOption.instance_variable_set(:@default_options, nil)
         | 
| 89 | 
            +
                    FaradayMiddlewareSubclasses::SubclassTwoOptions.instance_variable_set(:@default_options, nil)
         | 
| 90 | 
            +
                    Faraday::Middleware.instance_variable_set(:@default_options, nil)
         | 
| 91 | 
            +
                  end
         | 
| 92 | 
            +
                end
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                after(:all) do
         | 
| 95 | 
            +
                  FaradayMiddlewareSubclasses::SubclassNoOptions.instance_variable_set(:@default_options, nil)
         | 
| 96 | 
            +
                  FaradayMiddlewareSubclasses::SubclassOneOption.instance_variable_set(:@default_options, nil)
         | 
| 97 | 
            +
                  FaradayMiddlewareSubclasses::SubclassTwoOptions.instance_variable_set(:@default_options, nil)
         | 
| 98 | 
            +
                  Faraday::Middleware.instance_variable_set(:@default_options, nil)
         | 
| 99 | 
            +
                end
         | 
| 100 | 
            +
             | 
| 101 | 
            +
                context 'with subclass DEFAULT_OPTIONS defined' do
         | 
| 102 | 
            +
                  include_context 'reset @default_options'
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                  context 'and without application options configured' do
         | 
| 105 | 
            +
                    let(:resp1) { build_conn(:one_option).get('/success') }
         | 
| 106 | 
            +
             | 
| 107 | 
            +
                    it 'has only subclass defaults' do
         | 
| 108 | 
            +
                      expect(Faraday::Middleware.default_options).to eq(Faraday::Middleware::DEFAULT_OPTIONS)
         | 
| 109 | 
            +
                      expect(subclass_no_options.default_options).to eq(subclass_no_options::DEFAULT_OPTIONS)
         | 
| 110 | 
            +
                      expect(subclass_one_option.default_options).to eq(subclass_one_option::DEFAULT_OPTIONS)
         | 
| 111 | 
            +
                      expect(subclass_two_options.default_options).to eq(subclass_two_options::DEFAULT_OPTIONS)
         | 
| 112 | 
            +
                    end
         | 
| 113 | 
            +
             | 
| 114 | 
            +
                    it { expect(resp1.body).to eq('ok') }
         | 
| 115 | 
            +
                  end
         | 
| 116 | 
            +
             | 
| 117 | 
            +
                  context "and with one application's options changed" do
         | 
| 118 | 
            +
                    let(:resp2) { build_conn(:two_options).get('/success') }
         | 
| 119 | 
            +
             | 
| 120 | 
            +
                    before(:each) do
         | 
| 121 | 
            +
                      FaradayMiddlewareSubclasses::SubclassTwoOptions.default_options = { some_option: false }
         | 
| 122 | 
            +
                    end
         | 
| 123 | 
            +
             | 
| 124 | 
            +
                    it 'only updates default options of target subclass' do
         | 
| 125 | 
            +
                      expect(Faraday::Middleware.default_options).to eq(Faraday::Middleware::DEFAULT_OPTIONS)
         | 
| 126 | 
            +
                      expect(subclass_no_options.default_options).to eq(subclass_no_options::DEFAULT_OPTIONS)
         | 
| 127 | 
            +
                      expect(subclass_one_option.default_options).to eq(subclass_one_option::DEFAULT_OPTIONS)
         | 
| 128 | 
            +
                      expect(subclass_two_options.default_options).to eq({ some_option: false, some_other_option: false })
         | 
| 129 | 
            +
                    end
         | 
| 130 | 
            +
             | 
| 131 | 
            +
                    it { expect(resp2.body).to eq('ok') }
         | 
| 132 | 
            +
                  end
         | 
| 133 | 
            +
             | 
| 134 | 
            +
                  context "and with two applications' options changed" do
         | 
| 135 | 
            +
                    let(:resp1) { build_conn(:one_option).get('/success') }
         | 
| 136 | 
            +
                    let(:resp2) { build_conn(:two_options).get('/success') }
         | 
| 137 | 
            +
             | 
| 138 | 
            +
                    before(:each) do
         | 
| 139 | 
            +
                      FaradayMiddlewareSubclasses::SubclassOneOption.default_options = { some_other_option: true }
         | 
| 140 | 
            +
                      FaradayMiddlewareSubclasses::SubclassTwoOptions.default_options = { some_option: false }
         | 
| 141 | 
            +
                    end
         | 
| 142 | 
            +
             | 
| 143 | 
            +
                    it 'updates subclasses and parent independent of each other' do
         | 
| 144 | 
            +
                      expect(Faraday::Middleware.default_options).to eq(Faraday::Middleware::DEFAULT_OPTIONS)
         | 
| 145 | 
            +
                      expect(subclass_no_options.default_options).to eq(subclass_no_options::DEFAULT_OPTIONS)
         | 
| 146 | 
            +
                      expect(subclass_one_option.default_options).to eq({ some_other_option: true })
         | 
| 147 | 
            +
                      expect(subclass_two_options.default_options).to eq({ some_option: false, some_other_option: false })
         | 
| 148 | 
            +
                    end
         | 
| 149 | 
            +
             | 
| 150 | 
            +
                    it { expect(resp1.body).to eq('ok') }
         | 
| 151 | 
            +
                    it { expect(resp2.body).to eq('ok') }
         | 
| 152 | 
            +
                  end
         | 
| 153 | 
            +
                end
         | 
| 154 | 
            +
             | 
| 155 | 
            +
                context 'with FARADAY::MIDDLEWARE DEFAULT_OPTIONS and with Subclass DEFAULT_OPTIONS' do
         | 
| 156 | 
            +
                  before(:each) do
         | 
| 157 | 
            +
                    stub_const('Faraday::Middleware::DEFAULT_OPTIONS', { its_magic: false })
         | 
| 158 | 
            +
                  end
         | 
| 159 | 
            +
             | 
| 160 | 
            +
                  # Must stub Faraday::Middleware::DEFAULT_OPTIONS before resetting default options
         | 
| 161 | 
            +
                  include_context 'reset @default_options'
         | 
| 162 | 
            +
             | 
| 163 | 
            +
                  context 'and without application options configured' do
         | 
| 164 | 
            +
                    let(:resp1) { build_conn(:one_option).get('/success') }
         | 
| 165 | 
            +
             | 
| 166 | 
            +
                    it 'has only subclass defaults' do
         | 
| 167 | 
            +
                      expect(Faraday::Middleware.default_options).to eq(Faraday::Middleware::DEFAULT_OPTIONS)
         | 
| 168 | 
            +
                      expect(FaradayMiddlewareSubclasses::SubclassNoOptions.default_options).to eq({ its_magic: false })
         | 
| 169 | 
            +
                      expect(FaradayMiddlewareSubclasses::SubclassOneOption.default_options).to eq({ its_magic: false, some_other_option: false })
         | 
| 170 | 
            +
                      expect(FaradayMiddlewareSubclasses::SubclassTwoOptions.default_options).to eq({ its_magic: false, some_option: true, some_other_option: false })
         | 
| 171 | 
            +
                    end
         | 
| 172 | 
            +
             | 
| 173 | 
            +
                    it { expect(resp1.body).to eq('ok') }
         | 
| 174 | 
            +
                  end
         | 
| 175 | 
            +
             | 
| 176 | 
            +
                  context "and with two applications' options changed" do
         | 
| 177 | 
            +
                    let(:resp1) { build_conn(:one_option).get('/success') }
         | 
| 178 | 
            +
                    let(:resp2) { build_conn(:two_options).get('/success') }
         | 
| 179 | 
            +
             | 
| 180 | 
            +
                    before(:each) do
         | 
| 181 | 
            +
                      FaradayMiddlewareSubclasses::SubclassOneOption.default_options = { some_other_option: true }
         | 
| 182 | 
            +
                      FaradayMiddlewareSubclasses::SubclassTwoOptions.default_options = { some_option: false }
         | 
| 183 | 
            +
                    end
         | 
| 184 | 
            +
             | 
| 185 | 
            +
                    it 'updates subclasses and parent independent of each other' do
         | 
| 186 | 
            +
                      expect(Faraday::Middleware.default_options).to eq(Faraday::Middleware::DEFAULT_OPTIONS)
         | 
| 187 | 
            +
                      expect(FaradayMiddlewareSubclasses::SubclassNoOptions.default_options).to eq({ its_magic: false })
         | 
| 188 | 
            +
                      expect(FaradayMiddlewareSubclasses::SubclassOneOption.default_options).to eq({ its_magic: false, some_other_option: true })
         | 
| 189 | 
            +
                      expect(FaradayMiddlewareSubclasses::SubclassTwoOptions.default_options).to eq({ its_magic: false, some_option: false, some_other_option: false })
         | 
| 190 | 
            +
                    end
         | 
| 191 | 
            +
             | 
| 192 | 
            +
                    it { expect(resp1.body).to eq('ok') }
         | 
| 193 | 
            +
                    it { expect(resp2.body).to eq('ok') }
         | 
| 194 | 
            +
                  end
         | 
| 195 | 
            +
                end
         | 
| 196 | 
            +
             | 
| 197 | 
            +
                describe 'default_options input validation' do
         | 
| 198 | 
            +
                  include_context 'reset @default_options'
         | 
| 199 | 
            +
             | 
| 200 | 
            +
                  it 'raises error if Faraday::Middleware option does not exist' do
         | 
| 201 | 
            +
                    expect { Faraday::Middleware.default_options = { something_special: true } }.to raise_error(Faraday::InitializationError) do |e|
         | 
| 202 | 
            +
                      expect(e.message).to eq('Invalid options provided. Keys not found in Faraday::Middleware::DEFAULT_OPTIONS: something_special')
         | 
| 203 | 
            +
                    end
         | 
| 204 | 
            +
                  end
         | 
| 205 | 
            +
             | 
| 206 | 
            +
                  it 'raises error if subclass option does not exist' do
         | 
| 207 | 
            +
                    expect { subclass_one_option.default_options = { this_is_a_typo: true } }.to raise_error(Faraday::InitializationError) do |e|
         | 
| 208 | 
            +
                      expect(e.message).to eq('Invalid options provided. Keys not found in FaradayMiddlewareSubclasses::SubclassOneOption::DEFAULT_OPTIONS: this_is_a_typo')
         | 
| 209 | 
            +
                    end
         | 
| 210 | 
            +
                  end
         | 
| 211 | 
            +
                end
         | 
| 212 | 
            +
              end
         | 
| 70 213 | 
             
            end
         | 
| @@ -62,7 +62,8 @@ RSpec.describe Faraday::NestedParamsEncoder do | |
| 62 62 | 
             
              it 'encodes rack compat' do
         | 
| 63 63 | 
             
                params   = { a: [{ one: '1', two: '2' }, '3', ''] }
         | 
| 64 64 | 
             
                result   = Faraday::Utils.unescape(Faraday::NestedParamsEncoder.encode(params)).split('&')
         | 
| 65 | 
            -
                 | 
| 65 | 
            +
                escaped = Rack::Utils.build_nested_query(params)
         | 
| 66 | 
            +
                expected = Rack::Utils.unescape(escaped).split('&')
         | 
| 66 67 | 
             
                expect(result).to match_array(expected)
         | 
| 67 68 | 
             
              end
         | 
| 68 69 |  | 
| @@ -184,6 +184,23 @@ RSpec.describe Faraday::Response::Json, type: :response do | |
| 184 184 | 
             
                    response = process(body)
         | 
| 185 185 | 
             
                    expect(response.body).to eq(result)
         | 
| 186 186 | 
             
                  end
         | 
| 187 | 
            +
             | 
| 188 | 
            +
                  it 'passes relevant options to JSON parse even when nil responds to :load' do
         | 
| 189 | 
            +
                    original_allow_message_expectations_on_nil = RSpec::Mocks.configuration.allow_message_expectations_on_nil
         | 
| 190 | 
            +
                    RSpec::Mocks.configuration.allow_message_expectations_on_nil = true
         | 
| 191 | 
            +
                    allow(nil).to receive(:respond_to?)
         | 
| 192 | 
            +
                      .with(:load)
         | 
| 193 | 
            +
                      .and_return(true)
         | 
| 194 | 
            +
             | 
| 195 | 
            +
                    expect(JSON).to receive(:parse)
         | 
| 196 | 
            +
                      .with(body, { symbolize_names: true })
         | 
| 197 | 
            +
                      .and_return(result)
         | 
| 198 | 
            +
             | 
| 199 | 
            +
                    response = process(body)
         | 
| 200 | 
            +
                    expect(response.body).to eq(result)
         | 
| 201 | 
            +
                  ensure
         | 
| 202 | 
            +
                    RSpec::Mocks.configuration.allow_message_expectations_on_nil = original_allow_message_expectations_on_nil
         | 
| 203 | 
            +
                  end
         | 
| 187 204 | 
             
                end
         | 
| 188 205 | 
             
              end
         | 
| 189 206 | 
             
            end
         | 
| @@ -55,6 +55,26 @@ RSpec.describe Faraday::Response::Logger do | |
| 55 55 | 
             
                end
         | 
| 56 56 | 
             
              end
         | 
| 57 57 |  | 
| 58 | 
            +
              context 'when logger with program name' do
         | 
| 59 | 
            +
                let(:logger) { Logger.new(string_io, progname: 'my_best_program') }
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                it 'logs with program name' do
         | 
| 62 | 
            +
                  conn.get '/hello'
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                  expect(string_io.string).to match('-- my_best_program: request:')
         | 
| 65 | 
            +
                  expect(string_io.string).to match('-- my_best_program: response:')
         | 
| 66 | 
            +
                end
         | 
| 67 | 
            +
              end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
              context 'when logger without program name' do
         | 
| 70 | 
            +
                it 'logs without program name' do
         | 
| 71 | 
            +
                  conn.get '/hello'
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                  expect(string_io.string).to match('-- : request:')
         | 
| 74 | 
            +
                  expect(string_io.string).to match('-- : response:')
         | 
| 75 | 
            +
                end
         | 
| 76 | 
            +
              end
         | 
| 77 | 
            +
             | 
| 58 78 | 
             
              context 'with default formatter' do
         | 
| 59 79 | 
             
                let(:formatter) { instance_double(Faraday::Logging::Formatter, request: true, response: true, filter: []) }
         | 
| 60 80 |  | 
| @@ -194,18 +194,82 @@ RSpec.describe Faraday::Response::RaiseError do | |
| 194 194 | 
             
                  end
         | 
| 195 195 | 
             
                end
         | 
| 196 196 |  | 
| 197 | 
            -
                 | 
| 198 | 
            -
                   | 
| 199 | 
            -
             | 
| 200 | 
            -
             | 
| 201 | 
            -
             | 
| 202 | 
            -
             | 
| 203 | 
            -
             | 
| 204 | 
            -
             | 
| 205 | 
            -
             | 
| 206 | 
            -
             | 
| 197 | 
            +
                describe 'DEFAULT_OPTION: include_request' do
         | 
| 198 | 
            +
                  before(:each) do
         | 
| 199 | 
            +
                    Faraday::Response::RaiseError.instance_variable_set(:@default_options, nil)
         | 
| 200 | 
            +
                    Faraday::Middleware.instance_variable_set(:@default_options, nil)
         | 
| 201 | 
            +
                  end
         | 
| 202 | 
            +
             | 
| 203 | 
            +
                  after(:all) do
         | 
| 204 | 
            +
                    Faraday::Response::RaiseError.instance_variable_set(:@default_options, nil)
         | 
| 205 | 
            +
                    Faraday::Middleware.instance_variable_set(:@default_options, nil)
         | 
| 206 | 
            +
                  end
         | 
| 207 | 
            +
             | 
| 208 | 
            +
                  context 'when RaiseError DEFAULT_OPTION (include_request: true) is used' do
         | 
| 209 | 
            +
                    it 'includes request info in the exception' do
         | 
| 210 | 
            +
                      expect { perform_request }.to raise_error(Faraday::BadRequestError) do |ex|
         | 
| 211 | 
            +
                        expect(ex.response.keys).to contain_exactly(
         | 
| 212 | 
            +
                          :status,
         | 
| 213 | 
            +
                          :headers,
         | 
| 214 | 
            +
                          :body,
         | 
| 215 | 
            +
                          :request
         | 
| 216 | 
            +
                        )
         | 
| 217 | 
            +
                      end
         | 
| 207 218 | 
             
                    end
         | 
| 208 219 | 
             
                  end
         | 
| 220 | 
            +
             | 
| 221 | 
            +
                  context 'when application sets default_options `include_request: false`' do
         | 
| 222 | 
            +
                    before(:each) do
         | 
| 223 | 
            +
                      Faraday::Response::RaiseError.default_options = { include_request: false }
         | 
| 224 | 
            +
                    end
         | 
| 225 | 
            +
             | 
| 226 | 
            +
                    context 'and when include_request option is omitted' do
         | 
| 227 | 
            +
                      it 'does not include request info in the exception' do
         | 
| 228 | 
            +
                        expect { perform_request }.to raise_error(Faraday::BadRequestError) do |ex|
         | 
| 229 | 
            +
                          expect(ex.response.keys).to contain_exactly(
         | 
| 230 | 
            +
                            :status,
         | 
| 231 | 
            +
                            :headers,
         | 
| 232 | 
            +
                            :body
         | 
| 233 | 
            +
                          )
         | 
| 234 | 
            +
                        end
         | 
| 235 | 
            +
                      end
         | 
| 236 | 
            +
                    end
         | 
| 237 | 
            +
             | 
| 238 | 
            +
                    context 'and when include_request option is explicitly set for instance' do
         | 
| 239 | 
            +
                      let(:middleware_options) { { include_request: true } }
         | 
| 240 | 
            +
             | 
| 241 | 
            +
                      it 'includes request info in the exception' do
         | 
| 242 | 
            +
                        expect { perform_request }.to raise_error(Faraday::BadRequestError) do |ex|
         | 
| 243 | 
            +
                          expect(ex.response.keys).to contain_exactly(
         | 
| 244 | 
            +
                            :status,
         | 
| 245 | 
            +
                            :headers,
         | 
| 246 | 
            +
                            :body,
         | 
| 247 | 
            +
                            :request
         | 
| 248 | 
            +
                          )
         | 
| 249 | 
            +
                        end
         | 
| 250 | 
            +
                      end
         | 
| 251 | 
            +
                    end
         | 
| 252 | 
            +
                  end
         | 
| 253 | 
            +
                end
         | 
| 254 | 
            +
              end
         | 
| 255 | 
            +
             | 
| 256 | 
            +
              describe 'allowing certain status codes' do
         | 
| 257 | 
            +
                let(:conn) do
         | 
| 258 | 
            +
                  Faraday.new do |b|
         | 
| 259 | 
            +
                    b.response :raise_error, allowed_statuses: [404]
         | 
| 260 | 
            +
                    b.adapter :test do |stub|
         | 
| 261 | 
            +
                      stub.get('bad-request') { [400, { 'X-Reason' => 'because' }, 'keep looking'] }
         | 
| 262 | 
            +
                      stub.get('not-found') { [404, { 'X-Reason' => 'because' }, 'keep looking'] }
         | 
| 263 | 
            +
                    end
         | 
| 264 | 
            +
                  end
         | 
| 265 | 
            +
                end
         | 
| 266 | 
            +
             | 
| 267 | 
            +
                it 'raises an error for status codes that are not explicitly allowed' do
         | 
| 268 | 
            +
                  expect { conn.get('bad-request') }.to raise_error(Faraday::BadRequestError)
         | 
| 269 | 
            +
                end
         | 
| 270 | 
            +
             | 
| 271 | 
            +
                it 'does not raise an error for allowed status codes' do
         | 
| 272 | 
            +
                  expect { conn.get('not-found') }.not_to raise_error
         | 
| 209 273 | 
             
                end
         | 
| 210 274 | 
             
              end
         | 
| 211 275 | 
             
            end
         | 
| @@ -56,6 +56,15 @@ RSpec.describe Faraday::Utils::Headers do | |
| 56 56 | 
             
                it { expect(subject.delete('content-type')).to be_nil }
         | 
| 57 57 | 
             
              end
         | 
| 58 58 |  | 
| 59 | 
            +
              describe '#dig' do
         | 
| 60 | 
            +
                before { subject['Content-Type'] = 'application/json' }
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                it { expect(subject&.dig('Content-Type')).to eq('application/json') }
         | 
| 63 | 
            +
                it { expect(subject&.dig('CONTENT-TYPE')).to eq('application/json') }
         | 
| 64 | 
            +
                it { expect(subject&.dig(:content_type)).to eq('application/json') }
         | 
| 65 | 
            +
                it { expect(subject&.dig('invalid')).to be_nil }
         | 
| 66 | 
            +
              end
         | 
| 67 | 
            +
             | 
| 59 68 | 
             
              describe '#parse' do
         | 
| 60 69 | 
             
                context 'when response headers leave http status line out' do
         | 
| 61 70 | 
             
                  let(:headers) { "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n" }
         | 
    
        data/spec/faraday/utils_spec.rb
    CHANGED
    
    
    
        data/spec/faraday_spec.rb
    CHANGED
    
    | @@ -19,7 +19,9 @@ RSpec.describe Faraday do | |
| 19 19 |  | 
| 20 20 | 
             
                it 'uses method_missing on Faraday if there is no proxyable method' do
         | 
| 21 21 | 
             
                  expected_message =
         | 
| 22 | 
            -
                    if RUBY_VERSION >= '3. | 
| 22 | 
            +
                    if RUBY_VERSION >= '3.4'
         | 
| 23 | 
            +
                      "undefined method 'this_method_does_not_exist' for module Faraday"
         | 
| 24 | 
            +
                    elsif RUBY_VERSION >= '3.3'
         | 
| 23 25 | 
             
                      "undefined method `this_method_does_not_exist' for module Faraday"
         | 
| 24 26 | 
             
                    else
         | 
| 25 27 | 
             
                      "undefined method `this_method_does_not_exist' for Faraday:Module"
         | 
| @@ -0,0 +1,18 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module FaradayMiddlewareSubclasses
         | 
| 4 | 
            +
              class SubclassNoOptions < Faraday::Middleware
         | 
| 5 | 
            +
              end
         | 
| 6 | 
            +
             | 
| 7 | 
            +
              class SubclassOneOption < Faraday::Middleware
         | 
| 8 | 
            +
                DEFAULT_OPTIONS = { some_other_option: false }.freeze
         | 
| 9 | 
            +
              end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              class SubclassTwoOptions < Faraday::Middleware
         | 
| 12 | 
            +
                DEFAULT_OPTIONS = { some_option: true, some_other_option: false }.freeze
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
            end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            Faraday::Response.register_middleware(no_options: FaradayMiddlewareSubclasses::SubclassNoOptions)
         | 
| 17 | 
            +
            Faraday::Response.register_middleware(one_option: FaradayMiddlewareSubclasses::SubclassOneOption)
         | 
| 18 | 
            +
            Faraday::Response.register_middleware(two_options: FaradayMiddlewareSubclasses::SubclassTwoOptions)
         | 
    
        metadata
    CHANGED
    
    | @@ -1,16 +1,16 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: faraday
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 2. | 
| 4 | 
            +
              version: 2.12.2
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - "@technoweenie"
         | 
| 8 8 | 
             
            - "@iMacTia"
         | 
| 9 9 | 
             
            - "@olleolleolle"
         | 
| 10 | 
            -
            autorequire: | 
| 10 | 
            +
            autorequire:
         | 
| 11 11 | 
             
            bindir: bin
         | 
| 12 12 | 
             
            cert_chain: []
         | 
| 13 | 
            -
            date: 2024- | 
| 13 | 
            +
            date: 2024-12-09 00:00:00.000000000 Z
         | 
| 14 14 | 
             
            dependencies:
         | 
| 15 15 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 16 16 | 
             
              name: faraday-net_http
         | 
| @@ -21,7 +21,7 @@ dependencies: | |
| 21 21 | 
             
                    version: '2.0'
         | 
| 22 22 | 
             
                - - "<"
         | 
| 23 23 | 
             
                  - !ruby/object:Gem::Version
         | 
| 24 | 
            -
                    version: '3. | 
| 24 | 
            +
                    version: '3.5'
         | 
| 25 25 | 
             
              type: :runtime
         | 
| 26 26 | 
             
              prerelease: false
         | 
| 27 27 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| @@ -31,8 +31,36 @@ dependencies: | |
| 31 31 | 
             
                    version: '2.0'
         | 
| 32 32 | 
             
                - - "<"
         | 
| 33 33 | 
             
                  - !ruby/object:Gem::Version
         | 
| 34 | 
            -
                    version: '3. | 
| 35 | 
            -
             | 
| 34 | 
            +
                    version: '3.5'
         | 
| 35 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 36 | 
            +
              name: json
         | 
| 37 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 38 | 
            +
                requirements:
         | 
| 39 | 
            +
                - - ">="
         | 
| 40 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 41 | 
            +
                    version: '0'
         | 
| 42 | 
            +
              type: :runtime
         | 
| 43 | 
            +
              prerelease: false
         | 
| 44 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 45 | 
            +
                requirements:
         | 
| 46 | 
            +
                - - ">="
         | 
| 47 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 48 | 
            +
                    version: '0'
         | 
| 49 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 50 | 
            +
              name: logger
         | 
| 51 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 52 | 
            +
                requirements:
         | 
| 53 | 
            +
                - - ">="
         | 
| 54 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 55 | 
            +
                    version: '0'
         | 
| 56 | 
            +
              type: :runtime
         | 
| 57 | 
            +
              prerelease: false
         | 
| 58 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 59 | 
            +
                requirements:
         | 
| 60 | 
            +
                - - ">="
         | 
| 61 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 62 | 
            +
                    version: '0'
         | 
| 63 | 
            +
            description:
         | 
| 36 64 | 
             
            email: technoweenie@gmail.com
         | 
| 37 65 | 
             
            executables: []
         | 
| 38 66 | 
             
            extensions: []
         | 
| @@ -107,6 +135,7 @@ files: | |
| 107 135 | 
             
            - spec/spec_helper.rb
         | 
| 108 136 | 
             
            - spec/support/disabling_stub.rb
         | 
| 109 137 | 
             
            - spec/support/fake_safe_buffer.rb
         | 
| 138 | 
            +
            - spec/support/faraday_middleware_subclasses.rb
         | 
| 110 139 | 
             
            - spec/support/helper_methods.rb
         | 
| 111 140 | 
             
            - spec/support/shared_examples/adapter.rb
         | 
| 112 141 | 
             
            - spec/support/shared_examples/params_encoder.rb
         | 
| @@ -117,10 +146,11 @@ licenses: | |
| 117 146 | 
             
            - MIT
         | 
| 118 147 | 
             
            metadata:
         | 
| 119 148 | 
             
              homepage_uri: https://lostisland.github.io/faraday
         | 
| 120 | 
            -
              changelog_uri: https://github.com/lostisland/faraday/releases/tag/v2. | 
| 149 | 
            +
              changelog_uri: https://github.com/lostisland/faraday/releases/tag/v2.12.2
         | 
| 121 150 | 
             
              source_code_uri: https://github.com/lostisland/faraday
         | 
| 122 151 | 
             
              bug_tracker_uri: https://github.com/lostisland/faraday/issues
         | 
| 123 | 
            -
             | 
| 152 | 
            +
              rubygems_mfa_required: 'true'
         | 
| 153 | 
            +
            post_install_message:
         | 
| 124 154 | 
             
            rdoc_options: []
         | 
| 125 155 | 
             
            require_paths:
         | 
| 126 156 | 
             
            - lib
         | 
| @@ -136,8 +166,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 136 166 | 
             
                - !ruby/object:Gem::Version
         | 
| 137 167 | 
             
                  version: '0'
         | 
| 138 168 | 
             
            requirements: []
         | 
| 139 | 
            -
            rubygems_version: 3.5. | 
| 140 | 
            -
            signing_key: | 
| 169 | 
            +
            rubygems_version: 3.5.22
         | 
| 170 | 
            +
            signing_key:
         | 
| 141 171 | 
             
            specification_version: 4
         | 
| 142 172 | 
             
            summary: HTTP/REST API client library.
         | 
| 143 173 | 
             
            test_files: []
         |