faraday 0.17.1 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +69 -9
  3. data/LICENSE.md +1 -1
  4. data/README.md +17 -347
  5. data/Rakefile +1 -7
  6. data/examples/client_spec.rb +65 -0
  7. data/examples/client_test.rb +79 -0
  8. data/lib/faraday.rb +94 -176
  9. data/lib/faraday/adapter.rb +83 -22
  10. data/lib/faraday/adapter/em_http.rb +143 -100
  11. data/lib/faraday/adapter/em_http_ssl_patch.rb +24 -18
  12. data/lib/faraday/adapter/em_synchrony.rb +104 -60
  13. data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +18 -15
  14. data/lib/faraday/adapter/excon.rb +98 -56
  15. data/lib/faraday/adapter/httpclient.rb +83 -59
  16. data/lib/faraday/adapter/net_http.rb +130 -63
  17. data/lib/faraday/adapter/net_http_persistent.rb +51 -28
  18. data/lib/faraday/adapter/patron.rb +80 -43
  19. data/lib/faraday/adapter/rack.rb +30 -13
  20. data/lib/faraday/adapter/test.rb +86 -53
  21. data/lib/faraday/adapter/typhoeus.rb +4 -1
  22. data/lib/faraday/adapter_registry.rb +30 -0
  23. data/lib/faraday/autoload.rb +47 -36
  24. data/lib/faraday/connection.rb +312 -182
  25. data/lib/faraday/dependency_loader.rb +39 -0
  26. data/lib/faraday/encoders/flat_params_encoder.rb +105 -0
  27. data/lib/faraday/encoders/nested_params_encoder.rb +176 -0
  28. data/lib/faraday/error.rb +46 -25
  29. data/lib/faraday/file_part.rb +128 -0
  30. data/lib/faraday/logging/formatter.rb +105 -0
  31. data/lib/faraday/middleware.rb +12 -28
  32. data/lib/faraday/middleware_registry.rb +129 -0
  33. data/lib/faraday/options.rb +38 -193
  34. data/lib/faraday/options/connection_options.rb +22 -0
  35. data/lib/faraday/options/env.rb +181 -0
  36. data/lib/faraday/options/proxy_options.rb +28 -0
  37. data/lib/faraday/options/request_options.rb +22 -0
  38. data/lib/faraday/options/ssl_options.rb +59 -0
  39. data/lib/faraday/param_part.rb +53 -0
  40. data/lib/faraday/parameters.rb +4 -197
  41. data/lib/faraday/rack_builder.rb +77 -65
  42. data/lib/faraday/request.rb +86 -44
  43. data/lib/faraday/request/authorization.rb +44 -30
  44. data/lib/faraday/request/basic_authentication.rb +14 -7
  45. data/lib/faraday/request/instrumentation.rb +45 -27
  46. data/lib/faraday/request/multipart.rb +86 -48
  47. data/lib/faraday/request/retry.rb +197 -171
  48. data/lib/faraday/request/token_authentication.rb +15 -10
  49. data/lib/faraday/request/url_encoded.rb +43 -23
  50. data/lib/faraday/response.rb +24 -14
  51. data/lib/faraday/response/logger.rb +22 -69
  52. data/lib/faraday/response/raise_error.rb +49 -18
  53. data/lib/faraday/utils.rb +38 -247
  54. data/lib/faraday/utils/headers.rb +139 -0
  55. data/lib/faraday/utils/params_hash.rb +61 -0
  56. data/spec/external_adapters/faraday_specs_setup.rb +14 -0
  57. data/spec/faraday/adapter/em_http_spec.rb +47 -0
  58. data/spec/faraday/adapter/em_synchrony_spec.rb +16 -0
  59. data/spec/faraday/adapter/excon_spec.rb +49 -0
  60. data/spec/faraday/adapter/httpclient_spec.rb +73 -0
  61. data/spec/faraday/adapter/net_http_persistent_spec.rb +57 -0
  62. data/spec/faraday/adapter/net_http_spec.rb +64 -0
  63. data/spec/faraday/adapter/patron_spec.rb +18 -0
  64. data/spec/faraday/adapter/rack_spec.rb +8 -0
  65. data/spec/faraday/adapter/test_spec.rb +260 -0
  66. data/spec/faraday/adapter/typhoeus_spec.rb +7 -0
  67. data/spec/faraday/adapter_registry_spec.rb +28 -0
  68. data/spec/faraday/adapter_spec.rb +55 -0
  69. data/spec/faraday/composite_read_io_spec.rb +80 -0
  70. data/spec/faraday/connection_spec.rb +691 -0
  71. data/spec/faraday/error_spec.rb +0 -57
  72. data/spec/faraday/middleware_spec.rb +26 -0
  73. data/spec/faraday/options/env_spec.rb +70 -0
  74. data/spec/faraday/options/options_spec.rb +297 -0
  75. data/spec/faraday/options/proxy_options_spec.rb +37 -0
  76. data/spec/faraday/options/request_options_spec.rb +19 -0
  77. data/spec/faraday/params_encoders/flat_spec.rb +42 -0
  78. data/spec/faraday/params_encoders/nested_spec.rb +142 -0
  79. data/spec/faraday/rack_builder_spec.rb +345 -0
  80. data/spec/faraday/request/authorization_spec.rb +88 -0
  81. data/spec/faraday/request/instrumentation_spec.rb +76 -0
  82. data/spec/faraday/request/multipart_spec.rb +302 -0
  83. data/spec/faraday/request/retry_spec.rb +242 -0
  84. data/spec/faraday/request/url_encoded_spec.rb +83 -0
  85. data/spec/faraday/request_spec.rb +120 -0
  86. data/spec/faraday/response/logger_spec.rb +220 -0
  87. data/spec/faraday/response/middleware_spec.rb +68 -0
  88. data/spec/faraday/response/raise_error_spec.rb +60 -16
  89. data/spec/faraday/response_spec.rb +75 -0
  90. data/spec/faraday/utils/headers_spec.rb +82 -0
  91. data/spec/faraday/utils_spec.rb +56 -0
  92. data/spec/faraday_spec.rb +37 -0
  93. data/spec/spec_helper.rb +63 -35
  94. data/spec/support/disabling_stub.rb +14 -0
  95. data/spec/support/fake_safe_buffer.rb +15 -0
  96. data/spec/support/helper_methods.rb +133 -0
  97. data/spec/support/shared_examples/adapter.rb +104 -0
  98. data/spec/support/shared_examples/params_encoder.rb +18 -0
  99. data/spec/support/shared_examples/request_method.rb +234 -0
  100. data/spec/support/streaming_response_checker.rb +35 -0
  101. data/spec/support/webmock_rack_app.rb +68 -0
  102. metadata +80 -37
  103. data/lib/faraday/deprecate.rb +0 -101
  104. data/lib/faraday/upload_io.rb +0 -67
  105. data/spec/faraday/deprecate_spec.rb +0 -69
  106. data/test/adapters/default_test.rb +0 -14
  107. data/test/adapters/em_http_test.rb +0 -30
  108. data/test/adapters/em_synchrony_test.rb +0 -32
  109. data/test/adapters/excon_test.rb +0 -30
  110. data/test/adapters/httpclient_test.rb +0 -34
  111. data/test/adapters/integration.rb +0 -263
  112. data/test/adapters/logger_test.rb +0 -136
  113. data/test/adapters/net_http_persistent_test.rb +0 -114
  114. data/test/adapters/net_http_test.rb +0 -79
  115. data/test/adapters/patron_test.rb +0 -40
  116. data/test/adapters/rack_test.rb +0 -38
  117. data/test/adapters/test_middleware_test.rb +0 -157
  118. data/test/adapters/typhoeus_test.rb +0 -38
  119. data/test/authentication_middleware_test.rb +0 -65
  120. data/test/composite_read_io_test.rb +0 -109
  121. data/test/connection_test.rb +0 -738
  122. data/test/env_test.rb +0 -268
  123. data/test/helper.rb +0 -75
  124. data/test/live_server.rb +0 -67
  125. data/test/middleware/instrumentation_test.rb +0 -88
  126. data/test/middleware/retry_test.rb +0 -282
  127. data/test/middleware_stack_test.rb +0 -260
  128. data/test/multibyte.txt +0 -1
  129. data/test/options_test.rb +0 -333
  130. data/test/parameters_test.rb +0 -157
  131. data/test/request_middleware_test.rb +0 -126
  132. data/test/response_middleware_test.rb +0 -72
  133. data/test/strawberry.rb +0 -2
  134. data/test/utils_test.rb +0 -98
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Faraday::Adapter::NetHttp do
4
+ features :request_body_on_query_methods, :reason_phrase_parse, :compression, :streaming, :trace_method
5
+
6
+ it_behaves_like 'an adapter'
7
+
8
+ context 'checking http' do
9
+ let(:url) { URI('http://example.com') }
10
+ let(:adapter) { described_class.new }
11
+ let(:http) { adapter.send(:connection, url: url, request: {}) }
12
+
13
+ it { expect(http.port).to eq(80) }
14
+
15
+ it 'sets max_retries to 0' do
16
+ adapter.send(:configure_request, http, {})
17
+
18
+ expect(http.max_retries).to eq(0) if http.respond_to?(:max_retries=)
19
+ end
20
+
21
+ it 'supports write_timeout' do
22
+ adapter.send(:configure_request, http, write_timeout: 10)
23
+
24
+ expect(http.write_timeout).to eq(10) if http.respond_to?(:write_timeout=)
25
+ end
26
+
27
+ it 'supports open_timeout' do
28
+ adapter.send(:configure_request, http, open_timeout: 10)
29
+
30
+ expect(http.open_timeout).to eq(10)
31
+ end
32
+
33
+ it 'supports read_timeout' do
34
+ adapter.send(:configure_request, http, read_timeout: 10)
35
+
36
+ expect(http.read_timeout).to eq(10)
37
+ end
38
+
39
+ context 'with https url' do
40
+ let(:url) { URI('https://example.com') }
41
+
42
+ it { expect(http.port).to eq(443) }
43
+ end
44
+
45
+ context 'with http url including port' do
46
+ let(:url) { URI('https://example.com:1234') }
47
+
48
+ it { expect(http.port).to eq(1234) }
49
+ end
50
+
51
+ context 'with custom adapter config' do
52
+ let(:adapter) do
53
+ described_class.new do |http|
54
+ http.continue_timeout = 123
55
+ end
56
+ end
57
+
58
+ it do
59
+ adapter.send(:configure_request, http, {})
60
+ expect(http.continue_timeout).to eq(123)
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Faraday::Adapter::Patron, unless: defined?(JRUBY_VERSION) do
4
+ features :reason_phrase_parse
5
+
6
+ it_behaves_like 'an adapter'
7
+
8
+ it 'allows to provide adapter specific configs' do
9
+ conn = Faraday.new do |f|
10
+ f.adapter :patron do |session|
11
+ session.max_redirects = 10
12
+ raise 'Configuration block called'
13
+ end
14
+ end
15
+
16
+ expect { conn.get('/') }.to raise_error(RuntimeError, 'Configuration block called')
17
+ end
18
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Faraday::Adapter::Rack do
4
+ features :request_body_on_query_methods, :trace_method,
5
+ :skip_response_body_on_head
6
+
7
+ it_behaves_like 'an adapter', adapter_options: WebmockRackApp.new
8
+ end
@@ -0,0 +1,260 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Faraday::Adapter::Test do
4
+ let(:stubs) do
5
+ described_class::Stubs.new do |stub|
6
+ stub.get('http://domain.test/hello') do
7
+ [200, { 'Content-Type' => 'text/html' }, 'domain: hello']
8
+ end
9
+
10
+ stub.get('http://wrong.test/hello') do
11
+ [200, { 'Content-Type' => 'text/html' }, 'wrong: hello']
12
+ end
13
+
14
+ stub.get('http://wrong.test/bait') do
15
+ [404, { 'Content-Type' => 'text/html' }]
16
+ end
17
+
18
+ stub.get('/hello') do
19
+ [200, { 'Content-Type' => 'text/html' }, 'hello']
20
+ end
21
+
22
+ stub.get('/method-echo') do |env|
23
+ [200, { 'Content-Type' => 'text/html' }, env[:method].to_s]
24
+ end
25
+
26
+ stub.get(%r{\A/resources/\d+(?:\?|\z)}) do
27
+ [200, { 'Content-Type' => 'text/html' }, 'show']
28
+ end
29
+
30
+ stub.get(%r{\A/resources/(specified)\z}) do |_env, meta|
31
+ [200, { 'Content-Type' => 'text/html' }, "show #{meta[:match_data][1]}"]
32
+ end
33
+ end
34
+ end
35
+
36
+ let(:connection) do
37
+ Faraday.new do |builder|
38
+ builder.adapter :test, stubs
39
+ end
40
+ end
41
+
42
+ let(:response) { connection.get('/hello') }
43
+
44
+ context 'with simple path sets status' do
45
+ subject { response.status }
46
+
47
+ it { is_expected.to eq 200 }
48
+ end
49
+
50
+ context 'with simple path sets headers' do
51
+ subject { response.headers['Content-Type'] }
52
+
53
+ it { is_expected.to eq 'text/html' }
54
+ end
55
+
56
+ context 'with simple path sets body' do
57
+ subject { response.body }
58
+
59
+ it { is_expected.to eq 'hello' }
60
+ end
61
+
62
+ context 'with host points to the right stub' do
63
+ subject { connection.get('http://domain.test/hello').body }
64
+
65
+ it { is_expected.to eq 'domain: hello' }
66
+ end
67
+
68
+ describe 'can be called several times' do
69
+ subject { connection.get('/hello').body }
70
+
71
+ it { is_expected.to eq 'hello' }
72
+ end
73
+
74
+ describe 'can handle regular expression path' do
75
+ subject { connection.get('/resources/1').body }
76
+
77
+ it { is_expected.to eq 'show' }
78
+ end
79
+
80
+ describe 'can handle single parameter block' do
81
+ subject { connection.get('/method-echo').body }
82
+
83
+ it { is_expected.to eq 'get' }
84
+ end
85
+
86
+ describe 'can handle regular expression path with captured result' do
87
+ subject { connection.get('/resources/specified').body }
88
+
89
+ it { is_expected.to eq 'show specified' }
90
+ end
91
+
92
+ context 'with get params' do
93
+ subject { connection.get('/param?a=1').body }
94
+
95
+ before do
96
+ stubs.get('/param?a=1') { [200, {}, 'a'] }
97
+ end
98
+
99
+ it { is_expected.to eq 'a' }
100
+ end
101
+
102
+ describe 'ignoring unspecified get params' do
103
+ before do
104
+ stubs.get('/optional?a=1') { [200, {}, 'a'] }
105
+ end
106
+
107
+ context 'with multiple params' do
108
+ subject { connection.get('/optional?a=1&b=1').body }
109
+
110
+ it { is_expected.to eq 'a' }
111
+ end
112
+
113
+ context 'with single param' do
114
+ subject { connection.get('/optional?a=1').body }
115
+
116
+ it { is_expected.to eq 'a' }
117
+ end
118
+
119
+ context 'without params' do
120
+ subject(:request) { connection.get('/optional') }
121
+
122
+ it do
123
+ expect { request }.to raise_error(
124
+ Faraday::Adapter::Test::Stubs::NotFound
125
+ )
126
+ end
127
+ end
128
+ end
129
+
130
+ context 'with http headers' do
131
+ before do
132
+ stubs.get('/yo', 'X-HELLO' => 'hello') { [200, {}, 'a'] }
133
+ stubs.get('/yo') { [200, {}, 'b'] }
134
+ end
135
+
136
+ context 'with header' do
137
+ subject do
138
+ connection.get('/yo') { |env| env.headers['X-HELLO'] = 'hello' }.body
139
+ end
140
+
141
+ it { is_expected.to eq 'a' }
142
+ end
143
+
144
+ context 'without header' do
145
+ subject do
146
+ connection.get('/yo').body
147
+ end
148
+
149
+ it { is_expected.to eq 'b' }
150
+ end
151
+ end
152
+
153
+ describe 'different outcomes for the same request' do
154
+ def make_request
155
+ connection.get('/foo')
156
+ end
157
+
158
+ subject(:request) { make_request.body }
159
+
160
+ before do
161
+ stubs.get('/foo') { [200, { 'Content-Type' => 'text/html' }, 'hello'] }
162
+ stubs.get('/foo') { [200, { 'Content-Type' => 'text/html' }, 'world'] }
163
+ end
164
+
165
+ context 'the first request' do
166
+ it { is_expected.to eq 'hello' }
167
+ end
168
+
169
+ context 'the second request' do
170
+ before do
171
+ make_request
172
+ end
173
+
174
+ it { is_expected.to eq 'world' }
175
+ end
176
+ end
177
+
178
+ describe 'yielding env to stubs' do
179
+ subject { connection.get('http://foo.com/foo?a=1').body }
180
+
181
+ before do
182
+ stubs.get '/foo' do |env|
183
+ expect(env[:url].path).to eq '/foo'
184
+ expect(env[:url].host).to eq 'foo.com'
185
+ expect(env[:params]['a']).to eq '1'
186
+ expect(env[:request_headers]['Accept']).to eq 'text/plain'
187
+ [200, {}, 'a']
188
+ end
189
+
190
+ connection.headers['Accept'] = 'text/plain'
191
+ end
192
+
193
+ it { is_expected.to eq 'a' }
194
+ end
195
+
196
+ describe 'params parsing' do
197
+ subject { connection.get('http://foo.com/foo?a[b]=1').body }
198
+
199
+ context 'with default encoder' do
200
+ before do
201
+ stubs.get '/foo' do |env|
202
+ expect(env[:params]['a']['b']).to eq '1'
203
+ [200, {}, 'a']
204
+ end
205
+ end
206
+
207
+ it { is_expected.to eq 'a' }
208
+ end
209
+
210
+ context 'with nested encoder' do
211
+ before do
212
+ stubs.get '/foo' do |env|
213
+ expect(env[:params]['a']['b']).to eq '1'
214
+ [200, {}, 'a']
215
+ end
216
+
217
+ connection.options.params_encoder = Faraday::NestedParamsEncoder
218
+ end
219
+
220
+ it { is_expected.to eq 'a' }
221
+ end
222
+
223
+ context 'with flat encoder' do
224
+ before do
225
+ stubs.get '/foo' do |env|
226
+ expect(env[:params]['a[b]']).to eq '1'
227
+ [200, {}, 'a']
228
+ end
229
+
230
+ connection.options.params_encoder = Faraday::FlatParamsEncoder
231
+ end
232
+
233
+ it { is_expected.to eq 'a' }
234
+ end
235
+ end
236
+
237
+ describe 'raising an error if no stub was found' do
238
+ describe 'for request' do
239
+ subject(:request) { connection.get('/invalid') { [200, {}, []] } }
240
+
241
+ it { expect { request }.to raise_error described_class::Stubs::NotFound }
242
+ end
243
+
244
+ describe 'for specified host' do
245
+ subject(:request) { connection.get('http://domain.test/bait') }
246
+
247
+ it { expect { request }.to raise_error described_class::Stubs::NotFound }
248
+ end
249
+
250
+ describe 'for request without specified header' do
251
+ subject(:request) { connection.get('/yo') }
252
+
253
+ before do
254
+ stubs.get('/yo', 'X-HELLO' => 'hello') { [200, {}, 'a'] }
255
+ end
256
+
257
+ it { expect { request }.to raise_error described_class::Stubs::NotFound }
258
+ end
259
+ end
260
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Faraday::Adapter::Typhoeus do
4
+ features :request_body_on_query_methods, :parallel, :trace_method
5
+
6
+ it_behaves_like 'an adapter'
7
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Faraday::AdapterRegistry do
4
+ describe '#initialize' do
5
+ subject(:registry) { described_class.new }
6
+
7
+ it { expect { registry.get(:FinFangFoom) }.to raise_error(NameError) }
8
+ it { expect { registry.get('FinFangFoom') }.to raise_error(NameError) }
9
+
10
+ it 'looks up class by string name' do
11
+ expect(registry.get('Faraday::Connection')).to eq(Faraday::Connection)
12
+ end
13
+
14
+ it 'looks up class by symbol name' do
15
+ expect(registry.get(:Faraday)).to eq(Faraday)
16
+ end
17
+
18
+ it 'caches lookups with implicit name' do
19
+ registry.set :symbol
20
+ expect(registry.get('symbol')).to eq(:symbol)
21
+ end
22
+
23
+ it 'caches lookups with explicit name' do
24
+ registry.set 'string', :name
25
+ expect(registry.get(:name)).to eq('string')
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Faraday::Adapter do
4
+ let(:adapter) { Faraday::Adapter.new }
5
+ let(:request) { {} }
6
+
7
+ context '#request_timeout' do
8
+ it 'gets :read timeout' do
9
+ expect(timeout(:read)).to eq(nil)
10
+
11
+ request[:timeout] = 5
12
+ request[:write_timeout] = 1
13
+
14
+ expect(timeout(:read)).to eq(5)
15
+
16
+ request[:read_timeout] = 2
17
+
18
+ expect(timeout(:read)).to eq(2)
19
+ end
20
+
21
+ it 'gets :open timeout' do
22
+ expect(timeout(:open)).to eq(nil)
23
+
24
+ request[:timeout] = 5
25
+ request[:write_timeout] = 1
26
+
27
+ expect(timeout(:open)).to eq(5)
28
+
29
+ request[:open_timeout] = 2
30
+
31
+ expect(timeout(:open)).to eq(2)
32
+ end
33
+
34
+ it 'gets :write timeout' do
35
+ expect(timeout(:write)).to eq(nil)
36
+
37
+ request[:timeout] = 5
38
+ request[:read_timeout] = 1
39
+
40
+ expect(timeout(:write)).to eq(5)
41
+
42
+ request[:write_timeout] = 2
43
+
44
+ expect(timeout(:write)).to eq(2)
45
+ end
46
+
47
+ it 'attempts unknown timeout type' do
48
+ expect { timeout(:unknown) }.to raise_error(ArgumentError)
49
+ end
50
+
51
+ def timeout(type)
52
+ adapter.send(:request_timeout, type, request)
53
+ end
54
+ end
55
+ end