faraday 0.17.0 → 0.17.1

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 (52) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +216 -0
  3. data/Rakefile +13 -0
  4. data/lib/faraday.rb +1 -1
  5. data/lib/faraday/adapter/em_http.rb +9 -9
  6. data/lib/faraday/adapter/em_synchrony.rb +5 -5
  7. data/lib/faraday/adapter/excon.rb +3 -3
  8. data/lib/faraday/adapter/httpclient.rb +4 -4
  9. data/lib/faraday/adapter/net_http.rb +2 -2
  10. data/lib/faraday/adapter/net_http_persistent.rb +3 -3
  11. data/lib/faraday/adapter/patron.rb +5 -5
  12. data/lib/faraday/adapter/rack.rb +1 -1
  13. data/lib/faraday/deprecate.rb +101 -0
  14. data/lib/faraday/error.rb +85 -32
  15. data/lib/faraday/options.rb +1 -1
  16. data/lib/faraday/request/retry.rb +6 -5
  17. data/lib/faraday/response.rb +3 -3
  18. data/lib/faraday/response/raise_error.rb +7 -3
  19. data/spec/faraday/deprecate_spec.rb +69 -0
  20. data/spec/faraday/error_spec.rb +102 -0
  21. data/spec/faraday/response/raise_error_spec.rb +95 -0
  22. data/spec/spec_helper.rb +104 -0
  23. data/test/adapters/default_test.rb +14 -0
  24. data/test/adapters/em_http_test.rb +30 -0
  25. data/test/adapters/em_synchrony_test.rb +32 -0
  26. data/test/adapters/excon_test.rb +30 -0
  27. data/test/adapters/httpclient_test.rb +34 -0
  28. data/test/adapters/integration.rb +263 -0
  29. data/test/adapters/logger_test.rb +136 -0
  30. data/test/adapters/net_http_persistent_test.rb +114 -0
  31. data/test/adapters/net_http_test.rb +79 -0
  32. data/test/adapters/patron_test.rb +40 -0
  33. data/test/adapters/rack_test.rb +38 -0
  34. data/test/adapters/test_middleware_test.rb +157 -0
  35. data/test/adapters/typhoeus_test.rb +38 -0
  36. data/test/authentication_middleware_test.rb +65 -0
  37. data/test/composite_read_io_test.rb +109 -0
  38. data/test/connection_test.rb +738 -0
  39. data/test/env_test.rb +268 -0
  40. data/test/helper.rb +75 -0
  41. data/test/live_server.rb +67 -0
  42. data/test/middleware/instrumentation_test.rb +88 -0
  43. data/test/middleware/retry_test.rb +282 -0
  44. data/test/middleware_stack_test.rb +260 -0
  45. data/test/multibyte.txt +1 -0
  46. data/test/options_test.rb +333 -0
  47. data/test/parameters_test.rb +157 -0
  48. data/test/request_middleware_test.rb +126 -0
  49. data/test/response_middleware_test.rb +72 -0
  50. data/test/strawberry.rb +2 -0
  51. data/test/utils_test.rb +98 -0
  52. metadata +47 -5
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'faraday'
4
+
5
+ # This file was generated by the `rspec --init` command. Conventionally, all
6
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
7
+ # The generated `.rspec` file contains `--require spec_helper` which will cause
8
+ # this file to always be loaded, without a need to explicitly require it in any
9
+ # files.
10
+ #
11
+ # Given that it is always loaded, you are encouraged to keep this file as
12
+ # light-weight as possible. Requiring heavyweight dependencies from this file
13
+ # will add to the boot time of your test suite on EVERY test run, even for an
14
+ # individual file that may not need all of that loaded. Instead, consider making
15
+ # a separate helper file that requires the additional dependencies and performs
16
+ # the additional setup, and require it from the spec files that actually need
17
+ # it.
18
+ #
19
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
20
+ RSpec.configure do |config|
21
+ # rspec-expectations config goes here. You can use an alternate
22
+ # assertion/expectation library such as wrong or the stdlib/minitest
23
+ # assertions if you prefer.
24
+ config.expect_with :rspec do |expectations|
25
+ # This option will default to `true` in RSpec 4. It makes the `description`
26
+ # and `failure_message` of custom matchers include text for helper methods
27
+ # defined using `chain`, e.g.:
28
+ # be_bigger_than(2).and_smaller_than(4).description
29
+ # # => "be bigger than 2 and smaller than 4"
30
+ # ...rather than:
31
+ # # => "be bigger than 2"
32
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
33
+ end
34
+
35
+ # rspec-mocks config goes here. You can use an alternate test double
36
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
37
+ config.mock_with :rspec do |mocks|
38
+ # Prevents you from mocking or stubbing a method that does not exist on
39
+ # a real object. This is generally recommended, and will default to
40
+ # `true` in RSpec 4.
41
+ mocks.verify_partial_doubles = true
42
+ end
43
+
44
+ # This option will default to `:apply_to_host_groups` in RSpec 4 (and will
45
+ # have no way to turn it off -- the option exists only for backwards
46
+ # compatibility in RSpec 3). It causes shared context metadata to be
47
+ # inherited by the metadata hash of host groups and examples, rather than
48
+ # triggering implicit auto-inclusion in groups with matching metadata.
49
+ config.shared_context_metadata_behavior = :apply_to_host_groups
50
+
51
+ # Run specs in random order to surface order dependencies. If you find an
52
+ # order dependency and want to debug it, you can fix the order by providing
53
+ # the seed, which is printed after each run.
54
+ # --seed 1234
55
+ config.order = :random
56
+
57
+ # Seed global randomization in this process using the `--seed` CLI option.
58
+ # Setting this allows you to use `--seed` to deterministically reproduce
59
+ # test failures related to randomization by passing the same `--seed` value
60
+ # as the one that triggered the failure.
61
+ Kernel.srand config.seed
62
+
63
+ # Limits the available syntax to the non-monkey patched syntax that is
64
+ # recommended. For more details, see:
65
+ # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
66
+ # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
67
+ # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
68
+ config.disable_monkey_patching!
69
+
70
+ # The settings below are suggested to provide a good initial experience
71
+ # with RSpec, but feel free to customize to your heart's content.
72
+ =begin
73
+ # This allows you to limit a spec run to individual examples or groups
74
+ # you care about by tagging them with `:focus` metadata. When nothing
75
+ # is tagged with `:focus`, all examples get run. RSpec also provides
76
+ # aliases for `it`, `describe`, and `context` that include `:focus`
77
+ # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
78
+ config.filter_run_when_matching :focus
79
+
80
+ # Allows RSpec to persist some state between runs in order to support
81
+ # the `--only-failures` and `--next-failure` CLI options. We recommend
82
+ # you configure your source control system to ignore this file.
83
+ config.example_status_persistence_file_path = "spec/examples.txt"
84
+
85
+ # This setting enables warnings. It's recommended, but in some cases may
86
+ # be too noisy due to issues in dependencies.
87
+ config.warnings = true
88
+
89
+ # Many RSpec users commonly either run the entire suite or an individual
90
+ # file, and it's useful to allow more verbose output when running an
91
+ # individual spec file.
92
+ if config.files_to_run.one?
93
+ # Use the documentation formatter for detailed output,
94
+ # unless a formatter has already been configured
95
+ # (e.g. via a command-line flag).
96
+ config.default_formatter = "doc"
97
+ end
98
+
99
+ # Print the 10 slowest examples and example groups at the
100
+ # end of the spec run, to help surface which specs are running
101
+ # particularly slow.
102
+ config.profile_examples = 10
103
+ =end
104
+ end
@@ -0,0 +1,14 @@
1
+ require File.expand_path('../integration', __FILE__)
2
+
3
+ module Adapters
4
+ class DefaultTest < Faraday::TestCase
5
+
6
+ def adapter() :default end
7
+
8
+ Integration.apply(self, :NonParallel) do
9
+ # default stack is not configured with Multipart
10
+ undef :test_POST_sends_files
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,30 @@
1
+ require File.expand_path('../integration', __FILE__)
2
+
3
+ module Adapters
4
+ class EMHttpTest < Faraday::TestCase
5
+
6
+ def adapter() :em_http end
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
+ assert_equal host, conn.options[:bind][:host]
16
+ end
17
+ end unless jruby? and ssl_mode?
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
29
+ end
30
+ end
@@ -0,0 +1,32 @@
1
+ require File.expand_path('../integration', __FILE__)
2
+
3
+ module Adapters
4
+ class EMSynchronyTest < Faraday::TestCase
5
+
6
+ def adapter() :em_synchrony end
7
+
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
19
+ end
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
31
+ end
32
+ end
@@ -0,0 +1,30 @@
1
+ require File.expand_path('../integration', __FILE__)
2
+
3
+ module Adapters
4
+ class ExconTest < Faraday::TestCase
5
+
6
+ def adapter() :excon end
7
+
8
+ Integration.apply(self, :NonParallel) do
9
+ # https://github.com/geemus/excon/issues/126 ?
10
+ undef :test_timeout if ssl_mode?
11
+
12
+ # Excon lets OpenSSL::SSL::SSLError be raised without any way to
13
+ # distinguish whether it happened because of a 407 proxy response
14
+ undef :test_proxy_auth_fail if ssl_mode?
15
+
16
+ # https://github.com/geemus/excon/issues/358
17
+ undef :test_connection_error if RUBY_VERSION >= '2.1.0'
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
29
+ end
30
+ end
@@ -0,0 +1,34 @@
1
+ require File.expand_path('../integration', __FILE__)
2
+
3
+ module Adapters
4
+ class HttpclientTest < Faraday::TestCase
5
+
6
+ def adapter() :httpclient end
7
+
8
+ Integration.apply(self, :NonParallel, :Compression) do
9
+ def setup
10
+ require 'httpclient' unless defined?(HTTPClient)
11
+ HTTPClient::NO_PROXY_HOSTS.delete('localhost')
12
+ end
13
+
14
+ def test_binds_local_socket
15
+ host = '1.2.3.4'
16
+ conn = create_connection :request => { :bind => { :host => host } }
17
+ assert_equal host, conn.options[:bind][:host]
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
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,263 @@
1
+ require 'forwardable'
2
+ require File.expand_path("../../helper", __FILE__)
3
+ Faraday.require_lib 'autoload'
4
+
5
+ module Adapters
6
+ # Adapter integration tests. To use, implement two methods:
7
+ #
8
+ # `#adapter` required. returns a symbol for the adapter middleware name
9
+ # `#adapter_options` optional. extra arguments for building an adapter
10
+ module Integration
11
+ def self.apply(base, *extra_features)
12
+ if base.live_server
13
+ features = [:Common]
14
+ features.concat extra_features
15
+ features << :SSL if base.ssl_mode?
16
+ features.each {|name| base.send(:include, self.const_get(name)) }
17
+ yield if block_given?
18
+ elsif !defined? @warned
19
+ warn "Warning: Not running integration tests against a live server."
20
+ warn "Start the server `ruby test/live_server.rb` and set the LIVE=1 env variable."
21
+ warn "See CONTRIBUTING for usage."
22
+ @warned = true
23
+ end
24
+ end
25
+
26
+ module Parallel
27
+ def test_in_parallel
28
+ resp1, resp2 = nil, nil
29
+
30
+ connection = create_connection
31
+ connection.in_parallel do
32
+ resp1 = connection.get('echo?a=1')
33
+ resp2 = connection.get('echo?b=2')
34
+ assert connection.in_parallel?
35
+ assert_nil resp1.body
36
+ assert_nil resp2.body
37
+ end
38
+ assert !connection.in_parallel?
39
+ assert_equal 'get ?{"a"=>"1"}', resp1.body
40
+ assert_equal 'get ?{"b"=>"2"}', resp2.body
41
+ end
42
+ end
43
+
44
+ module NonParallel
45
+ def test_no_parallel_support
46
+ connection = create_connection
47
+ response = nil
48
+
49
+ err = capture_warnings do
50
+ connection.in_parallel do
51
+ response = connection.get('echo').body
52
+ end
53
+ end
54
+ assert response
55
+ assert_match "no parallel-capable adapter on Faraday stack", err
56
+ assert_match __FILE__, err
57
+ end
58
+ end
59
+
60
+ module Compression
61
+ def test_GET_handles_compression
62
+ res = get('echo_header', :name => 'accept-encoding')
63
+ assert_match(/\bgzip\b/, res.body)
64
+ assert_match(/\bdeflate\b/, res.body)
65
+ end
66
+ end
67
+
68
+ module SSL
69
+ def test_GET_ssl_fails_with_bad_cert
70
+ ca_file = 'tmp/faraday-different-ca-cert.crt'
71
+ conn = create_connection(:ssl => {:ca_file => ca_file})
72
+ err = assert_raises Faraday::SSLError do
73
+ conn.get('/ssl')
74
+ end
75
+ assert_includes err.message, "certificate"
76
+ end
77
+ end
78
+
79
+ module Common
80
+ extend Forwardable
81
+ def_delegators :create_connection, :get, :head, :put, :post, :patch, :delete, :run_request
82
+
83
+ def test_GET_retrieves_the_response_body
84
+ assert_equal 'get', get('echo').body
85
+ end
86
+
87
+ def test_GET_send_url_encoded_params
88
+ assert_equal %(get ?{"name"=>"zack"}), get('echo', :name => 'zack').body
89
+ end
90
+
91
+ def test_GET_retrieves_the_response_headers
92
+ response = get('echo')
93
+ assert_match(/text\/plain/, response.headers['Content-Type'], 'original case fail')
94
+ assert_match(/text\/plain/, response.headers['content-type'], 'lowercase fail')
95
+ end
96
+
97
+ def test_GET_handles_headers_with_multiple_values
98
+ assert_equal 'one, two', get('multi').headers['set-cookie']
99
+ end
100
+
101
+ def test_GET_with_body
102
+ response = get('echo') do |req|
103
+ req.body = {'bodyrock' => true}
104
+ end
105
+ assert_equal %(get {"bodyrock"=>"true"}), response.body
106
+ end
107
+
108
+ def test_GET_sends_user_agent
109
+ response = get('echo_header', {:name => 'user-agent'}, :user_agent => 'Agent Faraday')
110
+ assert_equal 'Agent Faraday', response.body
111
+ end
112
+
113
+ def test_GET_ssl
114
+ expected = self.class.ssl_mode?.to_s
115
+ assert_equal expected, get('ssl').body
116
+ end
117
+
118
+ def test_GET_reason_phrase
119
+ response = get('echo')
120
+ assert_equal "OK", response.reason_phrase
121
+ end
122
+
123
+ def test_POST_send_url_encoded_params
124
+ assert_equal %(post {"name"=>"zack"}), post('echo', :name => 'zack').body
125
+ end
126
+
127
+ def test_POST_send_url_encoded_nested_params
128
+ resp = post('echo', 'name' => {'first' => 'zack'})
129
+ assert_equal %(post {"name"=>{"first"=>"zack"}}), resp.body
130
+ end
131
+
132
+ def test_POST_retrieves_the_response_headers
133
+ assert_match(/text\/plain/, post('echo').headers['content-type'])
134
+ end
135
+
136
+ def test_POST_sends_files
137
+ resp = post('file') do |req|
138
+ req.body = {'uploaded_file' => Faraday::UploadIO.new(__FILE__, 'text/x-ruby')}
139
+ end
140
+ assert_equal "file integration.rb text/x-ruby #{File.size(__FILE__)}", resp.body
141
+ end
142
+
143
+ def test_PUT_send_url_encoded_params
144
+ assert_equal %(put {"name"=>"zack"}), put('echo', :name => 'zack').body
145
+ end
146
+
147
+ def test_PUT_send_url_encoded_nested_params
148
+ resp = put('echo', 'name' => {'first' => 'zack'})
149
+ assert_equal %(put {"name"=>{"first"=>"zack"}}), resp.body
150
+ end
151
+
152
+ def test_PUT_retrieves_the_response_headers
153
+ assert_match(/text\/plain/, put('echo').headers['content-type'])
154
+ end
155
+
156
+ def test_PATCH_send_url_encoded_params
157
+ assert_equal %(patch {"name"=>"zack"}), patch('echo', :name => 'zack').body
158
+ end
159
+
160
+ def test_OPTIONS
161
+ resp = run_request(:options, 'echo', nil, {})
162
+ assert_equal 'options', resp.body
163
+ end
164
+
165
+ def test_HEAD_retrieves_no_response_body
166
+ assert_equal '', head('echo').body
167
+ end
168
+
169
+ def test_HEAD_retrieves_the_response_headers
170
+ assert_match(/text\/plain/, head('echo').headers['content-type'])
171
+ end
172
+
173
+ def test_DELETE_retrieves_the_response_headers
174
+ assert_match(/text\/plain/, delete('echo').headers['content-type'])
175
+ end
176
+
177
+ def test_DELETE_retrieves_the_body
178
+ assert_equal %(delete), delete('echo').body
179
+ end
180
+
181
+ def test_timeout
182
+ conn = create_connection(:request => {:timeout => 1, :open_timeout => 1})
183
+ assert_raises Faraday::TimeoutError do
184
+ conn.get '/slow'
185
+ end
186
+ end
187
+
188
+ def test_connection_error
189
+ assert_raises Faraday::ConnectionFailed do
190
+ get 'http://localhost:4'
191
+ end
192
+ end
193
+
194
+ def test_proxy
195
+ proxy_uri = URI(ENV['LIVE_PROXY'])
196
+ conn = create_connection(:proxy => proxy_uri)
197
+
198
+ res = conn.get '/echo'
199
+ assert_equal 'get', res.body
200
+
201
+ unless self.class.ssl_mode?
202
+ # proxy can't append "Via" header for HTTPS responses
203
+ assert_match(/:#{proxy_uri.port}$/, res['via'])
204
+ end
205
+ end
206
+
207
+ def test_proxy_auth_fail
208
+ proxy_uri = URI(ENV['LIVE_PROXY'])
209
+ proxy_uri.password = 'WRONG'
210
+ conn = create_connection(:proxy => proxy_uri)
211
+
212
+ err = assert_raises Faraday::ConnectionFailed do
213
+ conn.get '/echo'
214
+ end
215
+
216
+ unless self.class.ssl_mode? && (self.class.jruby? ||
217
+ adapter == :em_http || adapter == :em_synchrony)
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
220
+ assert_equal %{407 "Proxy Authentication Required "}, err.message
221
+ end
222
+ end
223
+
224
+ def test_empty_body_response_represented_as_blank_string
225
+ response = get('204')
226
+ assert_equal '', response.body
227
+ end
228
+
229
+ def adapter
230
+ raise NotImplementedError.new("Need to override #adapter")
231
+ end
232
+
233
+ # extra options to pass when building the adapter
234
+ def adapter_options
235
+ []
236
+ end
237
+
238
+ def create_connection(options = {}, &optional_connection_config_blk)
239
+ if adapter == :default
240
+ builder_block = nil
241
+ else
242
+ builder_block = Proc.new do |b|
243
+ b.request :multipart
244
+ b.request :url_encoded
245
+ b.adapter adapter, *adapter_options, &optional_connection_config_blk
246
+ end
247
+ end
248
+
249
+ server = self.class.live_server
250
+ url = '%s://%s:%d' % [server.scheme, server.host, server.port]
251
+
252
+ options[:ssl] ||= {}
253
+ options[:ssl][:ca_file] ||= ENV['SSL_FILE']
254
+
255
+ Faraday::Connection.new(url, options, &builder_block).tap do |conn|
256
+ conn.headers['X-Faraday-Adapter'] = adapter.to_s
257
+ adapter_handler = conn.builder.handlers.last
258
+ conn.builder.insert_before adapter_handler, Faraday::Response::RaiseError
259
+ end
260
+ end
261
+ end
262
+ end
263
+ end