faraday 0.11.0 → 1.4.3
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 +5 -5
 - data/CHANGELOG.md +380 -0
 - data/LICENSE.md +1 -1
 - data/README.md +25 -229
 - data/Rakefile +7 -0
 - data/examples/client_spec.rb +65 -0
 - data/examples/client_test.rb +79 -0
 - data/lib/faraday/adapter/httpclient.rb +83 -59
 - data/lib/faraday/adapter/patron.rb +92 -36
 - data/lib/faraday/adapter/rack.rb +30 -13
 - data/lib/faraday/adapter/test.rb +103 -62
 - data/lib/faraday/adapter/typhoeus.rb +7 -115
 - data/lib/faraday/adapter.rb +77 -22
 - data/lib/faraday/adapter_registry.rb +30 -0
 - data/lib/faraday/autoload.rb +42 -36
 - data/lib/faraday/connection.rb +351 -167
 - data/lib/faraday/dependency_loader.rb +37 -0
 - data/lib/faraday/encoders/flat_params_encoder.rb +105 -0
 - data/lib/faraday/encoders/nested_params_encoder.rb +176 -0
 - data/lib/faraday/error.rb +127 -38
 - data/lib/faraday/file_part.rb +128 -0
 - data/lib/faraday/logging/formatter.rb +105 -0
 - data/lib/faraday/methods.rb +6 -0
 - data/lib/faraday/middleware.rb +19 -25
 - data/lib/faraday/middleware_registry.rb +129 -0
 - data/lib/faraday/options/connection_options.rb +22 -0
 - data/lib/faraday/options/env.rb +181 -0
 - data/lib/faraday/options/proxy_options.rb +32 -0
 - data/lib/faraday/options/request_options.rb +22 -0
 - data/lib/faraday/options/ssl_options.rb +59 -0
 - data/lib/faraday/options.rb +58 -207
 - data/lib/faraday/param_part.rb +53 -0
 - data/lib/faraday/parameters.rb +4 -196
 - data/lib/faraday/rack_builder.rb +84 -48
 - data/lib/faraday/request/authorization.rb +44 -30
 - data/lib/faraday/request/basic_authentication.rb +14 -7
 - data/lib/faraday/request/instrumentation.rb +45 -27
 - data/lib/faraday/request/multipart.rb +88 -45
 - data/lib/faraday/request/retry.rb +211 -126
 - data/lib/faraday/request/token_authentication.rb +15 -10
 - data/lib/faraday/request/url_encoded.rb +43 -23
 - data/lib/faraday/request.rb +94 -32
 - data/lib/faraday/response/logger.rb +22 -69
 - data/lib/faraday/response/raise_error.rb +49 -14
 - data/lib/faraday/response.rb +27 -23
 - data/lib/faraday/utils/headers.rb +139 -0
 - data/lib/faraday/utils/params_hash.rb +61 -0
 - data/lib/faraday/utils.rb +38 -238
 - data/lib/faraday/version.rb +5 -0
 - data/lib/faraday.rb +124 -187
 - data/spec/external_adapters/faraday_specs_setup.rb +14 -0
 - data/spec/faraday/adapter/em_http_spec.rb +47 -0
 - data/spec/faraday/adapter/em_synchrony_spec.rb +16 -0
 - data/spec/faraday/adapter/excon_spec.rb +49 -0
 - data/spec/faraday/adapter/httpclient_spec.rb +73 -0
 - data/spec/faraday/adapter/net_http_spec.rb +64 -0
 - data/spec/faraday/adapter/patron_spec.rb +18 -0
 - data/spec/faraday/adapter/rack_spec.rb +8 -0
 - data/spec/faraday/adapter/test_spec.rb +260 -0
 - data/spec/faraday/adapter/typhoeus_spec.rb +7 -0
 - data/spec/faraday/adapter_registry_spec.rb +28 -0
 - data/spec/faraday/adapter_spec.rb +55 -0
 - data/spec/faraday/composite_read_io_spec.rb +80 -0
 - data/spec/faraday/connection_spec.rb +736 -0
 - data/spec/faraday/error_spec.rb +60 -0
 - data/spec/faraday/middleware_spec.rb +52 -0
 - data/spec/faraday/options/env_spec.rb +70 -0
 - data/spec/faraday/options/options_spec.rb +297 -0
 - data/spec/faraday/options/proxy_options_spec.rb +44 -0
 - data/spec/faraday/options/request_options_spec.rb +19 -0
 - data/spec/faraday/params_encoders/flat_spec.rb +42 -0
 - data/spec/faraday/params_encoders/nested_spec.rb +142 -0
 - data/spec/faraday/rack_builder_spec.rb +345 -0
 - data/spec/faraday/request/authorization_spec.rb +88 -0
 - data/spec/faraday/request/instrumentation_spec.rb +76 -0
 - data/spec/faraday/request/multipart_spec.rb +302 -0
 - data/spec/faraday/request/retry_spec.rb +242 -0
 - data/spec/faraday/request/url_encoded_spec.rb +83 -0
 - data/spec/faraday/request_spec.rb +120 -0
 - data/spec/faraday/response/logger_spec.rb +220 -0
 - data/spec/faraday/response/middleware_spec.rb +68 -0
 - data/spec/faraday/response/raise_error_spec.rb +169 -0
 - data/spec/faraday/response_spec.rb +75 -0
 - data/spec/faraday/utils/headers_spec.rb +82 -0
 - data/spec/faraday/utils_spec.rb +56 -0
 - data/spec/faraday_spec.rb +37 -0
 - data/spec/spec_helper.rb +132 -0
 - data/spec/support/disabling_stub.rb +14 -0
 - data/spec/support/fake_safe_buffer.rb +15 -0
 - data/spec/support/helper_methods.rb +133 -0
 - data/spec/support/shared_examples/adapter.rb +105 -0
 - data/spec/support/shared_examples/params_encoder.rb +18 -0
 - data/spec/support/shared_examples/request_method.rb +262 -0
 - data/spec/support/streaming_response_checker.rb +35 -0
 - data/spec/support/webmock_rack_app.rb +68 -0
 - metadata +164 -16
 - data/lib/faraday/adapter/em_http.rb +0 -243
 - data/lib/faraday/adapter/em_http_ssl_patch.rb +0 -56
 - data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +0 -66
 - data/lib/faraday/adapter/em_synchrony.rb +0 -106
 - data/lib/faraday/adapter/excon.rb +0 -80
 - data/lib/faraday/adapter/net_http.rb +0 -135
 - data/lib/faraday/adapter/net_http_persistent.rb +0 -50
 - data/lib/faraday/upload_io.rb +0 -67
 
| 
         @@ -0,0 +1,120 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            RSpec.describe Faraday::Request do
         
     | 
| 
      
 4 
     | 
    
         
            +
              let(:conn) do
         
     | 
| 
      
 5 
     | 
    
         
            +
                Faraday.new(url: 'http://sushi.com/api',
         
     | 
| 
      
 6 
     | 
    
         
            +
                            headers: { 'Mime-Version' => '1.0' },
         
     | 
| 
      
 7 
     | 
    
         
            +
                            request: { oauth: { consumer_key: 'anonymous' } })
         
     | 
| 
      
 8 
     | 
    
         
            +
              end
         
     | 
| 
      
 9 
     | 
    
         
            +
              let(:http_method) { :get }
         
     | 
| 
      
 10 
     | 
    
         
            +
              let(:block) { nil }
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
              subject { conn.build_request(http_method, &block) }
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              context 'when nothing particular is configured' do
         
     | 
| 
      
 15 
     | 
    
         
            +
                it { expect(subject.http_method).to eq(:get) }
         
     | 
| 
      
 16 
     | 
    
         
            +
                it { expect(subject.to_env(conn).ssl.verify).to be_falsey }
         
     | 
| 
      
 17 
     | 
    
         
            +
              end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              context 'when HTTP method is post' do
         
     | 
| 
      
 20 
     | 
    
         
            +
                let(:http_method) { :post }
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                it { expect(subject.http_method).to eq(:post) }
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
              describe 'deprecate method for HTTP method' do
         
     | 
| 
      
 26 
     | 
    
         
            +
                let(:http_method) { :post }
         
     | 
| 
      
 27 
     | 
    
         
            +
                let(:expected_warning) do
         
     | 
| 
      
 28 
     | 
    
         
            +
                  %r{WARNING: `Faraday::Request#method` is deprecated; use `#http_method` instead. It will be removed in or after version 2.0.\n`Faraday::Request#method` called from .+/spec/faraday/request_spec.rb:\d+.}
         
     | 
| 
      
 29 
     | 
    
         
            +
                end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                it { expect(subject.method).to eq(:post) }
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                it { expect { subject.method }.to output(expected_warning).to_stderr }
         
     | 
| 
      
 34 
     | 
    
         
            +
              end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
              context 'when setting the url on setup with a URI' do
         
     | 
| 
      
 37 
     | 
    
         
            +
                let(:block) { proc { |req| req.url URI.parse('foo.json?a=1') } }
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                it { expect(subject.path).to eq(URI.parse('foo.json')) }
         
     | 
| 
      
 40 
     | 
    
         
            +
                it { expect(subject.params).to eq('a' => '1') }
         
     | 
| 
      
 41 
     | 
    
         
            +
                it { expect(subject.to_env(conn).url.to_s).to eq('http://sushi.com/api/foo.json?a=1') }
         
     | 
| 
      
 42 
     | 
    
         
            +
              end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
              context 'when setting the url on setup with a string path and params' do
         
     | 
| 
      
 45 
     | 
    
         
            +
                let(:block) { proc { |req| req.url 'foo.json', 'a' => 1 } }
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                it { expect(subject.path).to eq('foo.json') }
         
     | 
| 
      
 48 
     | 
    
         
            +
                it { expect(subject.params).to eq('a' => 1) }
         
     | 
| 
      
 49 
     | 
    
         
            +
                it { expect(subject.to_env(conn).url.to_s).to eq('http://sushi.com/api/foo.json?a=1') }
         
     | 
| 
      
 50 
     | 
    
         
            +
              end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
              context 'when setting the url on setup with a path including params' do
         
     | 
| 
      
 53 
     | 
    
         
            +
                let(:block) { proc { |req| req.url 'foo.json?b=2&a=1#qqq' } }
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                it { expect(subject.path).to eq('foo.json') }
         
     | 
| 
      
 56 
     | 
    
         
            +
                it { expect(subject.params).to eq('a' => '1', 'b' => '2') }
         
     | 
| 
      
 57 
     | 
    
         
            +
                it { expect(subject.to_env(conn).url.to_s).to eq('http://sushi.com/api/foo.json?a=1&b=2') }
         
     | 
| 
      
 58 
     | 
    
         
            +
              end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
              context 'when setting a header on setup with []= syntax' do
         
     | 
| 
      
 61 
     | 
    
         
            +
                let(:block) { proc { |req| req['Server'] = 'Faraday' } }
         
     | 
| 
      
 62 
     | 
    
         
            +
                let(:headers) { subject.to_env(conn).request_headers }
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                it { expect(subject.headers['Server']).to eq('Faraday') }
         
     | 
| 
      
 65 
     | 
    
         
            +
                it { expect(headers['mime-version']).to eq('1.0') }
         
     | 
| 
      
 66 
     | 
    
         
            +
                it { expect(headers['server']).to eq('Faraday') }
         
     | 
| 
      
 67 
     | 
    
         
            +
              end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
              context 'when setting the body on setup' do
         
     | 
| 
      
 70 
     | 
    
         
            +
                let(:block) { proc { |req| req.body = 'hi' } }
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                it { expect(subject.body).to eq('hi') }
         
     | 
| 
      
 73 
     | 
    
         
            +
                it { expect(subject.to_env(conn).body).to eq('hi') }
         
     | 
| 
      
 74 
     | 
    
         
            +
              end
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
              context 'with global request options set' do
         
     | 
| 
      
 77 
     | 
    
         
            +
                let(:env_request) { subject.to_env(conn).request }
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                before do
         
     | 
| 
      
 80 
     | 
    
         
            +
                  conn.options.timeout = 3
         
     | 
| 
      
 81 
     | 
    
         
            +
                  conn.options.open_timeout = 5
         
     | 
| 
      
 82 
     | 
    
         
            +
                  conn.ssl.verify = false
         
     | 
| 
      
 83 
     | 
    
         
            +
                  conn.proxy = 'http://proxy.com'
         
     | 
| 
      
 84 
     | 
    
         
            +
                end
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                it { expect(subject.options.timeout).to eq(3) }
         
     | 
| 
      
 87 
     | 
    
         
            +
                it { expect(subject.options.open_timeout).to eq(5) }
         
     | 
| 
      
 88 
     | 
    
         
            +
                it { expect(env_request.timeout).to eq(3) }
         
     | 
| 
      
 89 
     | 
    
         
            +
                it { expect(env_request.open_timeout).to eq(5) }
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
                context 'and per-request options set' do
         
     | 
| 
      
 92 
     | 
    
         
            +
                  let(:block) do
         
     | 
| 
      
 93 
     | 
    
         
            +
                    proc do |req|
         
     | 
| 
      
 94 
     | 
    
         
            +
                      req.options.timeout = 10
         
     | 
| 
      
 95 
     | 
    
         
            +
                      req.options.boundary = 'boo'
         
     | 
| 
      
 96 
     | 
    
         
            +
                      req.options.oauth[:consumer_secret] = 'xyz'
         
     | 
| 
      
 97 
     | 
    
         
            +
                      req.options.context = {
         
     | 
| 
      
 98 
     | 
    
         
            +
                        foo: 'foo',
         
     | 
| 
      
 99 
     | 
    
         
            +
                        bar: 'bar'
         
     | 
| 
      
 100 
     | 
    
         
            +
                      }
         
     | 
| 
      
 101 
     | 
    
         
            +
                    end
         
     | 
| 
      
 102 
     | 
    
         
            +
                  end
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
                  it { expect(subject.options.timeout).to eq(10) }
         
     | 
| 
      
 105 
     | 
    
         
            +
                  it { expect(subject.options.open_timeout).to eq(5) }
         
     | 
| 
      
 106 
     | 
    
         
            +
                  it { expect(env_request.timeout).to eq(10) }
         
     | 
| 
      
 107 
     | 
    
         
            +
                  it { expect(env_request.open_timeout).to eq(5) }
         
     | 
| 
      
 108 
     | 
    
         
            +
                  it { expect(env_request.boundary).to eq('boo') }
         
     | 
| 
      
 109 
     | 
    
         
            +
                  it { expect(env_request.context).to eq(foo: 'foo', bar: 'bar') }
         
     | 
| 
      
 110 
     | 
    
         
            +
                  it do
         
     | 
| 
      
 111 
     | 
    
         
            +
                    oauth_expected = { consumer_secret: 'xyz', consumer_key: 'anonymous' }
         
     | 
| 
      
 112 
     | 
    
         
            +
                    expect(env_request.oauth).to eq(oauth_expected)
         
     | 
| 
      
 113 
     | 
    
         
            +
                  end
         
     | 
| 
      
 114 
     | 
    
         
            +
                end
         
     | 
| 
      
 115 
     | 
    
         
            +
              end
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
              it 'supports marshal serialization' do
         
     | 
| 
      
 118 
     | 
    
         
            +
                expect(Marshal.load(Marshal.dump(subject))).to eq(subject)
         
     | 
| 
      
 119 
     | 
    
         
            +
              end
         
     | 
| 
      
 120 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,220 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'stringio'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'logger'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            RSpec.describe Faraday::Response::Logger do
         
     | 
| 
      
 7 
     | 
    
         
            +
              let(:string_io) { StringIO.new }
         
     | 
| 
      
 8 
     | 
    
         
            +
              let(:logger) { Logger.new(string_io) }
         
     | 
| 
      
 9 
     | 
    
         
            +
              let(:logger_options) { {} }
         
     | 
| 
      
 10 
     | 
    
         
            +
              let(:conn) do
         
     | 
| 
      
 11 
     | 
    
         
            +
                rubbles = ['Barney', 'Betty', 'Bam Bam']
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                Faraday.new do |b|
         
     | 
| 
      
 14 
     | 
    
         
            +
                  b.response :logger, logger, logger_options do |logger|
         
     | 
| 
      
 15 
     | 
    
         
            +
                    logger.filter(/(soylent green is) (.+)/, '\1 tasty')
         
     | 
| 
      
 16 
     | 
    
         
            +
                    logger.filter(/(api_key:).*"(.+)."/, '\1[API_KEY]')
         
     | 
| 
      
 17 
     | 
    
         
            +
                    logger.filter(/(password)=(.+)/, '\1=[HIDDEN]')
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
                  b.adapter :test do |stubs|
         
     | 
| 
      
 20 
     | 
    
         
            +
                    stubs.get('/hello') { [200, { 'Content-Type' => 'text/html' }, 'hello'] }
         
     | 
| 
      
 21 
     | 
    
         
            +
                    stubs.post('/ohai') { [200, { 'Content-Type' => 'text/html' }, 'fred'] }
         
     | 
| 
      
 22 
     | 
    
         
            +
                    stubs.post('/ohyes') { [200, { 'Content-Type' => 'text/html' }, 'pebbles'] }
         
     | 
| 
      
 23 
     | 
    
         
            +
                    stubs.get('/rubbles') { [200, { 'Content-Type' => 'application/json' }, rubbles] }
         
     | 
| 
      
 24 
     | 
    
         
            +
                    stubs.get('/filtered_body') { [200, { 'Content-Type' => 'text/html' }, 'soylent green is people'] }
         
     | 
| 
      
 25 
     | 
    
         
            +
                    stubs.get('/filtered_headers') { [200, { 'Content-Type' => 'text/html' }, 'headers response'] }
         
     | 
| 
      
 26 
     | 
    
         
            +
                    stubs.get('/filtered_params') { [200, { 'Content-Type' => 'text/html' }, 'params response'] }
         
     | 
| 
      
 27 
     | 
    
         
            +
                    stubs.get('/filtered_url') { [200, { 'Content-Type' => 'text/html' }, 'url response'] }
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
                end
         
     | 
| 
      
 30 
     | 
    
         
            +
              end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
              before do
         
     | 
| 
      
 33 
     | 
    
         
            +
                logger.level = Logger::DEBUG
         
     | 
| 
      
 34 
     | 
    
         
            +
              end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
              it 'still returns output' do
         
     | 
| 
      
 37 
     | 
    
         
            +
                resp = conn.get '/hello', nil, accept: 'text/html'
         
     | 
| 
      
 38 
     | 
    
         
            +
                expect(resp.body).to eq('hello')
         
     | 
| 
      
 39 
     | 
    
         
            +
              end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
              context 'without configuration' do
         
     | 
| 
      
 42 
     | 
    
         
            +
                let(:conn) do
         
     | 
| 
      
 43 
     | 
    
         
            +
                  Faraday.new do |b|
         
     | 
| 
      
 44 
     | 
    
         
            +
                    b.response :logger
         
     | 
| 
      
 45 
     | 
    
         
            +
                    b.adapter :test do |stubs|
         
     | 
| 
      
 46 
     | 
    
         
            +
                      stubs.get('/hello') { [200, { 'Content-Type' => 'text/html' }, 'hello'] }
         
     | 
| 
      
 47 
     | 
    
         
            +
                    end
         
     | 
| 
      
 48 
     | 
    
         
            +
                  end
         
     | 
| 
      
 49 
     | 
    
         
            +
                end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                it 'defaults to stdout' do
         
     | 
| 
      
 52 
     | 
    
         
            +
                  expect(Logger).to receive(:new).with($stdout).and_return(Logger.new(nil))
         
     | 
| 
      
 53 
     | 
    
         
            +
                  conn.get('/hello')
         
     | 
| 
      
 54 
     | 
    
         
            +
                end
         
     | 
| 
      
 55 
     | 
    
         
            +
              end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
              context 'with default formatter' do
         
     | 
| 
      
 58 
     | 
    
         
            +
                let(:formatter) { instance_double(Faraday::Logging::Formatter, request: true, response: true, filter: []) }
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                before { allow(Faraday::Logging::Formatter).to receive(:new).and_return(formatter) }
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                it 'delegates logging to the formatter' do
         
     | 
| 
      
 63 
     | 
    
         
            +
                  expect(formatter).to receive(:request).with(an_instance_of(Faraday::Env))
         
     | 
| 
      
 64 
     | 
    
         
            +
                  expect(formatter).to receive(:response).with(an_instance_of(Faraday::Env))
         
     | 
| 
      
 65 
     | 
    
         
            +
                  conn.get '/hello'
         
     | 
| 
      
 66 
     | 
    
         
            +
                end
         
     | 
| 
      
 67 
     | 
    
         
            +
              end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
              context 'with custom formatter' do
         
     | 
| 
      
 70 
     | 
    
         
            +
                let(:formatter_class) do
         
     | 
| 
      
 71 
     | 
    
         
            +
                  Class.new(Faraday::Logging::Formatter) do
         
     | 
| 
      
 72 
     | 
    
         
            +
                    def request(_env)
         
     | 
| 
      
 73 
     | 
    
         
            +
                      info 'Custom log formatter request'
         
     | 
| 
      
 74 
     | 
    
         
            +
                    end
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                    def response(_env)
         
     | 
| 
      
 77 
     | 
    
         
            +
                      info 'Custom log formatter response'
         
     | 
| 
      
 78 
     | 
    
         
            +
                    end
         
     | 
| 
      
 79 
     | 
    
         
            +
                  end
         
     | 
| 
      
 80 
     | 
    
         
            +
                end
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                let(:logger_options) { { formatter: formatter_class } }
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                it 'logs with custom formatter' do
         
     | 
| 
      
 85 
     | 
    
         
            +
                  conn.get '/hello'
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
                  expect(string_io.string).to match('Custom log formatter request')
         
     | 
| 
      
 88 
     | 
    
         
            +
                  expect(string_io.string).to match('Custom log formatter response')
         
     | 
| 
      
 89 
     | 
    
         
            +
                end
         
     | 
| 
      
 90 
     | 
    
         
            +
              end
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
              it 'logs method and url' do
         
     | 
| 
      
 93 
     | 
    
         
            +
                conn.get '/hello', nil, accept: 'text/html'
         
     | 
| 
      
 94 
     | 
    
         
            +
                expect(string_io.string).to match('GET http:/hello')
         
     | 
| 
      
 95 
     | 
    
         
            +
              end
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
              it 'logs request headers by default' do
         
     | 
| 
      
 98 
     | 
    
         
            +
                conn.get '/hello', nil, accept: 'text/html'
         
     | 
| 
      
 99 
     | 
    
         
            +
                expect(string_io.string).to match(%(Accept: "text/html))
         
     | 
| 
      
 100 
     | 
    
         
            +
              end
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
              it 'logs response headers by default' do
         
     | 
| 
      
 103 
     | 
    
         
            +
                conn.get '/hello', nil, accept: 'text/html'
         
     | 
| 
      
 104 
     | 
    
         
            +
                expect(string_io.string).to match(%(Content-Type: "text/html))
         
     | 
| 
      
 105 
     | 
    
         
            +
              end
         
     | 
| 
      
 106 
     | 
    
         
            +
             
     | 
| 
      
 107 
     | 
    
         
            +
              it 'does not log request body by default' do
         
     | 
| 
      
 108 
     | 
    
         
            +
                conn.post '/ohai', 'name=Unagi', accept: 'text/html'
         
     | 
| 
      
 109 
     | 
    
         
            +
                expect(string_io.string).not_to match(%(name=Unagi))
         
     | 
| 
      
 110 
     | 
    
         
            +
              end
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
              it 'does not log response body by default' do
         
     | 
| 
      
 113 
     | 
    
         
            +
                conn.post '/ohai', 'name=Toro', accept: 'text/html'
         
     | 
| 
      
 114 
     | 
    
         
            +
                expect(string_io.string).not_to match(%(fred))
         
     | 
| 
      
 115 
     | 
    
         
            +
              end
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
              it 'logs filter headers' do
         
     | 
| 
      
 118 
     | 
    
         
            +
                conn.headers = { 'api_key' => 'ABC123' }
         
     | 
| 
      
 119 
     | 
    
         
            +
                conn.get '/filtered_headers', nil, accept: 'text/html'
         
     | 
| 
      
 120 
     | 
    
         
            +
                expect(string_io.string).to match(%(api_key:))
         
     | 
| 
      
 121 
     | 
    
         
            +
                expect(string_io.string).to match(%([API_KEY]))
         
     | 
| 
      
 122 
     | 
    
         
            +
                expect(string_io.string).not_to match(%(ABC123))
         
     | 
| 
      
 123 
     | 
    
         
            +
              end
         
     | 
| 
      
 124 
     | 
    
         
            +
             
     | 
| 
      
 125 
     | 
    
         
            +
              it 'logs filter url' do
         
     | 
| 
      
 126 
     | 
    
         
            +
                conn.get '/filtered_url?password=hunter2', nil, accept: 'text/html'
         
     | 
| 
      
 127 
     | 
    
         
            +
                expect(string_io.string).to match(%([HIDDEN]))
         
     | 
| 
      
 128 
     | 
    
         
            +
                expect(string_io.string).not_to match(%(hunter2))
         
     | 
| 
      
 129 
     | 
    
         
            +
              end
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
              context 'when not logging request headers' do
         
     | 
| 
      
 132 
     | 
    
         
            +
                let(:logger_options) { { headers: { request: false } } }
         
     | 
| 
      
 133 
     | 
    
         
            +
             
     | 
| 
      
 134 
     | 
    
         
            +
                it 'does not log request headers if option is false' do
         
     | 
| 
      
 135 
     | 
    
         
            +
                  conn.get '/hello', nil, accept: 'text/html'
         
     | 
| 
      
 136 
     | 
    
         
            +
                  expect(string_io.string).not_to match(%(Accept: "text/html))
         
     | 
| 
      
 137 
     | 
    
         
            +
                end
         
     | 
| 
      
 138 
     | 
    
         
            +
              end
         
     | 
| 
      
 139 
     | 
    
         
            +
             
     | 
| 
      
 140 
     | 
    
         
            +
              context 'when not logging response headers' do
         
     | 
| 
      
 141 
     | 
    
         
            +
                let(:logger_options) { { headers: { response: false } } }
         
     | 
| 
      
 142 
     | 
    
         
            +
             
     | 
| 
      
 143 
     | 
    
         
            +
                it 'does not log response headers if option is false' do
         
     | 
| 
      
 144 
     | 
    
         
            +
                  conn.get '/hello', nil, accept: 'text/html'
         
     | 
| 
      
 145 
     | 
    
         
            +
                  expect(string_io.string).not_to match(%(Content-Type: "text/html))
         
     | 
| 
      
 146 
     | 
    
         
            +
                end
         
     | 
| 
      
 147 
     | 
    
         
            +
              end
         
     | 
| 
      
 148 
     | 
    
         
            +
             
     | 
| 
      
 149 
     | 
    
         
            +
              context 'when logging request body' do
         
     | 
| 
      
 150 
     | 
    
         
            +
                let(:logger_options) { { bodies: { request: true } } }
         
     | 
| 
      
 151 
     | 
    
         
            +
             
     | 
| 
      
 152 
     | 
    
         
            +
                it 'log only request body' do
         
     | 
| 
      
 153 
     | 
    
         
            +
                  conn.post '/ohyes', 'name=Tamago', accept: 'text/html'
         
     | 
| 
      
 154 
     | 
    
         
            +
                  expect(string_io.string).to match(%(name=Tamago))
         
     | 
| 
      
 155 
     | 
    
         
            +
                  expect(string_io.string).not_to match(%(pebbles))
         
     | 
| 
      
 156 
     | 
    
         
            +
                end
         
     | 
| 
      
 157 
     | 
    
         
            +
              end
         
     | 
| 
      
 158 
     | 
    
         
            +
             
     | 
| 
      
 159 
     | 
    
         
            +
              context 'when logging response body' do
         
     | 
| 
      
 160 
     | 
    
         
            +
                let(:logger_options) { { bodies: { response: true } } }
         
     | 
| 
      
 161 
     | 
    
         
            +
             
     | 
| 
      
 162 
     | 
    
         
            +
                it 'log only response body' do
         
     | 
| 
      
 163 
     | 
    
         
            +
                  conn.post '/ohyes', 'name=Hamachi', accept: 'text/html'
         
     | 
| 
      
 164 
     | 
    
         
            +
                  expect(string_io.string).to match(%(pebbles))
         
     | 
| 
      
 165 
     | 
    
         
            +
                  expect(string_io.string).not_to match(%(name=Hamachi))
         
     | 
| 
      
 166 
     | 
    
         
            +
                end
         
     | 
| 
      
 167 
     | 
    
         
            +
              end
         
     | 
| 
      
 168 
     | 
    
         
            +
             
     | 
| 
      
 169 
     | 
    
         
            +
              context 'when logging request and response bodies' do
         
     | 
| 
      
 170 
     | 
    
         
            +
                let(:logger_options) { { bodies: true } }
         
     | 
| 
      
 171 
     | 
    
         
            +
             
     | 
| 
      
 172 
     | 
    
         
            +
                it 'log request and response body' do
         
     | 
| 
      
 173 
     | 
    
         
            +
                  conn.post '/ohyes', 'name=Ebi', accept: 'text/html'
         
     | 
| 
      
 174 
     | 
    
         
            +
                  expect(string_io.string).to match(%(name=Ebi))
         
     | 
| 
      
 175 
     | 
    
         
            +
                  expect(string_io.string).to match(%(pebbles))
         
     | 
| 
      
 176 
     | 
    
         
            +
                end
         
     | 
| 
      
 177 
     | 
    
         
            +
             
     | 
| 
      
 178 
     | 
    
         
            +
                it 'log response body object' do
         
     | 
| 
      
 179 
     | 
    
         
            +
                  conn.get '/rubbles', nil, accept: 'text/html'
         
     | 
| 
      
 180 
     | 
    
         
            +
                  expect(string_io.string).to match(%([\"Barney\", \"Betty\", \"Bam Bam\"]\n))
         
     | 
| 
      
 181 
     | 
    
         
            +
                end
         
     | 
| 
      
 182 
     | 
    
         
            +
             
     | 
| 
      
 183 
     | 
    
         
            +
                it 'logs filter body' do
         
     | 
| 
      
 184 
     | 
    
         
            +
                  conn.get '/filtered_body', nil, accept: 'text/html'
         
     | 
| 
      
 185 
     | 
    
         
            +
                  expect(string_io.string).to match(%(soylent green is))
         
     | 
| 
      
 186 
     | 
    
         
            +
                  expect(string_io.string).to match(%(tasty))
         
     | 
| 
      
 187 
     | 
    
         
            +
                  expect(string_io.string).not_to match(%(people))
         
     | 
| 
      
 188 
     | 
    
         
            +
                end
         
     | 
| 
      
 189 
     | 
    
         
            +
              end
         
     | 
| 
      
 190 
     | 
    
         
            +
             
     | 
| 
      
 191 
     | 
    
         
            +
              context 'when using log_level' do
         
     | 
| 
      
 192 
     | 
    
         
            +
                let(:logger_options) { { bodies: true, log_level: :debug } }
         
     | 
| 
      
 193 
     | 
    
         
            +
             
     | 
| 
      
 194 
     | 
    
         
            +
                it 'logs request/request body on the specified level (debug)' do
         
     | 
| 
      
 195 
     | 
    
         
            +
                  logger.level = Logger::DEBUG
         
     | 
| 
      
 196 
     | 
    
         
            +
                  conn.post '/ohyes', 'name=Ebi', accept: 'text/html'
         
     | 
| 
      
 197 
     | 
    
         
            +
                  expect(string_io.string).to match(%(name=Ebi))
         
     | 
| 
      
 198 
     | 
    
         
            +
                  expect(string_io.string).to match(%(pebbles))
         
     | 
| 
      
 199 
     | 
    
         
            +
                end
         
     | 
| 
      
 200 
     | 
    
         
            +
             
     | 
| 
      
 201 
     | 
    
         
            +
                it 'logs headers on the debug level' do
         
     | 
| 
      
 202 
     | 
    
         
            +
                  logger.level = Logger::DEBUG
         
     | 
| 
      
 203 
     | 
    
         
            +
                  conn.get '/hello', nil, accept: 'text/html'
         
     | 
| 
      
 204 
     | 
    
         
            +
                  expect(string_io.string).to match(%(Content-Type: "text/html))
         
     | 
| 
      
 205 
     | 
    
         
            +
                end
         
     | 
| 
      
 206 
     | 
    
         
            +
             
     | 
| 
      
 207 
     | 
    
         
            +
                it 'does not log request/response body on the info level' do
         
     | 
| 
      
 208 
     | 
    
         
            +
                  logger.level = Logger::INFO
         
     | 
| 
      
 209 
     | 
    
         
            +
                  conn.post '/ohyes', 'name=Ebi', accept: 'text/html'
         
     | 
| 
      
 210 
     | 
    
         
            +
                  expect(string_io.string).not_to match(%(name=Ebi))
         
     | 
| 
      
 211 
     | 
    
         
            +
                  expect(string_io.string).not_to match(%(pebbles))
         
     | 
| 
      
 212 
     | 
    
         
            +
                end
         
     | 
| 
      
 213 
     | 
    
         
            +
             
     | 
| 
      
 214 
     | 
    
         
            +
                it 'does not log headers on the info level' do
         
     | 
| 
      
 215 
     | 
    
         
            +
                  logger.level = Logger::INFO
         
     | 
| 
      
 216 
     | 
    
         
            +
                  conn.get '/hello', nil, accept: 'text/html'
         
     | 
| 
      
 217 
     | 
    
         
            +
                  expect(string_io.string).not_to match(%(Content-Type: "text/html))
         
     | 
| 
      
 218 
     | 
    
         
            +
                end
         
     | 
| 
      
 219 
     | 
    
         
            +
              end
         
     | 
| 
      
 220 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,68 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            RSpec.describe Faraday::Response::Middleware do
         
     | 
| 
      
 4 
     | 
    
         
            +
              let(:conn) do
         
     | 
| 
      
 5 
     | 
    
         
            +
                Faraday.new do |b|
         
     | 
| 
      
 6 
     | 
    
         
            +
                  b.use custom_middleware
         
     | 
| 
      
 7 
     | 
    
         
            +
                  b.adapter :test do |stub|
         
     | 
| 
      
 8 
     | 
    
         
            +
                    stub.get('ok') { [200, { 'Content-Type' => 'text/html' }, '<body></body>'] }
         
     | 
| 
      
 9 
     | 
    
         
            +
                    stub.get('not_modified') { [304, nil, nil] }
         
     | 
| 
      
 10 
     | 
    
         
            +
                    stub.get('no_content') { [204, nil, nil] }
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              context 'with a custom ResponseMiddleware' do
         
     | 
| 
      
 16 
     | 
    
         
            +
                let(:custom_middleware) do
         
     | 
| 
      
 17 
     | 
    
         
            +
                  Class.new(Faraday::Response::Middleware) do
         
     | 
| 
      
 18 
     | 
    
         
            +
                    def parse(body)
         
     | 
| 
      
 19 
     | 
    
         
            +
                      body.upcase
         
     | 
| 
      
 20 
     | 
    
         
            +
                    end
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                it 'parses the response' do
         
     | 
| 
      
 25 
     | 
    
         
            +
                  expect(conn.get('ok').body).to eq('<BODY></BODY>')
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
              end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
              context 'with a custom ResponseMiddleware and private parse' do
         
     | 
| 
      
 30 
     | 
    
         
            +
                let(:custom_middleware) do
         
     | 
| 
      
 31 
     | 
    
         
            +
                  Class.new(Faraday::Response::Middleware) do
         
     | 
| 
      
 32 
     | 
    
         
            +
                    private
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                    def parse(body)
         
     | 
| 
      
 35 
     | 
    
         
            +
                      body.upcase
         
     | 
| 
      
 36 
     | 
    
         
            +
                    end
         
     | 
| 
      
 37 
     | 
    
         
            +
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                it 'parses the response' do
         
     | 
| 
      
 41 
     | 
    
         
            +
                  expect(conn.get('ok').body).to eq('<BODY></BODY>')
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
              end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
              context 'with a custom ResponseMiddleware but empty response' do
         
     | 
| 
      
 46 
     | 
    
         
            +
                let(:custom_middleware) do
         
     | 
| 
      
 47 
     | 
    
         
            +
                  Class.new(Faraday::Response::Middleware) do
         
     | 
| 
      
 48 
     | 
    
         
            +
                    def parse(_body)
         
     | 
| 
      
 49 
     | 
    
         
            +
                      raise 'this should not be called'
         
     | 
| 
      
 50 
     | 
    
         
            +
                    end
         
     | 
| 
      
 51 
     | 
    
         
            +
                  end
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                it 'raises exception for 200 responses' do
         
     | 
| 
      
 55 
     | 
    
         
            +
                  expect { conn.get('ok') }.to raise_error(StandardError)
         
     | 
| 
      
 56 
     | 
    
         
            +
                end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                it 'doesn\'t call the middleware for 204 responses' do
         
     | 
| 
      
 59 
     | 
    
         
            +
                  expect_any_instance_of(custom_middleware).not_to receive(:parse)
         
     | 
| 
      
 60 
     | 
    
         
            +
                  expect(conn.get('no_content').body).to be_nil
         
     | 
| 
      
 61 
     | 
    
         
            +
                end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                it 'doesn\'t call the middleware for 304 responses' do
         
     | 
| 
      
 64 
     | 
    
         
            +
                  expect_any_instance_of(custom_middleware).not_to receive(:parse)
         
     | 
| 
      
 65 
     | 
    
         
            +
                  expect(conn.get('not_modified').body).to be_nil
         
     | 
| 
      
 66 
     | 
    
         
            +
                end
         
     | 
| 
      
 67 
     | 
    
         
            +
              end
         
     | 
| 
      
 68 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,169 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            RSpec.describe Faraday::Response::RaiseError do
         
     | 
| 
      
 4 
     | 
    
         
            +
              let(:conn) do
         
     | 
| 
      
 5 
     | 
    
         
            +
                Faraday.new do |b|
         
     | 
| 
      
 6 
     | 
    
         
            +
                  b.response :raise_error
         
     | 
| 
      
 7 
     | 
    
         
            +
                  b.adapter :test do |stub|
         
     | 
| 
      
 8 
     | 
    
         
            +
                    stub.get('ok') { [200, { 'Content-Type' => 'text/html' }, '<body></body>'] }
         
     | 
| 
      
 9 
     | 
    
         
            +
                    stub.get('bad-request') { [400, { 'X-Reason' => 'because' }, 'keep looking'] }
         
     | 
| 
      
 10 
     | 
    
         
            +
                    stub.get('unauthorized') { [401, { 'X-Reason' => 'because' }, 'keep looking'] }
         
     | 
| 
      
 11 
     | 
    
         
            +
                    stub.get('forbidden') { [403, { 'X-Reason' => 'because' }, 'keep looking'] }
         
     | 
| 
      
 12 
     | 
    
         
            +
                    stub.get('not-found') { [404, { 'X-Reason' => 'because' }, 'keep looking'] }
         
     | 
| 
      
 13 
     | 
    
         
            +
                    stub.get('proxy-error') { [407, { 'X-Reason' => 'because' }, 'keep looking'] }
         
     | 
| 
      
 14 
     | 
    
         
            +
                    stub.get('conflict') { [409, { 'X-Reason' => 'because' }, 'keep looking'] }
         
     | 
| 
      
 15 
     | 
    
         
            +
                    stub.get('unprocessable-entity') { [422, { 'X-Reason' => 'because' }, 'keep looking'] }
         
     | 
| 
      
 16 
     | 
    
         
            +
                    stub.get('4xx') { [499, { 'X-Reason' => 'because' }, 'keep looking'] }
         
     | 
| 
      
 17 
     | 
    
         
            +
                    stub.get('nil-status') { [nil, { 'X-Reason' => 'nil' }, 'fail'] }
         
     | 
| 
      
 18 
     | 
    
         
            +
                    stub.get('server-error') { [500, { 'X-Error' => 'bailout' }, 'fail'] }
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
              it 'raises no exception for 200 responses' do
         
     | 
| 
      
 24 
     | 
    
         
            +
                expect { conn.get('ok') }.not_to raise_error
         
     | 
| 
      
 25 
     | 
    
         
            +
              end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
              it 'raises Faraday::BadRequestError for 400 responses' do
         
     | 
| 
      
 28 
     | 
    
         
            +
                expect { conn.get('bad-request') }.to raise_error(Faraday::BadRequestError) do |ex|
         
     | 
| 
      
 29 
     | 
    
         
            +
                  expect(ex.message).to eq('the server responded with status 400')
         
     | 
| 
      
 30 
     | 
    
         
            +
                  expect(ex.response[:headers]['X-Reason']).to eq('because')
         
     | 
| 
      
 31 
     | 
    
         
            +
                  expect(ex.response[:status]).to eq(400)
         
     | 
| 
      
 32 
     | 
    
         
            +
                  expect(ex.response_status).to eq(400)
         
     | 
| 
      
 33 
     | 
    
         
            +
                  expect(ex.response_body).to eq('keep looking')
         
     | 
| 
      
 34 
     | 
    
         
            +
                  expect(ex.response_headers['X-Reason']).to eq('because')
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
              end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
              it 'raises Faraday::UnauthorizedError for 401 responses' do
         
     | 
| 
      
 39 
     | 
    
         
            +
                expect { conn.get('unauthorized') }.to raise_error(Faraday::UnauthorizedError) do |ex|
         
     | 
| 
      
 40 
     | 
    
         
            +
                  expect(ex.message).to eq('the server responded with status 401')
         
     | 
| 
      
 41 
     | 
    
         
            +
                  expect(ex.response[:headers]['X-Reason']).to eq('because')
         
     | 
| 
      
 42 
     | 
    
         
            +
                  expect(ex.response[:status]).to eq(401)
         
     | 
| 
      
 43 
     | 
    
         
            +
                  expect(ex.response_status).to eq(401)
         
     | 
| 
      
 44 
     | 
    
         
            +
                  expect(ex.response_body).to eq('keep looking')
         
     | 
| 
      
 45 
     | 
    
         
            +
                  expect(ex.response_headers['X-Reason']).to eq('because')
         
     | 
| 
      
 46 
     | 
    
         
            +
                end
         
     | 
| 
      
 47 
     | 
    
         
            +
              end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
              it 'raises Faraday::ForbiddenError for 403 responses' do
         
     | 
| 
      
 50 
     | 
    
         
            +
                expect { conn.get('forbidden') }.to raise_error(Faraday::ForbiddenError) do |ex|
         
     | 
| 
      
 51 
     | 
    
         
            +
                  expect(ex.message).to eq('the server responded with status 403')
         
     | 
| 
      
 52 
     | 
    
         
            +
                  expect(ex.response[:headers]['X-Reason']).to eq('because')
         
     | 
| 
      
 53 
     | 
    
         
            +
                  expect(ex.response[:status]).to eq(403)
         
     | 
| 
      
 54 
     | 
    
         
            +
                  expect(ex.response_status).to eq(403)
         
     | 
| 
      
 55 
     | 
    
         
            +
                  expect(ex.response_body).to eq('keep looking')
         
     | 
| 
      
 56 
     | 
    
         
            +
                  expect(ex.response_headers['X-Reason']).to eq('because')
         
     | 
| 
      
 57 
     | 
    
         
            +
                end
         
     | 
| 
      
 58 
     | 
    
         
            +
              end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
              it 'raises Faraday::ResourceNotFound for 404 responses' do
         
     | 
| 
      
 61 
     | 
    
         
            +
                expect { conn.get('not-found') }.to raise_error(Faraday::ResourceNotFound) do |ex|
         
     | 
| 
      
 62 
     | 
    
         
            +
                  expect(ex.message).to eq('the server responded with status 404')
         
     | 
| 
      
 63 
     | 
    
         
            +
                  expect(ex.response[:headers]['X-Reason']).to eq('because')
         
     | 
| 
      
 64 
     | 
    
         
            +
                  expect(ex.response[:status]).to eq(404)
         
     | 
| 
      
 65 
     | 
    
         
            +
                  expect(ex.response_status).to eq(404)
         
     | 
| 
      
 66 
     | 
    
         
            +
                  expect(ex.response_body).to eq('keep looking')
         
     | 
| 
      
 67 
     | 
    
         
            +
                  expect(ex.response_headers['X-Reason']).to eq('because')
         
     | 
| 
      
 68 
     | 
    
         
            +
                end
         
     | 
| 
      
 69 
     | 
    
         
            +
              end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
              it 'raises Faraday::ProxyAuthError for 407 responses' do
         
     | 
| 
      
 72 
     | 
    
         
            +
                expect { conn.get('proxy-error') }.to raise_error(Faraday::ProxyAuthError) do |ex|
         
     | 
| 
      
 73 
     | 
    
         
            +
                  expect(ex.message).to eq('407 "Proxy Authentication Required"')
         
     | 
| 
      
 74 
     | 
    
         
            +
                  expect(ex.response[:headers]['X-Reason']).to eq('because')
         
     | 
| 
      
 75 
     | 
    
         
            +
                  expect(ex.response[:status]).to eq(407)
         
     | 
| 
      
 76 
     | 
    
         
            +
                  expect(ex.response_status).to eq(407)
         
     | 
| 
      
 77 
     | 
    
         
            +
                  expect(ex.response_body).to eq('keep looking')
         
     | 
| 
      
 78 
     | 
    
         
            +
                  expect(ex.response_headers['X-Reason']).to eq('because')
         
     | 
| 
      
 79 
     | 
    
         
            +
                end
         
     | 
| 
      
 80 
     | 
    
         
            +
              end
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
              it 'raises Faraday::ConflictError for 409 responses' do
         
     | 
| 
      
 83 
     | 
    
         
            +
                expect { conn.get('conflict') }.to raise_error(Faraday::ConflictError) do |ex|
         
     | 
| 
      
 84 
     | 
    
         
            +
                  expect(ex.message).to eq('the server responded with status 409')
         
     | 
| 
      
 85 
     | 
    
         
            +
                  expect(ex.response[:headers]['X-Reason']).to eq('because')
         
     | 
| 
      
 86 
     | 
    
         
            +
                  expect(ex.response[:status]).to eq(409)
         
     | 
| 
      
 87 
     | 
    
         
            +
                  expect(ex.response_status).to eq(409)
         
     | 
| 
      
 88 
     | 
    
         
            +
                  expect(ex.response_body).to eq('keep looking')
         
     | 
| 
      
 89 
     | 
    
         
            +
                  expect(ex.response_headers['X-Reason']).to eq('because')
         
     | 
| 
      
 90 
     | 
    
         
            +
                end
         
     | 
| 
      
 91 
     | 
    
         
            +
              end
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
              it 'raises Faraday::UnprocessableEntityError for 422 responses' do
         
     | 
| 
      
 94 
     | 
    
         
            +
                expect { conn.get('unprocessable-entity') }.to raise_error(Faraday::UnprocessableEntityError) do |ex|
         
     | 
| 
      
 95 
     | 
    
         
            +
                  expect(ex.message).to eq('the server responded with status 422')
         
     | 
| 
      
 96 
     | 
    
         
            +
                  expect(ex.response[:headers]['X-Reason']).to eq('because')
         
     | 
| 
      
 97 
     | 
    
         
            +
                  expect(ex.response[:status]).to eq(422)
         
     | 
| 
      
 98 
     | 
    
         
            +
                  expect(ex.response_status).to eq(422)
         
     | 
| 
      
 99 
     | 
    
         
            +
                  expect(ex.response_body).to eq('keep looking')
         
     | 
| 
      
 100 
     | 
    
         
            +
                  expect(ex.response_headers['X-Reason']).to eq('because')
         
     | 
| 
      
 101 
     | 
    
         
            +
                end
         
     | 
| 
      
 102 
     | 
    
         
            +
              end
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
              it 'raises Faraday::NilStatusError for nil status in response' do
         
     | 
| 
      
 105 
     | 
    
         
            +
                expect { conn.get('nil-status') }.to raise_error(Faraday::NilStatusError) do |ex|
         
     | 
| 
      
 106 
     | 
    
         
            +
                  expect(ex.message).to eq('http status could not be derived from the server response')
         
     | 
| 
      
 107 
     | 
    
         
            +
                  expect(ex.response[:headers]['X-Reason']).to eq('nil')
         
     | 
| 
      
 108 
     | 
    
         
            +
                  expect(ex.response[:status]).to be_nil
         
     | 
| 
      
 109 
     | 
    
         
            +
                  expect(ex.response_status).to be_nil
         
     | 
| 
      
 110 
     | 
    
         
            +
                  expect(ex.response_body).to eq('fail')
         
     | 
| 
      
 111 
     | 
    
         
            +
                  expect(ex.response_headers['X-Reason']).to eq('nil')
         
     | 
| 
      
 112 
     | 
    
         
            +
                end
         
     | 
| 
      
 113 
     | 
    
         
            +
              end
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
      
 115 
     | 
    
         
            +
              it 'raises Faraday::ClientError for other 4xx responses' do
         
     | 
| 
      
 116 
     | 
    
         
            +
                expect { conn.get('4xx') }.to raise_error(Faraday::ClientError) do |ex|
         
     | 
| 
      
 117 
     | 
    
         
            +
                  expect(ex.message).to eq('the server responded with status 499')
         
     | 
| 
      
 118 
     | 
    
         
            +
                  expect(ex.response[:headers]['X-Reason']).to eq('because')
         
     | 
| 
      
 119 
     | 
    
         
            +
                  expect(ex.response[:status]).to eq(499)
         
     | 
| 
      
 120 
     | 
    
         
            +
                  expect(ex.response_status).to eq(499)
         
     | 
| 
      
 121 
     | 
    
         
            +
                  expect(ex.response_body).to eq('keep looking')
         
     | 
| 
      
 122 
     | 
    
         
            +
                  expect(ex.response_headers['X-Reason']).to eq('because')
         
     | 
| 
      
 123 
     | 
    
         
            +
                end
         
     | 
| 
      
 124 
     | 
    
         
            +
              end
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
              it 'raises Faraday::ServerError for 500 responses' do
         
     | 
| 
      
 127 
     | 
    
         
            +
                expect { conn.get('server-error') }.to raise_error(Faraday::ServerError) do |ex|
         
     | 
| 
      
 128 
     | 
    
         
            +
                  expect(ex.message).to eq('the server responded with status 500')
         
     | 
| 
      
 129 
     | 
    
         
            +
                  expect(ex.response[:headers]['X-Error']).to eq('bailout')
         
     | 
| 
      
 130 
     | 
    
         
            +
                  expect(ex.response[:status]).to eq(500)
         
     | 
| 
      
 131 
     | 
    
         
            +
                  expect(ex.response_status).to eq(500)
         
     | 
| 
      
 132 
     | 
    
         
            +
                  expect(ex.response_body).to eq('fail')
         
     | 
| 
      
 133 
     | 
    
         
            +
                  expect(ex.response_headers['X-Error']).to eq('bailout')
         
     | 
| 
      
 134 
     | 
    
         
            +
                end
         
     | 
| 
      
 135 
     | 
    
         
            +
              end
         
     | 
| 
      
 136 
     | 
    
         
            +
             
     | 
| 
      
 137 
     | 
    
         
            +
              describe 'request info' do
         
     | 
| 
      
 138 
     | 
    
         
            +
                let(:conn) do
         
     | 
| 
      
 139 
     | 
    
         
            +
                  Faraday.new do |b|
         
     | 
| 
      
 140 
     | 
    
         
            +
                    b.response :raise_error
         
     | 
| 
      
 141 
     | 
    
         
            +
                    b.adapter :test do |stub|
         
     | 
| 
      
 142 
     | 
    
         
            +
                      stub.post('request?full=true', request_body, request_headers) do
         
     | 
| 
      
 143 
     | 
    
         
            +
                        [400, { 'X-Reason' => 'because' }, 'keep looking']
         
     | 
| 
      
 144 
     | 
    
         
            +
                      end
         
     | 
| 
      
 145 
     | 
    
         
            +
                    end
         
     | 
| 
      
 146 
     | 
    
         
            +
                  end
         
     | 
| 
      
 147 
     | 
    
         
            +
                end
         
     | 
| 
      
 148 
     | 
    
         
            +
                let(:request_body) { JSON.generate({ 'item' => 'sth' }) }
         
     | 
| 
      
 149 
     | 
    
         
            +
                let(:request_headers) { { 'Authorization' => 'Basic 123' } }
         
     | 
| 
      
 150 
     | 
    
         
            +
             
     | 
| 
      
 151 
     | 
    
         
            +
                subject(:perform_request) do
         
     | 
| 
      
 152 
     | 
    
         
            +
                  conn.post 'request' do |req|
         
     | 
| 
      
 153 
     | 
    
         
            +
                    req.headers['Authorization'] = 'Basic 123'
         
     | 
| 
      
 154 
     | 
    
         
            +
                    req.params[:full] = true
         
     | 
| 
      
 155 
     | 
    
         
            +
                    req.body = request_body
         
     | 
| 
      
 156 
     | 
    
         
            +
                  end
         
     | 
| 
      
 157 
     | 
    
         
            +
                end
         
     | 
| 
      
 158 
     | 
    
         
            +
             
     | 
| 
      
 159 
     | 
    
         
            +
                it 'returns the request info in the exception' do
         
     | 
| 
      
 160 
     | 
    
         
            +
                  expect { perform_request }.to raise_error(Faraday::BadRequestError) do |ex|
         
     | 
| 
      
 161 
     | 
    
         
            +
                    expect(ex.response[:request][:method]).to eq(:post)
         
     | 
| 
      
 162 
     | 
    
         
            +
                    expect(ex.response[:request][:url_path]).to eq('/request')
         
     | 
| 
      
 163 
     | 
    
         
            +
                    expect(ex.response[:request][:params]).to eq({ 'full' => 'true' })
         
     | 
| 
      
 164 
     | 
    
         
            +
                    expect(ex.response[:request][:headers]).to match(a_hash_including(request_headers))
         
     | 
| 
      
 165 
     | 
    
         
            +
                    expect(ex.response[:request][:body]).to eq(request_body)
         
     | 
| 
      
 166 
     | 
    
         
            +
                  end
         
     | 
| 
      
 167 
     | 
    
         
            +
                end
         
     | 
| 
      
 168 
     | 
    
         
            +
              end
         
     | 
| 
      
 169 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,75 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            RSpec.describe Faraday::Response do
         
     | 
| 
      
 4 
     | 
    
         
            +
              subject { Faraday::Response.new(env) }
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
              let(:env) do
         
     | 
| 
      
 7 
     | 
    
         
            +
                Faraday::Env.from(status: 404, body: 'yikes',
         
     | 
| 
      
 8 
     | 
    
         
            +
                                  response_headers: { 'Content-Type' => 'text/plain' })
         
     | 
| 
      
 9 
     | 
    
         
            +
              end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              it { expect(subject.finished?).to be_truthy }
         
     | 
| 
      
 12 
     | 
    
         
            +
              it { expect { subject.finish({}) }.to raise_error(RuntimeError) }
         
     | 
| 
      
 13 
     | 
    
         
            +
              it { expect(subject.success?).to be_falsey }
         
     | 
| 
      
 14 
     | 
    
         
            +
              it { expect(subject.status).to eq(404) }
         
     | 
| 
      
 15 
     | 
    
         
            +
              it { expect(subject.body).to eq('yikes') }
         
     | 
| 
      
 16 
     | 
    
         
            +
              it { expect(subject.headers['Content-Type']).to eq('text/plain') }
         
     | 
| 
      
 17 
     | 
    
         
            +
              it { expect(subject['content-type']).to eq('text/plain') }
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              describe '#apply_request' do
         
     | 
| 
      
 20 
     | 
    
         
            +
                before { subject.apply_request(body: 'a=b', method: :post) }
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                it { expect(subject.body).to eq('yikes') }
         
     | 
| 
      
 23 
     | 
    
         
            +
                it { expect(subject.env[:method]).to eq(:post) }
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
              describe '#to_hash' do
         
     | 
| 
      
 27 
     | 
    
         
            +
                let(:hash) { subject.to_hash }
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                it { expect(hash).to be_a(Hash) }
         
     | 
| 
      
 30 
     | 
    
         
            +
                it { expect(hash[:status]).to eq(subject.status) }
         
     | 
| 
      
 31 
     | 
    
         
            +
                it { expect(hash[:response_headers]).to eq(subject.headers) }
         
     | 
| 
      
 32 
     | 
    
         
            +
                it { expect(hash[:body]).to eq(subject.body) }
         
     | 
| 
      
 33 
     | 
    
         
            +
              end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
              describe 'marshal serialization support' do
         
     | 
| 
      
 36 
     | 
    
         
            +
                subject { Faraday::Response.new }
         
     | 
| 
      
 37 
     | 
    
         
            +
                let(:loaded) { Marshal.load(Marshal.dump(subject)) }
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                before do
         
     | 
| 
      
 40 
     | 
    
         
            +
                  subject.on_complete {}
         
     | 
| 
      
 41 
     | 
    
         
            +
                  subject.finish(env.merge(params: 'moo'))
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                it { expect(loaded.env[:params]).to be_nil }
         
     | 
| 
      
 45 
     | 
    
         
            +
                it { expect(loaded.env[:body]).to eq(env[:body]) }
         
     | 
| 
      
 46 
     | 
    
         
            +
                it { expect(loaded.env[:response_headers]).to eq(env[:response_headers]) }
         
     | 
| 
      
 47 
     | 
    
         
            +
                it { expect(loaded.env[:status]).to eq(env[:status]) }
         
     | 
| 
      
 48 
     | 
    
         
            +
              end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
              describe '#on_complete' do
         
     | 
| 
      
 51 
     | 
    
         
            +
                subject { Faraday::Response.new }
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                it 'parse body on finish' do
         
     | 
| 
      
 54 
     | 
    
         
            +
                  subject.on_complete { |env| env[:body] = env[:body].upcase }
         
     | 
| 
      
 55 
     | 
    
         
            +
                  subject.finish(env)
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                  expect(subject.body).to eq('YIKES')
         
     | 
| 
      
 58 
     | 
    
         
            +
                end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                it 'can access response body in on_complete callback' do
         
     | 
| 
      
 61 
     | 
    
         
            +
                  subject.on_complete { |env| env[:body] = subject.body.upcase }
         
     | 
| 
      
 62 
     | 
    
         
            +
                  subject.finish(env)
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                  expect(subject.body).to eq('YIKES')
         
     | 
| 
      
 65 
     | 
    
         
            +
                end
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                it 'can access response body in on_complete callback' do
         
     | 
| 
      
 68 
     | 
    
         
            +
                  callback_env = nil
         
     | 
| 
      
 69 
     | 
    
         
            +
                  subject.on_complete { |env| callback_env = env }
         
     | 
| 
      
 70 
     | 
    
         
            +
                  subject.finish({})
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                  expect(subject.env).to eq(callback_env)
         
     | 
| 
      
 73 
     | 
    
         
            +
                end
         
     | 
| 
      
 74 
     | 
    
         
            +
              end
         
     | 
| 
      
 75 
     | 
    
         
            +
            end
         
     |