faraday 0.9.1 → 0.17.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.
Files changed (74) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +212 -0
  3. data/LICENSE.md +1 -1
  4. data/README.md +203 -28
  5. data/Rakefile +6 -64
  6. data/lib/faraday/adapter/em_http.rb +17 -11
  7. data/lib/faraday/adapter/em_http_ssl_patch.rb +1 -1
  8. data/lib/faraday/adapter/em_synchrony.rb +19 -5
  9. data/lib/faraday/adapter/excon.rb +13 -11
  10. data/lib/faraday/adapter/httpclient.rb +31 -9
  11. data/lib/faraday/adapter/net_http.rb +36 -14
  12. data/lib/faraday/adapter/net_http_persistent.rb +37 -17
  13. data/lib/faraday/adapter/patron.rb +44 -21
  14. data/lib/faraday/adapter/rack.rb +1 -1
  15. data/lib/faraday/adapter/test.rb +79 -28
  16. data/lib/faraday/adapter/typhoeus.rb +4 -115
  17. data/lib/faraday/adapter.rb +10 -1
  18. data/lib/faraday/autoload.rb +1 -1
  19. data/lib/faraday/connection.rb +72 -20
  20. data/lib/faraday/deprecate.rb +107 -0
  21. data/lib/faraday/error.rb +132 -27
  22. data/lib/faraday/options.rb +45 -22
  23. data/lib/faraday/parameters.rb +56 -39
  24. data/lib/faraday/rack_builder.rb +29 -4
  25. data/lib/faraday/request/authorization.rb +1 -2
  26. data/lib/faraday/request/multipart.rb +7 -2
  27. data/lib/faraday/request/retry.rb +84 -19
  28. data/lib/faraday/request.rb +22 -0
  29. data/lib/faraday/response/logger.rb +29 -8
  30. data/lib/faraday/response/raise_error.rb +7 -3
  31. data/lib/faraday/response.rb +9 -5
  32. data/lib/faraday/utils.rb +32 -3
  33. data/lib/faraday.rb +15 -36
  34. data/spec/faraday/deprecate_spec.rb +69 -0
  35. data/spec/faraday/error_spec.rb +102 -0
  36. data/spec/faraday/response/raise_error_spec.rb +106 -0
  37. data/spec/spec_helper.rb +105 -0
  38. data/test/adapters/em_http_test.rb +10 -0
  39. data/test/adapters/em_synchrony_test.rb +22 -10
  40. data/test/adapters/excon_test.rb +10 -0
  41. data/test/adapters/httpclient_test.rb +14 -1
  42. data/test/adapters/integration.rb +17 -8
  43. data/test/adapters/logger_test.rb +65 -11
  44. data/test/adapters/net_http_persistent_test.rb +96 -2
  45. data/test/adapters/net_http_test.rb +67 -2
  46. data/test/adapters/patron_test.rb +28 -8
  47. data/test/adapters/rack_test.rb +8 -1
  48. data/test/adapters/test_middleware_test.rb +46 -3
  49. data/test/adapters/typhoeus_test.rb +19 -9
  50. data/test/composite_read_io_test.rb +16 -18
  51. data/test/connection_test.rb +294 -78
  52. data/test/env_test.rb +55 -5
  53. data/test/helper.rb +11 -17
  54. data/test/middleware/retry_test.rb +115 -10
  55. data/test/middleware_stack_test.rb +97 -10
  56. data/test/options_test.rb +97 -16
  57. data/test/parameters_test.rb +94 -1
  58. data/test/request_middleware_test.rb +24 -40
  59. data/test/response_middleware_test.rb +4 -4
  60. data/test/utils_test.rb +40 -0
  61. metadata +21 -66
  62. data/.document +0 -6
  63. data/CONTRIBUTING.md +0 -36
  64. data/Gemfile +0 -25
  65. data/faraday.gemspec +0 -34
  66. data/script/cached-bundle +0 -46
  67. data/script/console +0 -7
  68. data/script/generate_certs +0 -42
  69. data/script/package +0 -7
  70. data/script/proxy-server +0 -42
  71. data/script/release +0 -17
  72. data/script/s3-put +0 -71
  73. data/script/server +0 -36
  74. data/script/test +0 -172
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Faraday::ClientError do
4
+ describe '.initialize' do
5
+ subject { described_class.new(exception, response) }
6
+ let(:response) { nil }
7
+
8
+ context 'with exception only' do
9
+ let(:exception) { RuntimeError.new('test') }
10
+
11
+ it { expect(subject.wrapped_exception).to eq(exception) }
12
+ it { expect(subject.response).to be_nil }
13
+ it { expect(subject.message).to eq(exception.message) }
14
+ it { expect(subject.backtrace).to eq(exception.backtrace) }
15
+ it { expect(subject.inspect).to eq('#<Faraday::ClientError wrapped=#<RuntimeError: test>>') }
16
+ end
17
+
18
+ context 'with response hash' do
19
+ let(:exception) { { status: 400 } }
20
+
21
+ it { expect(subject.wrapped_exception).to be_nil }
22
+ it { expect(subject.response).to eq(exception) }
23
+ it { expect(subject.message).to eq('the server responded with status 400') }
24
+ it { expect(subject.inspect).to eq('#<Faraday::ClientError response={:status=>400}>') }
25
+ end
26
+
27
+ context 'with string' do
28
+ let(:exception) { 'custom message' }
29
+
30
+ it { expect(subject.wrapped_exception).to be_nil }
31
+ it { expect(subject.response).to be_nil }
32
+ it { expect(subject.message).to eq('custom message') }
33
+ it { expect(subject.inspect).to eq('#<Faraday::ClientError #<Faraday::ClientError: custom message>>') }
34
+ end
35
+
36
+ context 'with anything else #to_s' do
37
+ let(:exception) { %w[error1 error2] }
38
+
39
+ it { expect(subject.wrapped_exception).to be_nil }
40
+ it { expect(subject.response).to be_nil }
41
+ it { expect(subject.message).to eq('["error1", "error2"]') }
42
+ it { expect(subject.inspect).to eq('#<Faraday::ClientError #<Faraday::ClientError: ["error1", "error2"]>>') }
43
+ end
44
+
45
+ context 'maintains backward-compatibility until 1.0' do
46
+ it 'does not raise an error for error-namespaced classes but prints an error message' do
47
+ error_message, error = with_warn_squelching { Faraday::Error::ClientError.new('foo') }
48
+
49
+ expect(error).to be_a Faraday::ClientError
50
+ expect(error_message).to match(
51
+ Regexp.new(
52
+ 'NOTE: Faraday::Error::ClientError.new is deprecated; '\
53
+ 'use Faraday::ClientError.new instead. It will be removed in or after version 1.0'
54
+ )
55
+ )
56
+ end
57
+
58
+ it 'does not raise an error for inherited error-namespaced classes but prints an error message' do
59
+ error_message, = with_warn_squelching { Class.new(Faraday::Error::ClientError) }
60
+
61
+ expect(error_message).to match(
62
+ Regexp.new(
63
+ 'NOTE: Inheriting Faraday::Error::ClientError is deprecated; '\
64
+ 'use Faraday::ClientError instead. It will be removed in or after version 1.0'
65
+ )
66
+ )
67
+ end
68
+
69
+ it 'allows backward-compatible class to be subclassed' do
70
+ expect {
71
+ with_warn_squelching { Class.new(Faraday::Error::ClientError) }
72
+ }.not_to raise_error
73
+ end
74
+
75
+ it 'allows rescuing of a current error with a deprecated error' do
76
+ expect { raise Faraday::ClientError, nil }.to raise_error(Faraday::Error::ClientError)
77
+ end
78
+
79
+ it 'allows rescuing of a current error with a current error' do
80
+ expect { raise Faraday::ClientError, nil }.to raise_error(Faraday::ClientError)
81
+ end
82
+
83
+ it 'allows rescuing of a deprecated error with a deprecated error' do
84
+ expect { raise Faraday::Error::ClientError, nil }.to raise_error(Faraday::Error::ClientError)
85
+ end
86
+
87
+ it 'allows rescuing of a deprecated error with a current error' do
88
+ expect { raise Faraday::Error::ClientError, nil }.to raise_error(Faraday::ClientError)
89
+ end
90
+ end
91
+
92
+ def with_warn_squelching
93
+ stderr_catcher = StringIO.new
94
+ original_stderr = $stderr
95
+ $stderr = stderr_catcher
96
+ result = yield if block_given?
97
+ [stderr_catcher.tap(&:rewind).string, result]
98
+ ensure
99
+ $stderr = original_stderr
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,106 @@
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::ClientError for 400 responses' do
28
+ expect { conn.get('bad-request') }.to raise_error(Faraday::ClientError) 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
+ end
33
+ end
34
+
35
+ it 'raises Faraday::ClientError for 401 responses' do
36
+ expect { conn.get('unauthorized') }.to raise_error(Faraday::ClientError) do |ex|
37
+ expect(ex.message).to eq('the server responded with status 401')
38
+ expect(ex.response[:headers]['X-Reason']).to eq('because')
39
+ expect(ex.response[:status]).to eq(401)
40
+ end
41
+ end
42
+
43
+ it 'raises Faraday::ClientError for 403 responses' do
44
+ expect { conn.get('forbidden') }.to raise_error(Faraday::ClientError) do |ex|
45
+ expect(ex.message).to eq('the server responded with status 403')
46
+ expect(ex.response[:headers]['X-Reason']).to eq('because')
47
+ expect(ex.response[:status]).to eq(403)
48
+ end
49
+ end
50
+
51
+ it 'raises Faraday::ResourceNotFound for 404 responses' do
52
+ expect { conn.get('not-found') }.to raise_error(Faraday::ResourceNotFound) do |ex|
53
+ expect(ex.message).to eq('the server responded with status 404')
54
+ expect(ex.response[:headers]['X-Reason']).to eq('because')
55
+ expect(ex.response[:status]).to eq(404)
56
+ end
57
+ end
58
+
59
+ it 'raises Faraday::ConnectionFailed for 407 responses' do
60
+ expect { conn.get('proxy-error') }.to raise_error(Faraday::ConnectionFailed) do |ex|
61
+ expect(ex.message).to eq('407 "Proxy Authentication Required "')
62
+ expect(ex.response[:headers]['X-Reason']).to eq('because')
63
+ expect(ex.response[:status]).to eq(407)
64
+ end
65
+ end
66
+
67
+ it 'raises Faraday::ClientError for 409 responses' do
68
+ expect { conn.get('conflict') }.to raise_error(Faraday::ClientError) do |ex|
69
+ expect(ex.message).to eq('the server responded with status 409')
70
+ expect(ex.response[:headers]['X-Reason']).to eq('because')
71
+ expect(ex.response[:status]).to eq(409)
72
+ end
73
+ end
74
+
75
+ it 'raises Faraday::ClientError for 422 responses' do
76
+ expect { conn.get('unprocessable-entity') }.to raise_error(Faraday::ClientError) do |ex|
77
+ expect(ex.message).to eq('the server responded with status 422')
78
+ expect(ex.response[:headers]['X-Reason']).to eq('because')
79
+ expect(ex.response[:status]).to eq(422)
80
+ end
81
+ end
82
+
83
+ it 'raises Faraday::NilStatusError for nil status in response' do
84
+ expect { conn.get('nil-status') }.to raise_error(Faraday::NilStatusError) do |ex|
85
+ expect(ex.message).to eq('http status could not be derived from the server response')
86
+ expect(ex.response[:headers]['X-Reason']).to eq('nil')
87
+ expect(ex.response[:status]).to be_nil
88
+ end
89
+ end
90
+
91
+ it 'raises Faraday::ClientError for other 4xx responses' do
92
+ expect { conn.get('4xx') }.to raise_error(Faraday::ClientError) do |ex|
93
+ expect(ex.message).to eq('the server responded with status 499')
94
+ expect(ex.response[:headers]['X-Reason']).to eq('because')
95
+ expect(ex.response[:status]).to eq(499)
96
+ end
97
+ end
98
+
99
+ it 'raises Faraday::ClientError for 500 responses' do
100
+ expect { conn.get('server-error') }.to raise_error(Faraday::ClientError) do |ex|
101
+ expect(ex.message).to eq('the server responded with status 500')
102
+ expect(ex.response[:headers]['X-Error']).to eq('bailout')
103
+ expect(ex.response[:status]).to eq(500)
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'faraday'
4
+ Faraday::Deprecate.skip = false
5
+
6
+ # This file was generated by the `rspec --init` command. Conventionally, all
7
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
8
+ # The generated `.rspec` file contains `--require spec_helper` which will cause
9
+ # this file to always be loaded, without a need to explicitly require it in any
10
+ # files.
11
+ #
12
+ # Given that it is always loaded, you are encouraged to keep this file as
13
+ # light-weight as possible. Requiring heavyweight dependencies from this file
14
+ # will add to the boot time of your test suite on EVERY test run, even for an
15
+ # individual file that may not need all of that loaded. Instead, consider making
16
+ # a separate helper file that requires the additional dependencies and performs
17
+ # the additional setup, and require it from the spec files that actually need
18
+ # it.
19
+ #
20
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
21
+ RSpec.configure do |config|
22
+ # rspec-expectations config goes here. You can use an alternate
23
+ # assertion/expectation library such as wrong or the stdlib/minitest
24
+ # assertions if you prefer.
25
+ config.expect_with :rspec do |expectations|
26
+ # This option will default to `true` in RSpec 4. It makes the `description`
27
+ # and `failure_message` of custom matchers include text for helper methods
28
+ # defined using `chain`, e.g.:
29
+ # be_bigger_than(2).and_smaller_than(4).description
30
+ # # => "be bigger than 2 and smaller than 4"
31
+ # ...rather than:
32
+ # # => "be bigger than 2"
33
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
34
+ end
35
+
36
+ # rspec-mocks config goes here. You can use an alternate test double
37
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
38
+ config.mock_with :rspec do |mocks|
39
+ # Prevents you from mocking or stubbing a method that does not exist on
40
+ # a real object. This is generally recommended, and will default to
41
+ # `true` in RSpec 4.
42
+ mocks.verify_partial_doubles = true
43
+ end
44
+
45
+ # This option will default to `:apply_to_host_groups` in RSpec 4 (and will
46
+ # have no way to turn it off -- the option exists only for backwards
47
+ # compatibility in RSpec 3). It causes shared context metadata to be
48
+ # inherited by the metadata hash of host groups and examples, rather than
49
+ # triggering implicit auto-inclusion in groups with matching metadata.
50
+ config.shared_context_metadata_behavior = :apply_to_host_groups
51
+
52
+ # Run specs in random order to surface order dependencies. If you find an
53
+ # order dependency and want to debug it, you can fix the order by providing
54
+ # the seed, which is printed after each run.
55
+ # --seed 1234
56
+ config.order = :random
57
+
58
+ # Seed global randomization in this process using the `--seed` CLI option.
59
+ # Setting this allows you to use `--seed` to deterministically reproduce
60
+ # test failures related to randomization by passing the same `--seed` value
61
+ # as the one that triggered the failure.
62
+ Kernel.srand config.seed
63
+
64
+ # Limits the available syntax to the non-monkey patched syntax that is
65
+ # recommended. For more details, see:
66
+ # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
67
+ # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
68
+ # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
69
+ config.disable_monkey_patching!
70
+
71
+ # The settings below are suggested to provide a good initial experience
72
+ # with RSpec, but feel free to customize to your heart's content.
73
+ =begin
74
+ # This allows you to limit a spec run to individual examples or groups
75
+ # you care about by tagging them with `:focus` metadata. When nothing
76
+ # is tagged with `:focus`, all examples get run. RSpec also provides
77
+ # aliases for `it`, `describe`, and `context` that include `:focus`
78
+ # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
79
+ config.filter_run_when_matching :focus
80
+
81
+ # Allows RSpec to persist some state between runs in order to support
82
+ # the `--only-failures` and `--next-failure` CLI options. We recommend
83
+ # you configure your source control system to ignore this file.
84
+ config.example_status_persistence_file_path = "spec/examples.txt"
85
+
86
+ # This setting enables warnings. It's recommended, but in some cases may
87
+ # be too noisy due to issues in dependencies.
88
+ config.warnings = true
89
+
90
+ # Many RSpec users commonly either run the entire suite or an individual
91
+ # file, and it's useful to allow more verbose output when running an
92
+ # individual spec file.
93
+ if config.files_to_run.one?
94
+ # Use the documentation formatter for detailed output,
95
+ # unless a formatter has already been configured
96
+ # (e.g. via a command-line flag).
97
+ config.default_formatter = "doc"
98
+ end
99
+
100
+ # Print the 10 slowest examples and example groups at the
101
+ # end of the spec run, to help surface which specs are running
102
+ # particularly slow.
103
+ config.profile_examples = 10
104
+ =end
105
+ end
@@ -16,5 +16,15 @@ module Adapters
16
16
  end
17
17
  end unless jruby? and ssl_mode?
18
18
  # https://github.com/eventmachine/eventmachine/issues/180
19
+
20
+ def test_custom_adapter_config
21
+ url = URI('https://example.com:1234')
22
+
23
+ adapter = Faraday::Adapter::EMHttp.new nil, inactivity_timeout: 20
24
+
25
+ req = adapter.create_request(url: url, request: {})
26
+
27
+ assert_equal 20, req.connopts.inactivity_timeout
28
+ end
19
29
  end
20
30
  end
@@ -5,16 +5,28 @@ module Adapters
5
5
 
6
6
  def adapter() :em_synchrony end
7
7
 
8
- Integration.apply(self, :Parallel) do
9
- # https://github.com/eventmachine/eventmachine/pull/289
10
- undef :test_timeout
11
-
12
- def test_binds_local_socket
13
- host = '1.2.3.4'
14
- conn = create_connection :request => { :bind => { :host => host } }
15
- #put conn.get('/who-am-i').body
16
- assert_equal host, conn.options[:bind][:host]
8
+ unless jruby?
9
+ Integration.apply(self, :Parallel) do
10
+ # https://github.com/eventmachine/eventmachine/pull/289
11
+ undef :test_timeout
12
+
13
+ def test_binds_local_socket
14
+ host = '1.2.3.4'
15
+ conn = create_connection :request => { :bind => { :host => host } }
16
+ #put conn.get('/who-am-i').body
17
+ assert_equal host, conn.options[:bind][:host]
18
+ end
17
19
  end
18
- end unless RUBY_VERSION < '1.9' or jruby?
20
+ end
21
+
22
+ def test_custom_adapter_config
23
+ url = URI('https://example.com:1234')
24
+
25
+ adapter = Faraday::Adapter::EMSynchrony.new nil, inactivity_timeout: 20
26
+
27
+ req = adapter.create_request(url: url, request: {})
28
+
29
+ assert_equal 20, req.connopts.inactivity_timeout
30
+ end
19
31
  end
20
32
  end
@@ -16,5 +16,15 @@ module Adapters
16
16
  # https://github.com/geemus/excon/issues/358
17
17
  undef :test_connection_error if RUBY_VERSION >= '2.1.0'
18
18
  end
19
+
20
+ def test_custom_adapter_config
21
+ url = URI('https://example.com:1234')
22
+
23
+ adapter = Faraday::Adapter::Excon.new nil, debug_request: true
24
+
25
+ conn = adapter.create_connection({url: url}, {})
26
+
27
+ assert_equal true, conn.data[:debug_request]
28
+ end
19
29
  end
20
30
  end
@@ -5,7 +5,7 @@ module Adapters
5
5
 
6
6
  def adapter() :httpclient end
7
7
 
8
- Integration.apply(self, :NonParallel) do
8
+ Integration.apply(self, :NonParallel, :Compression) do
9
9
  def setup
10
10
  require 'httpclient' unless defined?(HTTPClient)
11
11
  HTTPClient::NO_PROXY_HOSTS.delete('localhost')
@@ -16,6 +16,19 @@ module Adapters
16
16
  conn = create_connection :request => { :bind => { :host => host } }
17
17
  assert_equal host, conn.options[:bind][:host]
18
18
  end
19
+
20
+ def test_custom_adapter_config
21
+ adapter = Faraday::Adapter::HTTPClient.new do |client|
22
+ client.keep_alive_timeout = 20
23
+ client.ssl_config.timeout = 25
24
+ end
25
+
26
+ client = adapter.client
27
+ adapter.configure_client
28
+
29
+ assert_equal 20, client.keep_alive_timeout
30
+ assert_equal 25, client.ssl_config.timeout
31
+ end
19
32
  end
20
33
  end
21
34
  end
@@ -9,7 +9,7 @@ module Adapters
9
9
  # `#adapter_options` optional. extra arguments for building an adapter
10
10
  module Integration
11
11
  def self.apply(base, *extra_features)
12
- if base.live_server?
12
+ if base.live_server
13
13
  features = [:Common]
14
14
  features.concat extra_features
15
15
  features << :SSL if base.ssl_mode?
@@ -18,6 +18,7 @@ module Adapters
18
18
  elsif !defined? @warned
19
19
  warn "Warning: Not running integration tests against a live server."
20
20
  warn "Start the server `ruby test/live_server.rb` and set the LIVE=1 env variable."
21
+ warn "See CONTRIBUTING for usage."
21
22
  @warned = true
22
23
  end
23
24
  end
@@ -59,7 +60,8 @@ module Adapters
59
60
  module Compression
60
61
  def test_GET_handles_compression
61
62
  res = get('echo_header', :name => 'accept-encoding')
62
- assert_match(/gzip;.+\bdeflate\b/, res.body)
63
+ assert_match(/\bgzip\b/, res.body)
64
+ assert_match(/\bdeflate\b/, res.body)
63
65
  end
64
66
  end
65
67
 
@@ -113,6 +115,11 @@ module Adapters
113
115
  assert_equal expected, get('ssl').body
114
116
  end
115
117
 
118
+ def test_GET_reason_phrase
119
+ response = get('echo')
120
+ assert_equal "OK", response.reason_phrase
121
+ end
122
+
116
123
  def test_POST_send_url_encoded_params
117
124
  assert_equal %(post {"name"=>"zack"}), post('echo', :name => 'zack').body
118
125
  end
@@ -173,13 +180,13 @@ module Adapters
173
180
 
174
181
  def test_timeout
175
182
  conn = create_connection(:request => {:timeout => 1, :open_timeout => 1})
176
- assert_raises Faraday::Error::TimeoutError do
183
+ assert_raises Faraday::TimeoutError do
177
184
  conn.get '/slow'
178
185
  end
179
186
  end
180
187
 
181
188
  def test_connection_error
182
- assert_raises Faraday::Error::ConnectionFailed do
189
+ assert_raises Faraday::ConnectionFailed do
183
190
  get 'http://localhost:4'
184
191
  end
185
192
  end
@@ -202,12 +209,14 @@ module Adapters
202
209
  proxy_uri.password = 'WRONG'
203
210
  conn = create_connection(:proxy => proxy_uri)
204
211
 
205
- err = assert_raises Faraday::Error::ConnectionFailed do
212
+ err = assert_raises Faraday::ConnectionFailed do
206
213
  conn.get '/echo'
207
214
  end
208
215
 
209
- unless self.class.ssl_mode? && self.class.jruby?
216
+ unless self.class.ssl_mode? && (self.class.jruby? ||
217
+ adapter == :em_http || adapter == :em_synchrony)
210
218
  # JRuby raises "End of file reached" which cannot be distinguished from a 407
219
+ # EM raises "connection closed by server" due to https://github.com/igrigorik/em-socksify/pull/19
211
220
  assert_equal %{407 "Proxy Authentication Required "}, err.message
212
221
  end
213
222
  end
@@ -226,14 +235,14 @@ module Adapters
226
235
  []
227
236
  end
228
237
 
229
- def create_connection(options = {})
238
+ def create_connection(options = {}, &optional_connection_config_blk)
230
239
  if adapter == :default
231
240
  builder_block = nil
232
241
  else
233
242
  builder_block = Proc.new do |b|
234
243
  b.request :multipart
235
244
  b.request :url_encoded
236
- b.adapter adapter, *adapter_options
245
+ b.adapter adapter, *adapter_options, &optional_connection_config_blk
237
246
  end
238
247
  end
239
248
 
@@ -8,13 +8,20 @@ module Adapters
8
8
  rubbles = ['Barney', 'Betty', 'Bam Bam']
9
9
 
10
10
  Faraday.new do |b|
11
- b.response :logger, logger, logger_options
11
+ b.response :logger, @logger, logger_options do | logger |
12
+ logger.filter(/(soylent green is) (.+)/,'\1 tasty')
13
+ logger.filter(/(api_key:).*"(.+)."/,'\1[API_KEY]')
14
+ logger.filter(/(password)=(.+)/,'\1=[HIDDEN]')
15
+ end
12
16
  b.adapter :test do |stubs|
13
17
  stubs.get('/hello') { [200, {'Content-Type' => 'text/html'}, 'hello'] }
14
18
  stubs.post('/ohai') { [200, {'Content-Type' => 'text/html'}, 'fred'] }
15
- stubs.get('/ohno') { [200, {'Content-Type' => 'text/html'}, 'wilma'] }
16
19
  stubs.post('/ohyes') { [200, {'Content-Type' => 'text/html'}, 'pebbles'] }
17
20
  stubs.get('/rubbles') { [200, {'Content-Type' => 'application/json'}, rubbles] }
21
+ stubs.get('/filtered_body') { [200, {'Content-Type' => 'text/html'}, 'soylent green is people'] }
22
+ stubs.get('/filtered_headers') { [200, {'Content-Type' => 'text/html'}, 'headers response'] }
23
+ stubs.get('/filtered_params') { [200, {'Content-Type' => 'text/html'}, 'params response'] }
24
+ stubs.get('/filtered_url') { [200, {'Content-Type' => 'text/html'}, 'url response'] }
18
25
  end
19
26
  end
20
27
  end
@@ -25,25 +32,45 @@ module Adapters
25
32
  @logger.level = Logger::DEBUG
26
33
 
27
34
  @conn = conn(@logger)
28
- @resp = @conn.get '/hello', nil, :accept => 'text/html'
29
35
  end
30
36
 
31
37
  def test_still_returns_output
32
- assert_equal 'hello', @resp.body
38
+ resp = @conn.get '/hello', nil, :accept => 'text/html'
39
+ assert_equal 'hello', resp.body
33
40
  end
34
41
 
35
42
  def test_logs_method_and_url
36
- assert_match "get http:/hello", @io.string
43
+ @conn.get '/hello', nil, :accept => 'text/html'
44
+ assert_match 'request: GET http:/hello', @io.string
45
+ end
46
+
47
+ def test_logs_status_code
48
+ @conn.get '/hello', nil, :accept => 'text/html'
49
+ assert_match 'response: Status 200', @io.string
37
50
  end
38
51
 
39
- def test_logs_request_headers
52
+ def test_logs_request_headers_by_default
53
+ @conn.get '/hello', nil, :accept => 'text/html'
40
54
  assert_match %(Accept: "text/html), @io.string
41
55
  end
42
56
 
43
- def test_logs_response_headers
57
+ def test_logs_response_headers_by_default
58
+ @conn.get '/hello', nil, :accept => 'text/html'
44
59
  assert_match %(Content-Type: "text/html), @io.string
45
60
  end
46
61
 
62
+ def test_does_not_log_request_headers_if_option_is_false
63
+ app = conn(@logger, :headers => { :request => false })
64
+ app.get '/hello', nil, :accept => 'text/html'
65
+ refute_match %(Accept: "text/html), @io.string
66
+ end
67
+
68
+ def test_does_log_response_headers_if_option_is_false
69
+ app = conn(@logger, :headers => { :response => false })
70
+ app.get '/hello', nil, :accept => 'text/html'
71
+ refute_match %(Content-Type: "text/html), @io.string
72
+ end
73
+
47
74
  def test_does_not_log_request_body_by_default
48
75
  @conn.post '/ohai', 'name=Unagi', :accept => 'text/html'
49
76
  refute_match %(name=Unagi), @io.string
@@ -54,16 +81,18 @@ module Adapters
54
81
  refute_match %(fred), @io.string
55
82
  end
56
83
 
57
- def test_log_request_body
84
+ def test_log_only_request_body
58
85
  app = conn(@logger, :bodies => { :request => true })
59
86
  app.post '/ohyes', 'name=Tamago', :accept => 'text/html'
60
87
  assert_match %(name=Tamago), @io.string
88
+ refute_match %(pebbles), @io.string
61
89
  end
62
90
 
63
- def test_log_response_body
91
+ def test_log_only_response_body
64
92
  app = conn(@logger, :bodies => { :response => true })
65
- app.get '/ohno', :accept => 'text/html'
66
- assert_match %(wilma), @io.string
93
+ app.post '/ohyes', 'name=Hamachi', :accept => 'text/html'
94
+ assert_match %(pebbles), @io.string
95
+ refute_match %(name=Hamachi), @io.string
67
96
  end
68
97
 
69
98
  def test_log_request_and_response_body
@@ -78,5 +107,30 @@ module Adapters
78
107
  app.get '/rubbles', nil, :accept => 'text/html'
79
108
  assert_match %([\"Barney\", \"Betty\", \"Bam Bam\"]\n), @io.string
80
109
  end
110
+
111
+ def test_logs_filter_body
112
+ app = conn(@logger, :bodies => true)
113
+ app.get '/filtered_body', nil, :accept => 'text/html'
114
+ assert_match %(soylent green is), @io.string
115
+ assert_match %(tasty), @io.string
116
+ refute_match %(people), @io.string
117
+ end
118
+
119
+ def test_logs_filter_headers
120
+ app = conn(@logger)
121
+ app.headers = {'api_key' => 'ABC123'}
122
+ app.get '/filtered_headers', nil, :accept => 'text/html'
123
+ assert_match %(api_key:), @io.string
124
+ assert_match %([API_KEY]), @io.string
125
+ refute_match %(ABC123), @io.string
126
+ end
127
+
128
+ def test_logs_filter_url
129
+ app = conn(@logger)
130
+ app.get '/filtered_url?password=hunter2', nil, :accept => 'text/html'
131
+ assert_match %(password=[HIDDEN]), @io.string
132
+ refute_match %(hunter2), @io.string
133
+ end
134
+
81
135
  end
82
136
  end