faraday 2.0.0 → 2.7.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 +81 -3
  3. data/LICENSE.md +1 -1
  4. data/README.md +1 -6
  5. data/examples/client_spec.rb +40 -18
  6. data/examples/client_test.rb +47 -21
  7. data/lib/faraday/adapter/test.rb +41 -7
  8. data/lib/faraday/adapter.rb +2 -2
  9. data/lib/faraday/connection.rb +34 -34
  10. data/lib/faraday/encoders/nested_params_encoder.rb +11 -4
  11. data/lib/faraday/logging/formatter.rb +17 -3
  12. data/lib/faraday/middleware.rb +3 -0
  13. data/lib/faraday/middleware_registry.rb +19 -1
  14. data/lib/faraday/options/env.rb +18 -0
  15. data/lib/faraday/options/ssl_options.rb +11 -1
  16. data/lib/faraday/rack_builder.rb +2 -2
  17. data/lib/faraday/request/authorization.rb +8 -3
  18. data/lib/faraday/request/url_encoded.rb +3 -1
  19. data/lib/faraday/request.rb +1 -1
  20. data/lib/faraday/response/logger.rb +4 -0
  21. data/lib/faraday/utils/headers.rb +6 -1
  22. data/lib/faraday/version.rb +1 -1
  23. data/lib/faraday.rb +8 -2
  24. data/spec/faraday/adapter/test_spec.rb +36 -0
  25. data/spec/faraday/connection_spec.rb +48 -42
  26. data/spec/faraday/middleware_registry_spec.rb +31 -0
  27. data/spec/faraday/middleware_spec.rb +18 -0
  28. data/spec/faraday/options/env_spec.rb +6 -0
  29. data/spec/faraday/params_encoders/nested_spec.rb +8 -0
  30. data/spec/faraday/rack_builder_spec.rb +27 -12
  31. data/spec/faraday/request/authorization_spec.rb +35 -0
  32. data/spec/faraday/request/url_encoded_spec.rb +12 -1
  33. data/spec/faraday/request_spec.rb +5 -4
  34. data/spec/faraday/response/logger_spec.rb +28 -0
  35. data/spec/faraday/utils/headers_spec.rb +22 -4
  36. data/spec/faraday/utils_spec.rb +2 -1
  37. data/spec/support/shared_examples/adapter.rb +2 -1
  38. data/spec/support/shared_examples/request_method.rb +17 -3
  39. metadata +24 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 367d509be94da297eac6ece76f5561772218a5982696eba047ef8599d0ff05e1
4
- data.tar.gz: 779c66227b778b17661428c17ab65567e23f13ea2824b92251eba67cd32c6280
3
+ metadata.gz: aded1d146b09e5b537b81833177fcd70acbed297598160e1114807fe047c15c2
4
+ data.tar.gz: 3b4c82d7712d3667767da96b87050d0cdb76bc0d0d2ed3f67d7f7ccb595f474e
5
5
  SHA512:
6
- metadata.gz: 73d405ce87ac4a0917806b16ab11693b68966334656689a95bc06764501c44965832b08fa7bf36beeb71c2144a6661775df4f22b18e8281f664a0605fc2ece49
7
- data.tar.gz: 22701db3eb1bb1668aaf6429e711acad05099577b39ccc792d32c42a82043f628483973a993c5ce91acd4207a9f0a01f47a51d6bffc4212047e4150fbb63e1e1
6
+ metadata.gz: 6e37eda4374f7c99ea8e687a6c704fcc74935800c4209c5b94767737e2133dc343dcfaa49deda11ddd312fe6f8e8b661a765134b402d3aa787672ffc84026547
7
+ data.tar.gz: 8ce5708af5954af94fdb2c1aff6a4cefcf7ed512d2f91d05c7ac3cdfc72fcad2840e9674c5defb8aaed570e5c9e5f2324911fb22e4b05184b2597a87959f2853
data/CHANGELOG.md CHANGED
@@ -1,5 +1,83 @@
1
1
  # Faraday Changelog
2
2
 
3
+ ## The changelog has moved!
4
+
5
+ This file is not being updated anymore. Instead, please check the [Releases](https://github.com/lostisland/faraday/releases) page.
6
+
7
+ ## [2.2.0](https://github.com/lostisland/faraday/compare/v2.1.0...v2.2.0) (2022-02-03)
8
+
9
+ * Reintroduce the possibility to register middleware with symbols, strings or procs in [#1391](https://github.com/lostisland/faraday/pull/1391)
10
+
11
+ ## [2.1.0](https://github.com/lostisland/faraday/compare/v2.0.1...v2.1.0) (2022-01-15)
12
+
13
+ * Fix test adapter thread safety by @iMacTia in [#1380](https://github.com/lostisland/faraday/pull/1380)
14
+ * Add default adapter options by @hirasawayuki in [#1382](https://github.com/lostisland/faraday/pull/1382)
15
+ * CI: Add Ruby 3.1 to matrix by @petergoldstein in [#1374](https://github.com/lostisland/faraday/pull/1374)
16
+ * docs: fix regex pattern in logger.md examples by @hirasawayuki in [#1378](https://github.com/lostisland/faraday/pull/1378)
17
+
18
+ ## [2.0.1](https://github.com/lostisland/faraday/compare/v2.0.0...v2.0.1) (2022-01-05)
19
+
20
+ * Re-add `faraday-net_http` as default adapter by @iMacTia in [#1366](https://github.com/lostisland/faraday/pull/1366)
21
+ * Updated sample format in UPGRADING.md by @vimutter in [#1361](https://github.com/lostisland/faraday/pull/1361)
22
+ * docs: Make UPGRADING examples more copyable by @olleolleolle in [#1363](https://github.com/lostisland/faraday/pull/1363)
23
+
24
+ ## [2.0.0](https://github.com/lostisland/faraday/compare/v1.8.0...v2.0.0) (2022-01-04)
25
+
26
+ The next major release is here, and it comes almost 2 years after the release of v1.0!
27
+
28
+ This release changes the way you use Faraday and embraces a new paradigm of Faraday as an ecosystem, rather than a library.
29
+
30
+ What does that mean? It means that Faraday is less of a bundled tool and more of a framework for the community to build on top of.
31
+
32
+ As a result, all adapters and some middleware have moved out and are now shipped as standalone gems 🙌!
33
+
34
+ But this doesn't mean that upgrading from Faraday 1.x to Faraday 2.0 should be hard, in fact we've listed everything you need to do in the [UPGRADING.md](https://github.com/lostisland/faraday/blob/main/UPGRADING.md) doc.
35
+
36
+ Moreover, we've setup a new [awesome-faraday](https://github.com/lostisland/awesome-faraday) repository that will showcase a curated list of adapters and middleware 😎.
37
+
38
+ This release was the result of the efforts of the core team and all the contributors, new and old, that have helped achieve this milestone 👏.
39
+
40
+ ## What's Changed
41
+
42
+ * Autoloading, dependency loading and middleware registry cleanup by @iMacTia in [#1301](https://github.com/lostisland/faraday/pull/1301)
43
+ * Move JSON middleware (request and response) from faraday_middleware by @iMacTia in [#1300](https://github.com/lostisland/faraday/pull/1300)
44
+ * Remove deprecated `Faraday::Request#method` by @olleolleolle in [#1303](https://github.com/lostisland/faraday/pull/1303)
45
+ * Remove deprecated `Faraday::UploadIO` by @iMacTia in [#1307](https://github.com/lostisland/faraday/pull/1307)
46
+ * [1.x] Deprecate Authorization helpers in `Faraday::Connection` by @iMacTia in [#1306](https://github.com/lostisland/faraday/pull/1306)
47
+ * Drop deprecated auth helpers from Connection and refactor auth middleware by @iMacTia in [#1308](https://github.com/lostisland/faraday/pull/1308)
48
+ * Add Faraday 1.x examples in authentication.md docs by @iMacTia in [#1320](https://github.com/lostisland/faraday/pull/1320)
49
+ * Fix passing a URL with embedded basic auth by @iMacTia in [#1324](https://github.com/lostisland/faraday/pull/1324)
50
+ * Register JSON middleware by @mollerhoj in [#1331](https://github.com/lostisland/faraday/pull/1331)
51
+ * Retry middleware should handle string exception class name consistently by @jrochkind in [#1334](https://github.com/lostisland/faraday/pull/1334)
52
+ * Improve request info in exceptions raised by RaiseError Middleware by @willianzocolau in [#1335](https://github.com/lostisland/faraday/pull/1335)
53
+ * Remove net-http adapter and update docs by @iMacTia in [#1336](https://github.com/lostisland/faraday/pull/1336)
54
+ * Explain plan for faraday_middleware in UPGRADING.md by @iMacTia in [#1339](https://github.com/lostisland/faraday/pull/1339)
55
+ * Scripts folder cleanup by @iMacTia in [#1340](https://github.com/lostisland/faraday/pull/1340)
56
+ * Replace `Hash#merge` with `Utils#deep_merge` for connection options by @xkwd in [#1343](https://github.com/lostisland/faraday/pull/1343)
57
+ * Callable authorizers by @sled in [#1345](https://github.com/lostisland/faraday/pull/1345)
58
+ * Default value for exc error by @DariuszMusielak in [#1351](https://github.com/lostisland/faraday/pull/1351)
59
+ * Don't call `retry_block` unless a retry is going to happen by @jrochkind in [#1350](https://github.com/lostisland/faraday/pull/1350)
60
+ * Improve documentation for v2 by @iMacTia in [#1353](https://github.com/lostisland/faraday/pull/1353)
61
+ * Remove default `default_adapter` (yes, you read that right) by @iMacTia in [#1354](https://github.com/lostisland/faraday/pull/1354)
62
+ * Remove retry middleware by @iMacTia in [#1356](https://github.com/lostisland/faraday/pull/1356)
63
+ * Remove multipart middleware and all its documentation and tests by @iMacTia in [#1357](https://github.com/lostisland/faraday/pull/1357)
64
+
65
+ ## [1.9.3](https://github.com/lostisland/faraday/compare/v1.9.2...v1.9.3) (2022-01-06)
66
+
67
+ * Re-add support for Ruby 2.4+ by @iMacTia in [#1371](https://github.com/lostisland/faraday/pull/1371)
68
+
69
+ ## [1.9.2](https://github.com/lostisland/faraday/compare/v1.9.1...v1.9.2) (2022-01-06)
70
+
71
+ * Add alias with legacy name to gemified middleware by @iMacTia in [#1372](https://github.com/lostisland/faraday/pull/1372)
72
+
73
+ ## [1.9.1](https://github.com/lostisland/faraday/compare/v1.9.0...v1.9.1) (2022-01-06)
74
+
75
+ * Update adapter dependencies in Gemspec by @iMacTia in [#1370](https://github.com/lostisland/faraday/pull/1370)
76
+
77
+ ## [1.9.0](https://github.com/lostisland/faraday/compare/v1.8.0...v1.9.0) (2022-01-06)
78
+
79
+ * Use external multipart and retry middleware by @iMacTia in [#1367](https://github.com/lostisland/faraday/pull/1367)
80
+
3
81
  ## [1.8.0](https://github.com/lostisland/faraday/releases/tag/v1.8.0) (2021-09-18)
4
82
 
5
83
  ### Features
@@ -65,7 +143,7 @@
65
143
 
66
144
  ### Highlights
67
145
 
68
- With this release, we continue the work of gradually moving out adapters into their own gems 🎉
146
+ With this release, we continue the work of gradually moving out adapters into their own gems 🎉
69
147
  Thanks to @MikeRogers0 for helping the Faraday team in progressing with this quest 👏
70
148
 
71
149
  And thanks to @olleolleolle efforts, Faraday is becoming more inclusive than ever 🤗
@@ -112,7 +190,7 @@ Checkout the "Misc" section below for more details 🙌 !
112
190
  ## [v1.3.0](https://github.com/lostisland/faraday/releases/tag/v1.3.0) (2020-12-31)
113
191
 
114
192
  ### Highlights
115
- Faraday v1.3.0 is the first release to officially support Ruby 3.0 in the CI pipeline 🎉 🍾!
193
+ Faraday v1.3.0 is the first release to officially support Ruby 3.0 in the CI pipeline 🎉 🍾!
116
194
 
117
195
  This is also the first release with a previously "included" adapter (Net::HTTP) being isolated into a [separate gem](https://github.com/lostisland/faraday-net_http) 🎊!
118
196
  The new adapter is added to Faraday as a dependency for now, so that means full backwards-compatibility, but just to be safe be careful when upgrading!
@@ -203,7 +281,7 @@ Many thanks to the Faraday Team, @JanDintel and everyone who attended the [ROSS
203
281
  * Allows `parse` method to be private/protected in response middleware (#1123)
204
282
  * Encode Spaces in Query Strings as '%20' Instead of '+' (#1125)
205
283
  * Limits rack to v2.0.x (#1127)
206
- * Adapter Registry reads also use mutex (#1136)
284
+ * Adapter Registry reads also use mutex (#1136)
207
285
 
208
286
  ### Documentation
209
287
 
data/LICENSE.md CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2009-2020 Rick Olson, Zack Hobson
1
+ Copyright (c) 2009-2022 Rick Olson, Zack Hobson
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -10,11 +10,6 @@ adapters (such as Net::HTTP) and embraces the concept of Rack middleware when pr
10
10
  You probably don't want to use Faraday directly in your project, as it will lack an actual client library to perform
11
11
  requests. Instead, you probably want to have a look at [Awesome Faraday][awesome] for a list of available adapters.
12
12
 
13
- ## FARADAY 2.0
14
-
15
- You're reading the README and looking at the code of our upcoming v2.0 release (the `main` branch, currently in alpha).
16
- If you're here to read about our latest v1.x release, then please head over to the [1.x branch](https://github.com/lostisland/faraday/tree/1.x).
17
-
18
13
  ## Getting Started
19
14
 
20
15
  The best starting point is the [Faraday Website][website], with its introduction and explanation.
@@ -47,7 +42,7 @@ Open the issues page and check for the `help wanted` label!
47
42
  But before you start coding, please read our [Contributing Guide][contributing]
48
43
 
49
44
  ## Copyright
50
- © 2009 - 2021, the [Faraday Team][faraday_team]. Website and branding design by [Elena Lo Piccolo](https://elelopic.design).
45
+ © 2009 - 2022, the [Faraday Team][faraday_team]. Website and branding design by [Elena Lo Piccolo](https://elelopic.design).
51
46
 
52
47
  [awesome]: https://github.com/lostisland/awesome-faraday/#adapters
53
48
  [website]: https://lostisland.github.io/faraday
@@ -12,10 +12,15 @@ class Client
12
12
  @conn = conn
13
13
  end
14
14
 
15
- def sushi(jname, params: {})
15
+ def httpbingo(jname, params: {})
16
16
  res = @conn.get("/#{jname}", params)
17
17
  data = JSON.parse(res.body)
18
- data['name']
18
+ data['origin']
19
+ end
20
+
21
+ def foo(params)
22
+ res = @conn.post('/foo', JSON.dump(params))
23
+ res.status
19
24
  end
20
25
  end
21
26
 
@@ -24,42 +29,42 @@ RSpec.describe Client do
24
29
  let(:conn) { Faraday.new { |b| b.adapter(:test, stubs) } }
25
30
  let(:client) { Client.new(conn) }
26
31
 
27
- it 'parses name' do
28
- stubs.get('/ebi') do |env|
32
+ it 'parses origin' do
33
+ stubs.get('/ip') do |env|
29
34
  # optional: you can inspect the Faraday::Env
30
- expect(env.url.path).to eq('/ebi')
35
+ expect(env.url.path).to eq('/ip')
31
36
  [
32
37
  200,
33
38
  { 'Content-Type': 'application/javascript' },
34
- '{"name": "shrimp"}'
39
+ '{"origin": "127.0.0.1"}'
35
40
  ]
36
41
  end
37
42
 
38
43
  # uncomment to trigger stubs.verify_stubbed_calls failure
39
44
  # stubs.get('/unused') { [404, {}, ''] }
40
45
 
41
- expect(client.sushi('ebi')).to eq('shrimp')
46
+ expect(client.httpbingo('ip')).to eq('127.0.0.1')
42
47
  stubs.verify_stubbed_calls
43
48
  end
44
49
 
45
50
  it 'handles 404' do
46
- stubs.get('/ebi') do
51
+ stubs.get('/api') do
47
52
  [
48
53
  404,
49
54
  { 'Content-Type': 'application/javascript' },
50
55
  '{}'
51
56
  ]
52
57
  end
53
- expect(client.sushi('ebi')).to be_nil
58
+ expect(client.httpbingo('api')).to be_nil
54
59
  stubs.verify_stubbed_calls
55
60
  end
56
61
 
57
62
  it 'handles exception' do
58
- stubs.get('/ebi') do
63
+ stubs.get('/api') do
59
64
  raise Faraday::ConnectionFailed
60
65
  end
61
66
 
62
- expect { client.sushi('ebi') }.to raise_error(Faraday::ConnectionFailed)
67
+ expect { client.httpbingo('api') }.to raise_error(Faraday::ConnectionFailed)
63
68
  stubs.verify_stubbed_calls
64
69
  end
65
70
 
@@ -67,17 +72,17 @@ RSpec.describe Client do
67
72
  let(:stubs) { Faraday::Adapter::Test::Stubs.new(strict_mode: true) }
68
73
 
69
74
  it 'verifies the all parameter values are identical' do
70
- stubs.get('/ebi?abc=123') do
75
+ stubs.get('/api?abc=123') do
71
76
  [
72
77
  200,
73
78
  { 'Content-Type': 'application/javascript' },
74
- '{"name": "shrimp"}'
79
+ '{"origin": "127.0.0.1"}'
75
80
  ]
76
81
  end
77
82
 
78
83
  # uncomment to raise Stubs::NotFound
79
- # expect(client.sushi('ebi', params: { abc: 123, foo: 'Kappa' })).to eq('shrimp')
80
- expect(client.sushi('ebi', params: { abc: 123 })).to eq('shrimp')
84
+ # expect(client.httpbingo('api', params: { abc: 123, foo: 'Kappa' })).to eq('127.0.0.1')
85
+ expect(client.httpbingo('api', params: { abc: 123 })).to eq('127.0.0.1')
81
86
  stubs.verify_stubbed_calls
82
87
  end
83
88
  end
@@ -86,11 +91,28 @@ RSpec.describe Client do
86
91
  let(:conn) { Faraday.new(request: { params_encoder: Faraday::FlatParamsEncoder }) { |b| b.adapter(:test, stubs) } }
87
92
 
88
93
  it 'handles the same multiple URL parameters' do
89
- stubs.get('/ebi?a=x&a=y&a=z') { [200, { 'Content-Type' => 'application/json' }, '{"name": "shrimp"}'] }
94
+ stubs.get('/api?a=x&a=y&a=z') { [200, { 'Content-Type' => 'application/json' }, '{"origin": "127.0.0.1"}'] }
90
95
 
91
96
  # uncomment to raise Stubs::NotFound
92
- # expect(client.sushi('ebi', params: { a: %w[x y] })).to eq('shrimp')
93
- expect(client.sushi('ebi', params: { a: %w[x y z] })).to eq('shrimp')
97
+ # expect(client.httpbingo('api', params: { a: %w[x y] })).to eq('127.0.0.1')
98
+ expect(client.httpbingo('api', params: { a: %w[x y z] })).to eq('127.0.0.1')
99
+ stubs.verify_stubbed_calls
100
+ end
101
+ end
102
+
103
+ context 'When you want to test the body, you can use a proc as well as string' do
104
+ it 'tests with a string' do
105
+ stubs.post('/foo', '{"name":"YK"}') { [200, {}, ''] }
106
+
107
+ expect(client.foo(name: 'YK')).to eq 200
108
+ stubs.verify_stubbed_calls
109
+ end
110
+
111
+ it 'tests with a proc' do
112
+ check = ->(request_body) { JSON.parse(request_body).slice('name') == { 'name' => 'YK' } }
113
+ stubs.post('/foo', check) { [200, {}, ''] }
114
+
115
+ expect(client.foo(name: 'YK', created_at: Time.now)).to eq 200
94
116
  stubs.verify_stubbed_calls
95
117
  end
96
118
  end
@@ -13,24 +13,29 @@ class Client
13
13
  @conn = conn
14
14
  end
15
15
 
16
- def sushi(jname, params: {})
16
+ def httpbingo(jname, params: {})
17
17
  res = @conn.get("/#{jname}", params)
18
18
  data = JSON.parse(res.body)
19
- data['name']
19
+ data['origin']
20
+ end
21
+
22
+ def foo(params)
23
+ res = @conn.post('/foo', JSON.dump(params))
24
+ res.status
20
25
  end
21
26
  end
22
27
 
23
28
  # Example API client test
24
29
  class ClientTest < Test::Unit::TestCase
25
- def test_sushi_name
30
+ def test_httpbingo_name
26
31
  stubs = Faraday::Adapter::Test::Stubs.new
27
- stubs.get('/ebi') do |env|
32
+ stubs.get('/api') do |env|
28
33
  # optional: you can inspect the Faraday::Env
29
- assert_equal '/ebi', env.url.path
34
+ assert_equal '/api', env.url.path
30
35
  [
31
36
  200,
32
37
  { 'Content-Type': 'application/javascript' },
33
- '{"name": "shrimp"}'
38
+ '{"origin": "127.0.0.1"}'
34
39
  ]
35
40
  end
36
41
 
@@ -38,13 +43,13 @@ class ClientTest < Test::Unit::TestCase
38
43
  # stubs.get('/unused') { [404, {}, ''] }
39
44
 
40
45
  cli = client(stubs)
41
- assert_equal 'shrimp', cli.sushi('ebi')
46
+ assert_equal '127.0.0.1', cli.httpbingo('api')
42
47
  stubs.verify_stubbed_calls
43
48
  end
44
49
 
45
- def test_sushi_not_found
50
+ def test_httpbingo_not_found
46
51
  stubs = Faraday::Adapter::Test::Stubs.new
47
- stubs.get('/ebi') do
52
+ stubs.get('/api') do
48
53
  [
49
54
  404,
50
55
  { 'Content-Type': 'application/javascript' },
@@ -53,48 +58,48 @@ class ClientTest < Test::Unit::TestCase
53
58
  end
54
59
 
55
60
  cli = client(stubs)
56
- assert_nil cli.sushi('ebi')
61
+ assert_nil cli.httpbingo('api')
57
62
  stubs.verify_stubbed_calls
58
63
  end
59
64
 
60
- def test_sushi_exception
65
+ def test_httpbingo_exception
61
66
  stubs = Faraday::Adapter::Test::Stubs.new
62
- stubs.get('/ebi') do
67
+ stubs.get('/api') do
63
68
  raise Faraday::ConnectionFailed
64
69
  end
65
70
 
66
71
  cli = client(stubs)
67
72
  assert_raise Faraday::ConnectionFailed do
68
- cli.sushi('ebi')
73
+ cli.httpbingo('api')
69
74
  end
70
75
  stubs.verify_stubbed_calls
71
76
  end
72
77
 
73
78
  def test_strict_mode
74
79
  stubs = Faraday::Adapter::Test::Stubs.new(strict_mode: true)
75
- stubs.get('/ebi?abc=123') do
80
+ stubs.get('/api?abc=123') do
76
81
  [
77
82
  200,
78
83
  { 'Content-Type': 'application/javascript' },
79
- '{"name": "shrimp"}'
84
+ '{"origin": "127.0.0.1"}'
80
85
  ]
81
86
  end
82
87
 
83
88
  cli = client(stubs)
84
- assert_equal 'shrimp', cli.sushi('ebi', params: { abc: 123 })
89
+ assert_equal '127.0.0.1', cli.httpbingo('api', params: { abc: 123 })
85
90
 
86
91
  # uncomment to raise Stubs::NotFound
87
- # assert_equal 'shrimp', cli.sushi('ebi', params: { abc: 123, foo: 'Kappa' })
92
+ # assert_equal '127.0.0.1', cli.httpbingo('api', params: { abc: 123, foo: 'Kappa' })
88
93
  stubs.verify_stubbed_calls
89
94
  end
90
95
 
91
96
  def test_non_default_params_encoder
92
97
  stubs = Faraday::Adapter::Test::Stubs.new(strict_mode: true)
93
- stubs.get('/ebi?a=x&a=y&a=z') do
98
+ stubs.get('/api?a=x&a=y&a=z') do
94
99
  [
95
100
  200,
96
101
  { 'Content-Type': 'application/javascript' },
97
- '{"name": "shrimp"}'
102
+ '{"origin": "127.0.0.1"}'
98
103
  ]
99
104
  end
100
105
  conn = Faraday.new(request: { params_encoder: Faraday::FlatParamsEncoder }) do |builder|
@@ -102,10 +107,31 @@ class ClientTest < Test::Unit::TestCase
102
107
  end
103
108
 
104
109
  cli = Client.new(conn)
105
- assert_equal 'shrimp', cli.sushi('ebi', params: { a: %w[x y z] })
110
+ assert_equal '127.0.0.1', cli.httpbingo('api', params: { a: %w[x y z] })
106
111
 
107
112
  # uncomment to raise Stubs::NotFound
108
- # assert_equal 'shrimp', cli.sushi('ebi', params: { a: %w[x y] })
113
+ # assert_equal '127.0.0.1', cli.httpbingo('api', params: { a: %w[x y] })
114
+ stubs.verify_stubbed_calls
115
+ end
116
+
117
+ def test_with_string_body
118
+ stubs = Faraday::Adapter::Test::Stubs.new do |stub|
119
+ stub.post('/foo', '{"name":"YK"}') { [200, {}, ''] }
120
+ end
121
+ cli = client(stubs)
122
+ assert_equal 200, cli.foo(name: 'YK')
123
+
124
+ stubs.verify_stubbed_calls
125
+ end
126
+
127
+ def test_with_proc_body
128
+ stubs = Faraday::Adapter::Test::Stubs.new do |stub|
129
+ check = ->(request_body) { JSON.parse(request_body).slice('name') == { 'name' => 'YK' } }
130
+ stub.post('/foo', check) { [200, {}, ''] }
131
+ end
132
+ cli = client(stubs)
133
+ assert_equal 200, cli.foo(name: 'YK', created_at: Time.now)
134
+
109
135
  stubs.verify_stubbed_calls
110
136
  end
111
137
 
@@ -26,6 +26,15 @@ module Faraday
26
26
  # ]
27
27
  # end
28
28
  #
29
+ # # Test the request body is the same as the stubbed body
30
+ # stub.post('/bar', 'name=YK&word=call') { [200, {}, ''] }
31
+ #
32
+ # # You can pass a proc as a stubbed body and check the request body in your way.
33
+ # # In this case, the proc should return true or false.
34
+ # stub.post('/foo', ->(request_body) do
35
+ # JSON.parse(request_body).slice('name') == { 'name' => 'YK' } }) { [200, {}, '']
36
+ # end
37
+ #
29
38
  # # You can set strict_mode to exactly match the stubbed requests.
30
39
  # stub.strict_mode = true
31
40
  # end
@@ -42,6 +51,12 @@ module Faraday
42
51
  #
43
52
  # resp = test.get '/items/2'
44
53
  # resp.body # => 'showing item: 2'
54
+ #
55
+ # resp = test.post '/bar', 'name=YK&word=call'
56
+ # resp.status # => 200
57
+ #
58
+ # resp = test.post '/foo', JSON.dump(name: 'YK', created_at: Time.now)
59
+ # resp.status # => 200
45
60
  class Test < Faraday::Adapter
46
61
  attr_accessor :stubs
47
62
 
@@ -55,6 +70,7 @@ module Faraday
55
70
  @stack = {}
56
71
  @consumed = {}
57
72
  @strict_mode = strict_mode
73
+ @stubs_mutex = Monitor.new
58
74
  yield(self) if block_given?
59
75
  end
60
76
 
@@ -70,10 +86,13 @@ module Faraday
70
86
  stack = @stack[request_method]
71
87
  consumed = (@consumed[request_method] ||= [])
72
88
 
73
- stub, meta = matches?(stack, env)
74
- if stub
75
- consumed << stack.delete(stub)
76
- return stub, meta
89
+ @stubs_mutex.synchronize do
90
+ stub, meta = matches?(stack, env)
91
+ if stub
92
+ removed = stack.delete(stub)
93
+ consumed << removed unless removed.nil?
94
+ return stub, meta
95
+ end
77
96
  end
78
97
  matches?(consumed, env)
79
98
  end
@@ -177,7 +196,7 @@ module Faraday
177
196
  [(host.nil? || host == request_host) &&
178
197
  path_match?(request_path, meta) &&
179
198
  params_match?(env) &&
180
- (body.to_s.size.zero? || request_body == body) &&
199
+ body_match?(request_body) &&
181
200
  headers_match?(request_headers), meta]
182
201
  end
183
202
 
@@ -218,6 +237,17 @@ module Faraday
218
237
  end
219
238
  end
220
239
 
240
+ def body_match?(request_body)
241
+ return true if body.to_s.size.zero?
242
+
243
+ case body
244
+ when Proc
245
+ body.call(request_body)
246
+ else
247
+ request_body == body
248
+ end
249
+ end
250
+
221
251
  def to_s
222
252
  "#{path} #{body}"
223
253
  end
@@ -242,7 +272,7 @@ module Faraday
242
272
  stub, meta = stubs.match(env)
243
273
 
244
274
  unless stub
245
- raise Stubs::NotFound, "no stubbed request for #{env[:method]} "\
275
+ raise Stubs::NotFound, "no stubbed request for #{env[:method]} " \
246
276
  "#{env[:url]} #{env[:body]}"
247
277
  end
248
278
 
@@ -253,7 +283,11 @@ module Faraday
253
283
  else
254
284
  stub.block.call(env, meta)
255
285
  end
256
- save_response(env, status, body, headers)
286
+
287
+ # We need to explicitly pass `reason_phrase = nil` here to avoid keyword args conflicts.
288
+ # See https://github.com/lostisland/faraday/issues/1444
289
+ # TODO: remove `nil` explicit reason_phrase once Ruby 3.0 becomes minimum req. version
290
+ save_response(env, status, body, headers, nil)
257
291
 
258
292
  @app.call(env)
259
293
  end
@@ -59,7 +59,7 @@ module Faraday
59
59
 
60
60
  private
61
61
 
62
- def save_response(env, status, body, headers = nil, reason_phrase = nil)
62
+ def save_response(env, status, body, headers = nil, reason_phrase = nil, finished: true)
63
63
  env.status = status
64
64
  env.body = body
65
65
  env.reason_phrase = reason_phrase&.to_s&.strip
@@ -68,7 +68,7 @@ module Faraday
68
68
  yield(response_headers) if block_given?
69
69
  end
70
70
 
71
- env.response.finish(env) unless env.parallel?
71
+ env.response.finish(env) unless env.parallel? || !finished
72
72
  env.response
73
73
  end
74
74