faraday 2.8.1 → 2.14.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 (39) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1 -1
  3. data/README.md +1 -1
  4. data/Rakefile +3 -0
  5. data/lib/faraday/adapter.rb +1 -1
  6. data/lib/faraday/connection.rb +16 -7
  7. data/lib/faraday/encoders/flat_params_encoder.rb +2 -2
  8. data/lib/faraday/encoders/nested_params_encoder.rb +1 -1
  9. data/lib/faraday/error.rb +46 -5
  10. data/lib/faraday/logging/formatter.rb +7 -7
  11. data/lib/faraday/middleware.rb +40 -1
  12. data/lib/faraday/options/env.rb +2 -2
  13. data/lib/faraday/options/proxy_options.rb +4 -2
  14. data/lib/faraday/options/ssl_options.rb +8 -2
  15. data/lib/faraday/rack_builder.rb +21 -25
  16. data/lib/faraday/request/json.rb +1 -1
  17. data/lib/faraday/response/json.rb +2 -1
  18. data/lib/faraday/response/logger.rb +5 -3
  19. data/lib/faraday/response/raise_error.rb +19 -19
  20. data/lib/faraday/response.rb +7 -3
  21. data/lib/faraday/utils/headers.rb +8 -2
  22. data/lib/faraday/utils.rb +3 -4
  23. data/lib/faraday/version.rb +1 -1
  24. data/lib/faraday.rb +2 -1
  25. data/spec/faraday/connection_spec.rb +2 -2
  26. data/spec/faraday/error_spec.rb +93 -3
  27. data/spec/faraday/middleware_spec.rb +143 -0
  28. data/spec/faraday/options/proxy_options_spec.rb +27 -0
  29. data/spec/faraday/params_encoders/nested_spec.rb +2 -1
  30. data/spec/faraday/response/json_spec.rb +17 -0
  31. data/spec/faraday/response/logger_spec.rb +45 -4
  32. data/spec/faraday/response/raise_error_spec.rb +97 -22
  33. data/spec/faraday/response_spec.rb +7 -0
  34. data/spec/faraday/utils/headers_spec.rb +9 -0
  35. data/spec/faraday/utils_spec.rb +3 -1
  36. data/spec/faraday_spec.rb +3 -1
  37. data/spec/spec_helper.rb +6 -5
  38. data/spec/support/faraday_middleware_subclasses.rb +18 -0
  39. metadata +22 -24
@@ -13,7 +13,7 @@ RSpec.describe Faraday::Response::RaiseError do
13
13
  stub.get('proxy-error') { [407, { 'X-Reason' => 'because' }, 'keep looking'] }
14
14
  stub.get('request-timeout') { [408, { 'X-Reason' => 'because' }, 'keep looking'] }
15
15
  stub.get('conflict') { [409, { 'X-Reason' => 'because' }, 'keep looking'] }
16
- stub.get('unprocessable-entity') { [422, { 'X-Reason' => 'because' }, 'keep looking'] }
16
+ stub.get('unprocessable-content') { [422, { 'X-Reason' => 'because' }, 'keep looking'] }
17
17
  stub.get('too-many-requests') { [429, { 'X-Reason' => 'because' }, 'keep looking'] }
18
18
  stub.get('4xx') { [499, { 'X-Reason' => 'because' }, 'keep looking'] }
19
19
  stub.get('nil-status') { [nil, { 'X-Reason' => 'nil' }, 'fail'] }
@@ -28,7 +28,7 @@ RSpec.describe Faraday::Response::RaiseError do
28
28
 
29
29
  it 'raises Faraday::BadRequestError for 400 responses' do
30
30
  expect { conn.get('bad-request') }.to raise_error(Faraday::BadRequestError) do |ex|
31
- expect(ex.message).to eq('the server responded with status 400')
31
+ expect(ex.message).to eq('the server responded with status 400 for GET http:/bad-request')
32
32
  expect(ex.response[:headers]['X-Reason']).to eq('because')
33
33
  expect(ex.response[:status]).to eq(400)
34
34
  expect(ex.response_status).to eq(400)
@@ -39,7 +39,7 @@ RSpec.describe Faraday::Response::RaiseError do
39
39
 
40
40
  it 'raises Faraday::UnauthorizedError for 401 responses' do
41
41
  expect { conn.get('unauthorized') }.to raise_error(Faraday::UnauthorizedError) do |ex|
42
- expect(ex.message).to eq('the server responded with status 401')
42
+ expect(ex.message).to eq('the server responded with status 401 for GET http:/unauthorized')
43
43
  expect(ex.response[:headers]['X-Reason']).to eq('because')
44
44
  expect(ex.response[:status]).to eq(401)
45
45
  expect(ex.response_status).to eq(401)
@@ -50,7 +50,7 @@ RSpec.describe Faraday::Response::RaiseError do
50
50
 
51
51
  it 'raises Faraday::ForbiddenError for 403 responses' do
52
52
  expect { conn.get('forbidden') }.to raise_error(Faraday::ForbiddenError) do |ex|
53
- expect(ex.message).to eq('the server responded with status 403')
53
+ expect(ex.message).to eq('the server responded with status 403 for GET http:/forbidden')
54
54
  expect(ex.response[:headers]['X-Reason']).to eq('because')
55
55
  expect(ex.response[:status]).to eq(403)
56
56
  expect(ex.response_status).to eq(403)
@@ -61,7 +61,7 @@ RSpec.describe Faraday::Response::RaiseError do
61
61
 
62
62
  it 'raises Faraday::ResourceNotFound for 404 responses' do
63
63
  expect { conn.get('not-found') }.to raise_error(Faraday::ResourceNotFound) do |ex|
64
- expect(ex.message).to eq('the server responded with status 404')
64
+ expect(ex.message).to eq('the server responded with status 404 for GET http:/not-found')
65
65
  expect(ex.response[:headers]['X-Reason']).to eq('because')
66
66
  expect(ex.response[:status]).to eq(404)
67
67
  expect(ex.response_status).to eq(404)
@@ -83,7 +83,7 @@ RSpec.describe Faraday::Response::RaiseError do
83
83
 
84
84
  it 'raises Faraday::RequestTimeoutError for 408 responses' do
85
85
  expect { conn.get('request-timeout') }.to raise_error(Faraday::RequestTimeoutError) do |ex|
86
- expect(ex.message).to eq('the server responded with status 408')
86
+ expect(ex.message).to eq('the server responded with status 408 for GET http:/request-timeout')
87
87
  expect(ex.response[:headers]['X-Reason']).to eq('because')
88
88
  expect(ex.response[:status]).to eq(408)
89
89
  expect(ex.response_status).to eq(408)
@@ -94,7 +94,7 @@ RSpec.describe Faraday::Response::RaiseError do
94
94
 
95
95
  it 'raises Faraday::ConflictError for 409 responses' do
96
96
  expect { conn.get('conflict') }.to raise_error(Faraday::ConflictError) do |ex|
97
- expect(ex.message).to eq('the server responded with status 409')
97
+ expect(ex.message).to eq('the server responded with status 409 for GET http:/conflict')
98
98
  expect(ex.response[:headers]['X-Reason']).to eq('because')
99
99
  expect(ex.response[:status]).to eq(409)
100
100
  expect(ex.response_status).to eq(409)
@@ -103,9 +103,20 @@ RSpec.describe Faraday::Response::RaiseError do
103
103
  end
104
104
  end
105
105
 
106
- it 'raises Faraday::UnprocessableEntityError for 422 responses' do
107
- expect { conn.get('unprocessable-entity') }.to raise_error(Faraday::UnprocessableEntityError) do |ex|
108
- expect(ex.message).to eq('the server responded with status 422')
106
+ it 'raises legacy Faraday::UnprocessableEntityError for 422 responses' do
107
+ expect { conn.get('unprocessable-content') }.to raise_error(Faraday::UnprocessableEntityError) do |ex|
108
+ expect(ex.message).to eq('the server responded with status 422 for GET http:/unprocessable-content')
109
+ expect(ex.response[:headers]['X-Reason']).to eq('because')
110
+ expect(ex.response[:status]).to eq(422)
111
+ expect(ex.response_status).to eq(422)
112
+ expect(ex.response_body).to eq('keep looking')
113
+ expect(ex.response_headers['X-Reason']).to eq('because')
114
+ end
115
+ end
116
+
117
+ it 'raises Faraday::UnprocessableContentError for 422 responses' do
118
+ expect { conn.get('unprocessable-content') }.to raise_error(Faraday::UnprocessableContentError) do |ex|
119
+ expect(ex.message).to eq('the server responded with status 422 for GET http:/unprocessable-content')
109
120
  expect(ex.response[:headers]['X-Reason']).to eq('because')
110
121
  expect(ex.response[:status]).to eq(422)
111
122
  expect(ex.response_status).to eq(422)
@@ -116,7 +127,7 @@ RSpec.describe Faraday::Response::RaiseError do
116
127
 
117
128
  it 'raises Faraday::TooManyRequestsError for 429 responses' do
118
129
  expect { conn.get('too-many-requests') }.to raise_error(Faraday::TooManyRequestsError) do |ex|
119
- expect(ex.message).to eq('the server responded with status 429')
130
+ expect(ex.message).to eq('the server responded with status 429 for GET http:/too-many-requests')
120
131
  expect(ex.response[:headers]['X-Reason']).to eq('because')
121
132
  expect(ex.response[:status]).to eq(429)
122
133
  expect(ex.response_status).to eq(429)
@@ -138,7 +149,7 @@ RSpec.describe Faraday::Response::RaiseError do
138
149
 
139
150
  it 'raises Faraday::ClientError for other 4xx responses' do
140
151
  expect { conn.get('4xx') }.to raise_error(Faraday::ClientError) do |ex|
141
- expect(ex.message).to eq('the server responded with status 499')
152
+ expect(ex.message).to eq('the server responded with status 499 for GET http:/4xx')
142
153
  expect(ex.response[:headers]['X-Reason']).to eq('because')
143
154
  expect(ex.response[:status]).to eq(499)
144
155
  expect(ex.response_status).to eq(499)
@@ -149,7 +160,7 @@ RSpec.describe Faraday::Response::RaiseError do
149
160
 
150
161
  it 'raises Faraday::ServerError for 500 responses' do
151
162
  expect { conn.get('server-error') }.to raise_error(Faraday::ServerError) do |ex|
152
- expect(ex.message).to eq('the server responded with status 500')
163
+ expect(ex.message).to eq('the server responded with status 500 for GET http:/server-error')
153
164
  expect(ex.response[:headers]['X-Error']).to eq('bailout')
154
165
  expect(ex.response[:status]).to eq(500)
155
166
  expect(ex.response_status).to eq(500)
@@ -194,18 +205,82 @@ RSpec.describe Faraday::Response::RaiseError do
194
205
  end
195
206
  end
196
207
 
197
- context 'when the include_request option is set to false' do
198
- let(:middleware_options) { { include_request: false } }
208
+ describe 'DEFAULT_OPTION: include_request' do
209
+ before(:each) do
210
+ Faraday::Response::RaiseError.instance_variable_set(:@default_options, nil)
211
+ Faraday::Middleware.instance_variable_set(:@default_options, nil)
212
+ end
213
+
214
+ after(:all) do
215
+ Faraday::Response::RaiseError.instance_variable_set(:@default_options, nil)
216
+ Faraday::Middleware.instance_variable_set(:@default_options, nil)
217
+ end
218
+
219
+ context 'when RaiseError DEFAULT_OPTION (include_request: true) is used' do
220
+ it 'includes request info in the exception' do
221
+ expect { perform_request }.to raise_error(Faraday::BadRequestError) do |ex|
222
+ expect(ex.response.keys).to contain_exactly(
223
+ :status,
224
+ :headers,
225
+ :body,
226
+ :request
227
+ )
228
+ end
229
+ end
230
+ end
231
+
232
+ context 'when application sets default_options `include_request: false`' do
233
+ before(:each) do
234
+ Faraday::Response::RaiseError.default_options = { include_request: false }
235
+ end
236
+
237
+ context 'and when include_request option is omitted' do
238
+ it 'does not include request info in the exception' do
239
+ expect { perform_request }.to raise_error(Faraday::BadRequestError) do |ex|
240
+ expect(ex.response.keys).to contain_exactly(
241
+ :status,
242
+ :headers,
243
+ :body
244
+ )
245
+ end
246
+ end
247
+ end
199
248
 
200
- it 'does not include request info in the exception' do
201
- expect { perform_request }.to raise_error(Faraday::BadRequestError) do |ex|
202
- expect(ex.response.keys).to contain_exactly(
203
- :status,
204
- :headers,
205
- :body
206
- )
249
+ context 'and when include_request option is explicitly set for instance' do
250
+ let(:middleware_options) { { include_request: true } }
251
+
252
+ it 'includes request info in the exception' do
253
+ expect { perform_request }.to raise_error(Faraday::BadRequestError) do |ex|
254
+ expect(ex.response.keys).to contain_exactly(
255
+ :status,
256
+ :headers,
257
+ :body,
258
+ :request
259
+ )
260
+ end
261
+ end
207
262
  end
208
263
  end
209
264
  end
210
265
  end
266
+
267
+ describe 'allowing certain status codes' do
268
+ let(:conn) do
269
+ Faraday.new do |b|
270
+ b.response :raise_error, allowed_statuses: [404]
271
+ b.adapter :test do |stub|
272
+ stub.get('bad-request') { [400, { 'X-Reason' => 'because' }, 'keep looking'] }
273
+ stub.get('not-found') { [404, { 'X-Reason' => 'because' }, 'keep looking'] }
274
+ end
275
+ end
276
+ end
277
+
278
+ it 'raises an error for status codes that are not explicitly allowed' do
279
+ expect { conn.get('bad-request') }.to raise_error(Faraday::BadRequestError)
280
+ end
281
+
282
+ it 'does not raise an error for allowed status codes' do
283
+ expect { conn.get('not-found') }.not_to raise_error
284
+ end
285
+ end
211
286
  end
@@ -13,6 +13,7 @@ RSpec.describe Faraday::Response do
13
13
  it { expect(subject.success?).to be_falsey }
14
14
  it { expect(subject.status).to eq(404) }
15
15
  it { expect(subject.body).to eq('yikes') }
16
+ it { expect(subject.url).to eq(URI('https://lostisland.github.io/faraday')) }
16
17
  it { expect(subject.headers['Content-Type']).to eq('text/plain') }
17
18
  it { expect(subject['content-type']).to eq('text/plain') }
18
19
 
@@ -31,6 +32,12 @@ RSpec.describe Faraday::Response do
31
32
  it { expect(hash[:response_headers]).to eq(subject.headers) }
32
33
  it { expect(hash[:body]).to eq(subject.body) }
33
34
  it { expect(hash[:url]).to eq(subject.env.url) }
35
+
36
+ context 'when response is not finished' do
37
+ subject { Faraday::Response.new.to_hash }
38
+
39
+ it { is_expected.to eq({ status: nil, body: nil, response_headers: {}, url: nil }) }
40
+ end
34
41
  end
35
42
 
36
43
  describe 'marshal serialization support' do
@@ -56,6 +56,15 @@ RSpec.describe Faraday::Utils::Headers do
56
56
  it { expect(subject.delete('content-type')).to be_nil }
57
57
  end
58
58
 
59
+ describe '#dig' do
60
+ before { subject['Content-Type'] = 'application/json' }
61
+
62
+ it { expect(subject&.dig('Content-Type')).to eq('application/json') }
63
+ it { expect(subject&.dig('CONTENT-TYPE')).to eq('application/json') }
64
+ it { expect(subject&.dig(:content_type)).to eq('application/json') }
65
+ it { expect(subject&.dig('invalid')).to be_nil }
66
+ end
67
+
59
68
  describe '#parse' do
60
69
  context 'when response headers leave http status line out' do
61
70
  let(:headers) { "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n" }
@@ -103,7 +103,9 @@ RSpec.describe Faraday::Utils do
103
103
  version: '2',
104
104
  min_version: nil,
105
105
  max_version: nil,
106
- verify_hostname: nil
106
+ verify_hostname: nil,
107
+ hostname: nil,
108
+ ciphers: nil
107
109
  }
108
110
  end
109
111
 
data/spec/faraday_spec.rb CHANGED
@@ -19,7 +19,9 @@ RSpec.describe Faraday do
19
19
 
20
20
  it 'uses method_missing on Faraday if there is no proxyable method' do
21
21
  expected_message =
22
- if RUBY_VERSION >= '3.3'
22
+ if RUBY_VERSION >= '3.4'
23
+ "undefined method 'this_method_does_not_exist' for module Faraday"
24
+ elsif RUBY_VERSION >= '3.3'
23
25
  "undefined method `this_method_does_not_exist' for module Faraday"
24
26
  else
25
27
  "undefined method `this_method_does_not_exist' for Faraday:Module"
data/spec/spec_helper.rb CHANGED
@@ -29,14 +29,15 @@ SimpleCov.start do
29
29
  minimum_coverage_by_file 26
30
30
  end
31
31
 
32
- # Ensure all /lib files are loaded
33
- # so they will be included in the test coverage report.
34
- Dir['./lib/**/*.rb'].sort.each { |file| require file }
35
-
36
32
  require 'faraday'
37
33
  require 'pry'
38
34
 
39
- Dir['./spec/support/**/*.rb'].sort.each { |f| require f }
35
+ # Ensure all /lib files are loaded
36
+ # so they will be included in the test coverage report.
37
+ Dir['./lib/**/*.rb'].each { |file| require file }
38
+
39
+ # Load all Rspec support files
40
+ Dir['./spec/support/**/*.rb'].each { |file| require file }
40
41
 
41
42
  RSpec.configure do |config|
42
43
  # rspec-expectations config goes here. You can use an alternate
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FaradayMiddlewareSubclasses
4
+ class SubclassNoOptions < Faraday::Middleware
5
+ end
6
+
7
+ class SubclassOneOption < Faraday::Middleware
8
+ DEFAULT_OPTIONS = { some_other_option: false }.freeze
9
+ end
10
+
11
+ class SubclassTwoOptions < Faraday::Middleware
12
+ DEFAULT_OPTIONS = { some_option: true, some_other_option: false }.freeze
13
+ end
14
+ end
15
+
16
+ Faraday::Response.register_middleware(no_options: FaradayMiddlewareSubclasses::SubclassNoOptions)
17
+ Faraday::Response.register_middleware(one_option: FaradayMiddlewareSubclasses::SubclassOneOption)
18
+ Faraday::Response.register_middleware(two_options: FaradayMiddlewareSubclasses::SubclassTwoOptions)
metadata CHANGED
@@ -1,66 +1,64 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: faraday
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.8.1
4
+ version: 2.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - "@technoweenie"
8
8
  - "@iMacTia"
9
9
  - "@olleolleolle"
10
- autorequire:
11
10
  bindir: bin
12
11
  cert_chain: []
13
- date: 2023-12-21 00:00:00.000000000 Z
12
+ date: 1980-01-02 00:00:00.000000000 Z
14
13
  dependencies:
15
14
  - !ruby/object:Gem::Dependency
16
- name: base64
15
+ name: faraday-net_http
17
16
  requirement: !ruby/object:Gem::Requirement
18
17
  requirements:
19
18
  - - ">="
20
19
  - !ruby/object:Gem::Version
21
- version: '0'
20
+ version: '2.0'
21
+ - - "<"
22
+ - !ruby/object:Gem::Version
23
+ version: '3.5'
22
24
  type: :runtime
23
25
  prerelease: false
24
26
  version_requirements: !ruby/object:Gem::Requirement
25
27
  requirements:
26
28
  - - ">="
27
29
  - !ruby/object:Gem::Version
28
- version: '0'
30
+ version: '2.0'
31
+ - - "<"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.5'
29
34
  - !ruby/object:Gem::Dependency
30
- name: faraday-net_http
35
+ name: json
31
36
  requirement: !ruby/object:Gem::Requirement
32
37
  requirements:
33
38
  - - ">="
34
39
  - !ruby/object:Gem::Version
35
- version: '2.0'
36
- - - "<"
37
- - !ruby/object:Gem::Version
38
- version: '3.1'
40
+ version: '0'
39
41
  type: :runtime
40
42
  prerelease: false
41
43
  version_requirements: !ruby/object:Gem::Requirement
42
44
  requirements:
43
45
  - - ">="
44
46
  - !ruby/object:Gem::Version
45
- version: '2.0'
46
- - - "<"
47
- - !ruby/object:Gem::Version
48
- version: '3.1'
47
+ version: '0'
49
48
  - !ruby/object:Gem::Dependency
50
- name: ruby2_keywords
49
+ name: logger
51
50
  requirement: !ruby/object:Gem::Requirement
52
51
  requirements:
53
52
  - - ">="
54
53
  - !ruby/object:Gem::Version
55
- version: 0.0.4
54
+ version: '0'
56
55
  type: :runtime
57
56
  prerelease: false
58
57
  version_requirements: !ruby/object:Gem::Requirement
59
58
  requirements:
60
59
  - - ">="
61
60
  - !ruby/object:Gem::Version
62
- version: 0.0.4
63
- description:
61
+ version: '0'
64
62
  email: technoweenie@gmail.com
65
63
  executables: []
66
64
  extensions: []
@@ -135,6 +133,7 @@ files:
135
133
  - spec/spec_helper.rb
136
134
  - spec/support/disabling_stub.rb
137
135
  - spec/support/fake_safe_buffer.rb
136
+ - spec/support/faraday_middleware_subclasses.rb
138
137
  - spec/support/helper_methods.rb
139
138
  - spec/support/shared_examples/adapter.rb
140
139
  - spec/support/shared_examples/params_encoder.rb
@@ -145,10 +144,10 @@ licenses:
145
144
  - MIT
146
145
  metadata:
147
146
  homepage_uri: https://lostisland.github.io/faraday
148
- changelog_uri: https://github.com/lostisland/faraday/releases/tag/v2.8.1
147
+ changelog_uri: https://github.com/lostisland/faraday/releases/tag/v2.14.0
149
148
  source_code_uri: https://github.com/lostisland/faraday
150
149
  bug_tracker_uri: https://github.com/lostisland/faraday/issues
151
- post_install_message:
150
+ rubygems_mfa_required: 'true'
152
151
  rdoc_options: []
153
152
  require_paths:
154
153
  - lib
@@ -157,15 +156,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
157
156
  requirements:
158
157
  - - ">="
159
158
  - !ruby/object:Gem::Version
160
- version: '2.6'
159
+ version: '3.0'
161
160
  required_rubygems_version: !ruby/object:Gem::Requirement
162
161
  requirements:
163
162
  - - ">="
164
163
  - !ruby/object:Gem::Version
165
164
  version: '0'
166
165
  requirements: []
167
- rubygems_version: 3.1.6
168
- signing_key:
166
+ rubygems_version: 3.6.9
169
167
  specification_version: 4
170
168
  summary: HTTP/REST API client library.
171
169
  test_files: []