faraday 2.9.2 → 2.10.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d2795a487e8f0330545b6b9720029b597b0f0f36d33ed47bf3a7ab5ec8e2d583
4
- data.tar.gz: a892c9ceebf1a9b5499ca7c6f20a1f6bb3c8a632bcf953f83af0ac17814c0691
3
+ metadata.gz: 38164352c529ba998b6bf30d524aab2a4ada891fbffd2043148d1d8022ea4948
4
+ data.tar.gz: 2f0ffedf44bd70095af902f953dc3c61a16ee471f392954d5085e6143bc0bdff
5
5
  SHA512:
6
- metadata.gz: dc55e018b7b5cec1d5538194841c74a643182d0bb6bc3a73bf5ca1c3c7c88f84998f8b4f90165bffe22b01422e3d90c7bbf6c035714c563bb09265bd34029169
7
- data.tar.gz: 05c24fe02e969616d069ba3b02fa7fddfb5c70cb504bfd39ca60983d12aaa47207f985c1e5a1a24d29c71c6cecbe899eb2252f4a8f9458d8681e06584d7016fc
6
+ metadata.gz: 6b1f592fa1199f33f688304d02f544655593990f6202ec6ae970064f5f2699b2cf66962b3e26f087edea76c66eca048907358d5d9c9bb809beb405008d0395e8
7
+ data.tar.gz: '081ad3877890fb49a0b3cd3ade3924fd5b482bc1a7624a3d56701096e90bee49c2d2619b6454dfa604a67f81cf0682bbe7acd1eb0f3247bc2790e8a7afded7a5'
data/lib/faraday/error.rb CHANGED
@@ -158,4 +158,8 @@ module Faraday
158
158
  # Raised by middlewares that parse the response, like the JSON response middleware.
159
159
  class ParsingError < Error
160
160
  end
161
+
162
+ # Raised by Faraday::Middleware and subclasses when invalid default_options are used
163
+ class InitializationError < Error
164
+ end
161
165
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'monitor'
4
+
3
5
  module Faraday
4
6
  # Middleware is the basic base class of any Faraday middleware.
5
7
  class Middleware
@@ -7,9 +9,49 @@ module Faraday
7
9
 
8
10
  attr_reader :app, :options
9
11
 
12
+ DEFAULT_OPTIONS = {}.freeze
13
+
10
14
  def initialize(app = nil, options = {})
11
15
  @app = app
12
- @options = options
16
+ @options = self.class.default_options.merge(options)
17
+ end
18
+
19
+ class << self
20
+ # Faraday::Middleware::default_options= allows user to set default options at the Faraday::Middleware
21
+ # class level.
22
+ #
23
+ # @example Set the Faraday::Response::RaiseError option, `include_request` to `false`
24
+ # my_app/config/initializers/my_faraday_middleware.rb
25
+ #
26
+ # Faraday::Response::RaiseError.default_options = { include_request: false }
27
+ #
28
+ def default_options=(options = {})
29
+ validate_default_options(options)
30
+ lock.synchronize do
31
+ @default_options = default_options.merge(options)
32
+ end
33
+ end
34
+
35
+ # default_options attr_reader that initializes class instance variable
36
+ # with the values of any Faraday::Middleware defaults, and merges with
37
+ # subclass defaults
38
+ def default_options
39
+ @default_options ||= DEFAULT_OPTIONS.merge(self::DEFAULT_OPTIONS)
40
+ end
41
+
42
+ private
43
+
44
+ def lock
45
+ @lock ||= Monitor.new
46
+ end
47
+
48
+ def validate_default_options(options)
49
+ invalid_keys = options.keys.reject { |opt| self::DEFAULT_OPTIONS.key?(opt) }
50
+ return unless invalid_keys.any?
51
+
52
+ raise(Faraday::InitializationError,
53
+ "Invalid options provided. Keys not found in #{self}::DEFAULT_OPTIONS: #{invalid_keys.join(', ')}")
54
+ end
13
55
  end
14
56
 
15
57
  def call(env)
@@ -10,6 +10,8 @@ module Faraday
10
10
  ServerErrorStatuses = (500...600)
11
11
  # rubocop:enable Naming/ConstantName
12
12
 
13
+ DEFAULT_OPTIONS = { include_request: true }.freeze
14
+
13
15
  def on_complete(env)
14
16
  case env[:status]
15
17
  when 400
@@ -58,7 +60,7 @@ module Faraday
58
60
 
59
61
  # Include the request data by default. If the middleware was explicitly
60
62
  # configured to _not_ include request data, then omit it.
61
- return response unless options.fetch(:include_request, true)
63
+ return response unless options[:include_request]
62
64
 
63
65
  response.merge(
64
66
  request: {
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Faraday
4
- VERSION = '2.9.2'
4
+ VERSION = '2.10.0'
5
5
  end
@@ -67,4 +67,147 @@ RSpec.describe Faraday::Middleware do
67
67
  end
68
68
  end
69
69
  end
70
+
71
+ describe '::default_options' do
72
+ let(:subclass_no_options) { FaradayMiddlewareSubclasses::SubclassNoOptions }
73
+ let(:subclass_one_option) { FaradayMiddlewareSubclasses::SubclassOneOption }
74
+ let(:subclass_two_options) { FaradayMiddlewareSubclasses::SubclassTwoOptions }
75
+
76
+ def build_conn(resp_middleware)
77
+ Faraday.new do |c|
78
+ c.adapter :test do |stub|
79
+ stub.get('/success') { [200, {}, 'ok'] }
80
+ end
81
+ c.response resp_middleware
82
+ end
83
+ end
84
+
85
+ RSpec.shared_context 'reset @default_options' do
86
+ before(:each) do
87
+ FaradayMiddlewareSubclasses::SubclassNoOptions.instance_variable_set(:@default_options, nil)
88
+ FaradayMiddlewareSubclasses::SubclassOneOption.instance_variable_set(:@default_options, nil)
89
+ FaradayMiddlewareSubclasses::SubclassTwoOptions.instance_variable_set(:@default_options, nil)
90
+ Faraday::Middleware.instance_variable_set(:@default_options, nil)
91
+ end
92
+ end
93
+
94
+ after(:all) do
95
+ FaradayMiddlewareSubclasses::SubclassNoOptions.instance_variable_set(:@default_options, nil)
96
+ FaradayMiddlewareSubclasses::SubclassOneOption.instance_variable_set(:@default_options, nil)
97
+ FaradayMiddlewareSubclasses::SubclassTwoOptions.instance_variable_set(:@default_options, nil)
98
+ Faraday::Middleware.instance_variable_set(:@default_options, nil)
99
+ end
100
+
101
+ context 'with subclass DEFAULT_OPTIONS defined' do
102
+ include_context 'reset @default_options'
103
+
104
+ context 'and without application options configured' do
105
+ let(:resp1) { build_conn(:one_option).get('/success') }
106
+
107
+ it 'has only subclass defaults' do
108
+ expect(Faraday::Middleware.default_options).to eq(Faraday::Middleware::DEFAULT_OPTIONS)
109
+ expect(subclass_no_options.default_options).to eq(subclass_no_options::DEFAULT_OPTIONS)
110
+ expect(subclass_one_option.default_options).to eq(subclass_one_option::DEFAULT_OPTIONS)
111
+ expect(subclass_two_options.default_options).to eq(subclass_two_options::DEFAULT_OPTIONS)
112
+ end
113
+
114
+ it { expect(resp1.body).to eq('ok') }
115
+ end
116
+
117
+ context "and with one application's options changed" do
118
+ let(:resp2) { build_conn(:two_options).get('/success') }
119
+
120
+ before(:each) do
121
+ FaradayMiddlewareSubclasses::SubclassTwoOptions.default_options = { some_option: false }
122
+ end
123
+
124
+ it 'only updates default options of target subclass' do
125
+ expect(Faraday::Middleware.default_options).to eq(Faraday::Middleware::DEFAULT_OPTIONS)
126
+ expect(subclass_no_options.default_options).to eq(subclass_no_options::DEFAULT_OPTIONS)
127
+ expect(subclass_one_option.default_options).to eq(subclass_one_option::DEFAULT_OPTIONS)
128
+ expect(subclass_two_options.default_options).to eq({ some_option: false, some_other_option: false })
129
+ end
130
+
131
+ it { expect(resp2.body).to eq('ok') }
132
+ end
133
+
134
+ context "and with two applications' options changed" do
135
+ let(:resp1) { build_conn(:one_option).get('/success') }
136
+ let(:resp2) { build_conn(:two_options).get('/success') }
137
+
138
+ before(:each) do
139
+ FaradayMiddlewareSubclasses::SubclassOneOption.default_options = { some_other_option: true }
140
+ FaradayMiddlewareSubclasses::SubclassTwoOptions.default_options = { some_option: false }
141
+ end
142
+
143
+ it 'updates subclasses and parent independent of each other' do
144
+ expect(Faraday::Middleware.default_options).to eq(Faraday::Middleware::DEFAULT_OPTIONS)
145
+ expect(subclass_no_options.default_options).to eq(subclass_no_options::DEFAULT_OPTIONS)
146
+ expect(subclass_one_option.default_options).to eq({ some_other_option: true })
147
+ expect(subclass_two_options.default_options).to eq({ some_option: false, some_other_option: false })
148
+ end
149
+
150
+ it { expect(resp1.body).to eq('ok') }
151
+ it { expect(resp2.body).to eq('ok') }
152
+ end
153
+ end
154
+
155
+ context 'with FARADAY::MIDDLEWARE DEFAULT_OPTIONS and with Subclass DEFAULT_OPTIONS' do
156
+ before(:each) do
157
+ stub_const('Faraday::Middleware::DEFAULT_OPTIONS', { its_magic: false })
158
+ end
159
+
160
+ # Must stub Faraday::Middleware::DEFAULT_OPTIONS before resetting default options
161
+ include_context 'reset @default_options'
162
+
163
+ context 'and without application options configured' do
164
+ let(:resp1) { build_conn(:one_option).get('/success') }
165
+
166
+ it 'has only subclass defaults' do
167
+ expect(Faraday::Middleware.default_options).to eq(Faraday::Middleware::DEFAULT_OPTIONS)
168
+ expect(FaradayMiddlewareSubclasses::SubclassNoOptions.default_options).to eq({ its_magic: false })
169
+ expect(FaradayMiddlewareSubclasses::SubclassOneOption.default_options).to eq({ its_magic: false, some_other_option: false })
170
+ expect(FaradayMiddlewareSubclasses::SubclassTwoOptions.default_options).to eq({ its_magic: false, some_option: true, some_other_option: false })
171
+ end
172
+
173
+ it { expect(resp1.body).to eq('ok') }
174
+ end
175
+
176
+ context "and with two applications' options changed" do
177
+ let(:resp1) { build_conn(:one_option).get('/success') }
178
+ let(:resp2) { build_conn(:two_options).get('/success') }
179
+
180
+ before(:each) do
181
+ FaradayMiddlewareSubclasses::SubclassOneOption.default_options = { some_other_option: true }
182
+ FaradayMiddlewareSubclasses::SubclassTwoOptions.default_options = { some_option: false }
183
+ end
184
+
185
+ it 'updates subclasses and parent independent of each other' do
186
+ expect(Faraday::Middleware.default_options).to eq(Faraday::Middleware::DEFAULT_OPTIONS)
187
+ expect(FaradayMiddlewareSubclasses::SubclassNoOptions.default_options).to eq({ its_magic: false })
188
+ expect(FaradayMiddlewareSubclasses::SubclassOneOption.default_options).to eq({ its_magic: false, some_other_option: true })
189
+ expect(FaradayMiddlewareSubclasses::SubclassTwoOptions.default_options).to eq({ its_magic: false, some_option: false, some_other_option: false })
190
+ end
191
+
192
+ it { expect(resp1.body).to eq('ok') }
193
+ it { expect(resp2.body).to eq('ok') }
194
+ end
195
+ end
196
+
197
+ describe 'default_options input validation' do
198
+ include_context 'reset @default_options'
199
+
200
+ it 'raises error if Faraday::Middleware option does not exist' do
201
+ expect { Faraday::Middleware.default_options = { something_special: true } }.to raise_error(Faraday::InitializationError) do |e|
202
+ expect(e.message).to eq('Invalid options provided. Keys not found in Faraday::Middleware::DEFAULT_OPTIONS: something_special')
203
+ end
204
+ end
205
+
206
+ it 'raises error if subclass option does not exist' do
207
+ expect { subclass_one_option.default_options = { this_is_a_typo: true } }.to raise_error(Faraday::InitializationError) do |e|
208
+ expect(e.message).to eq('Invalid options provided. Keys not found in FaradayMiddlewareSubclasses::SubclassOneOption::DEFAULT_OPTIONS: this_is_a_typo')
209
+ end
210
+ end
211
+ end
212
+ end
70
213
  end
@@ -194,16 +194,60 @@ RSpec.describe Faraday::Response::RaiseError do
194
194
  end
195
195
  end
196
196
 
197
- context 'when the include_request option is set to false' do
198
- let(:middleware_options) { { include_request: false } }
199
-
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
- )
197
+ describe 'DEFAULT_OPTION: include_request' do
198
+ before(:each) do
199
+ Faraday::Response::RaiseError.instance_variable_set(:@default_options, nil)
200
+ Faraday::Middleware.instance_variable_set(:@default_options, nil)
201
+ end
202
+
203
+ after(:all) do
204
+ Faraday::Response::RaiseError.instance_variable_set(:@default_options, nil)
205
+ Faraday::Middleware.instance_variable_set(:@default_options, nil)
206
+ end
207
+
208
+ context 'when RaiseError DEFAULT_OPTION (include_request: true) is used' do
209
+ it 'includes request info in the exception' do
210
+ expect { perform_request }.to raise_error(Faraday::BadRequestError) do |ex|
211
+ expect(ex.response.keys).to contain_exactly(
212
+ :status,
213
+ :headers,
214
+ :body,
215
+ :request
216
+ )
217
+ end
218
+ end
219
+ end
220
+
221
+ context 'when application sets default_options `include_request: false`' do
222
+ before(:each) do
223
+ Faraday::Response::RaiseError.default_options = { include_request: false }
224
+ end
225
+
226
+ context 'and when include_request option is omitted' do
227
+ it 'does not include request info in the exception' do
228
+ expect { perform_request }.to raise_error(Faraday::BadRequestError) do |ex|
229
+ expect(ex.response.keys).to contain_exactly(
230
+ :status,
231
+ :headers,
232
+ :body
233
+ )
234
+ end
235
+ end
236
+ end
237
+
238
+ context 'and when include_request option is explicitly set for instance' do
239
+ let(:middleware_options) { { include_request: true } }
240
+
241
+ it 'includes request info in the exception' do
242
+ expect { perform_request }.to raise_error(Faraday::BadRequestError) do |ex|
243
+ expect(ex.response.keys).to contain_exactly(
244
+ :status,
245
+ :headers,
246
+ :body,
247
+ :request
248
+ )
249
+ end
250
+ end
207
251
  end
208
252
  end
209
253
  end
@@ -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,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: faraday
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.9.2
4
+ version: 2.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - "@technoweenie"
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2024-06-18 00:00:00.000000000 Z
13
+ date: 2024-07-08 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: faraday-net_http
@@ -32,6 +32,20 @@ dependencies:
32
32
  - - "<"
33
33
  - !ruby/object:Gem::Version
34
34
  version: '3.2'
35
+ - !ruby/object:Gem::Dependency
36
+ name: logger
37
+ requirement: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ type: :runtime
43
+ prerelease: false
44
+ version_requirements: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
35
49
  description:
36
50
  email: technoweenie@gmail.com
37
51
  executables: []
@@ -107,6 +121,7 @@ files:
107
121
  - spec/spec_helper.rb
108
122
  - spec/support/disabling_stub.rb
109
123
  - spec/support/fake_safe_buffer.rb
124
+ - spec/support/faraday_middleware_subclasses.rb
110
125
  - spec/support/helper_methods.rb
111
126
  - spec/support/shared_examples/adapter.rb
112
127
  - spec/support/shared_examples/params_encoder.rb
@@ -117,7 +132,7 @@ licenses:
117
132
  - MIT
118
133
  metadata:
119
134
  homepage_uri: https://lostisland.github.io/faraday
120
- changelog_uri: https://github.com/lostisland/faraday/releases/tag/v2.9.2
135
+ changelog_uri: https://github.com/lostisland/faraday/releases/tag/v2.10.0
121
136
  source_code_uri: https://github.com/lostisland/faraday
122
137
  bug_tracker_uri: https://github.com/lostisland/faraday/issues
123
138
  post_install_message: