faraday 1.1.0 → 2.7.4

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 (91) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +299 -1
  3. data/LICENSE.md +1 -1
  4. data/README.md +18 -17
  5. data/examples/client_spec.rb +67 -13
  6. data/examples/client_test.rb +80 -15
  7. data/lib/faraday/adapter/test.rb +117 -52
  8. data/lib/faraday/adapter.rb +5 -20
  9. data/lib/faraday/connection.rb +64 -118
  10. data/lib/faraday/encoders/nested_params_encoder.rb +13 -6
  11. data/lib/faraday/error.rb +15 -8
  12. data/lib/faraday/logging/formatter.rb +19 -2
  13. data/lib/faraday/methods.rb +6 -0
  14. data/lib/faraday/middleware.rb +17 -5
  15. data/lib/faraday/middleware_registry.rb +17 -63
  16. data/lib/faraday/options/env.rb +31 -7
  17. data/lib/faraday/options/proxy_options.rb +4 -0
  18. data/lib/faraday/options/ssl_options.rb +11 -1
  19. data/lib/faraday/options.rb +3 -3
  20. data/lib/faraday/rack_builder.rb +23 -20
  21. data/lib/faraday/request/authorization.rb +37 -38
  22. data/lib/faraday/request/instrumentation.rb +2 -0
  23. data/lib/faraday/request/json.rb +55 -0
  24. data/lib/faraday/request/url_encoded.rb +5 -1
  25. data/lib/faraday/request.rb +12 -32
  26. data/lib/faraday/response/json.rb +54 -0
  27. data/lib/faraday/response/logger.rb +8 -4
  28. data/lib/faraday/response/raise_error.rb +9 -1
  29. data/lib/faraday/response.rb +10 -26
  30. data/lib/faraday/utils/headers.rb +7 -2
  31. data/lib/faraday/utils.rb +10 -5
  32. data/lib/faraday/version.rb +5 -0
  33. data/lib/faraday.rb +49 -58
  34. data/spec/faraday/adapter/test_spec.rb +182 -0
  35. data/spec/faraday/connection_spec.rb +207 -90
  36. data/spec/faraday/error_spec.rb +15 -0
  37. data/spec/faraday/middleware_registry_spec.rb +31 -0
  38. data/spec/faraday/middleware_spec.rb +50 -6
  39. data/spec/faraday/options/env_spec.rb +8 -2
  40. data/spec/faraday/options/proxy_options_spec.rb +7 -0
  41. data/spec/faraday/params_encoders/nested_spec.rb +8 -0
  42. data/spec/faraday/rack_builder_spec.rb +26 -54
  43. data/spec/faraday/request/authorization_spec.rb +54 -24
  44. data/spec/faraday/request/instrumentation_spec.rb +5 -7
  45. data/spec/faraday/request/json_spec.rb +111 -0
  46. data/spec/faraday/request/url_encoded_spec.rb +12 -2
  47. data/spec/faraday/request_spec.rb +5 -15
  48. data/spec/faraday/response/json_spec.rb +117 -0
  49. data/spec/faraday/response/logger_spec.rb +28 -0
  50. data/spec/faraday/response/raise_error_spec.rb +37 -4
  51. data/spec/faraday/response_spec.rb +3 -1
  52. data/spec/faraday/utils/headers_spec.rb +22 -4
  53. data/spec/faraday/utils_spec.rb +63 -1
  54. data/spec/support/fake_safe_buffer.rb +1 -1
  55. data/spec/support/helper_methods.rb +0 -37
  56. data/spec/support/shared_examples/adapter.rb +4 -3
  57. data/spec/support/shared_examples/request_method.rb +58 -29
  58. metadata +19 -45
  59. data/lib/faraday/adapter/em_http.rb +0 -286
  60. data/lib/faraday/adapter/em_http_ssl_patch.rb +0 -62
  61. data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +0 -69
  62. data/lib/faraday/adapter/em_synchrony.rb +0 -150
  63. data/lib/faraday/adapter/excon.rb +0 -124
  64. data/lib/faraday/adapter/httpclient.rb +0 -152
  65. data/lib/faraday/adapter/net_http.rb +0 -219
  66. data/lib/faraday/adapter/net_http_persistent.rb +0 -91
  67. data/lib/faraday/adapter/patron.rb +0 -132
  68. data/lib/faraday/adapter/rack.rb +0 -75
  69. data/lib/faraday/adapter/typhoeus.rb +0 -15
  70. data/lib/faraday/autoload.rb +0 -95
  71. data/lib/faraday/dependency_loader.rb +0 -39
  72. data/lib/faraday/file_part.rb +0 -128
  73. data/lib/faraday/param_part.rb +0 -53
  74. data/lib/faraday/request/basic_authentication.rb +0 -20
  75. data/lib/faraday/request/multipart.rb +0 -106
  76. data/lib/faraday/request/retry.rb +0 -239
  77. data/lib/faraday/request/token_authentication.rb +0 -20
  78. data/spec/faraday/adapter/em_http_spec.rb +0 -47
  79. data/spec/faraday/adapter/em_synchrony_spec.rb +0 -16
  80. data/spec/faraday/adapter/excon_spec.rb +0 -49
  81. data/spec/faraday/adapter/httpclient_spec.rb +0 -73
  82. data/spec/faraday/adapter/net_http_persistent_spec.rb +0 -57
  83. data/spec/faraday/adapter/net_http_spec.rb +0 -64
  84. data/spec/faraday/adapter/patron_spec.rb +0 -18
  85. data/spec/faraday/adapter/rack_spec.rb +0 -8
  86. data/spec/faraday/adapter/typhoeus_spec.rb +0 -7
  87. data/spec/faraday/composite_read_io_spec.rb +0 -80
  88. data/spec/faraday/request/multipart_spec.rb +0 -302
  89. data/spec/faraday/request/retry_spec.rb +0 -242
  90. data/spec/faraday/response/middleware_spec.rb +0 -68
  91. data/spec/support/webmock_rack_app.rb +0 -68
@@ -0,0 +1,117 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Faraday::Response::Json, type: :response do
4
+ let(:options) { {} }
5
+ let(:headers) { {} }
6
+ let(:middleware) do
7
+ described_class.new(lambda { |env|
8
+ Faraday::Response.new(env)
9
+ }, **options)
10
+ end
11
+
12
+ def process(body, content_type = 'application/json', options = {})
13
+ env = {
14
+ body: body, request: options,
15
+ request_headers: Faraday::Utils::Headers.new,
16
+ response_headers: Faraday::Utils::Headers.new(headers)
17
+ }
18
+ env[:response_headers]['content-type'] = content_type if content_type
19
+ yield(env) if block_given?
20
+ middleware.call(Faraday::Env.from(env))
21
+ end
22
+
23
+ context 'no type matching' do
24
+ it "doesn't change nil body" do
25
+ expect(process(nil).body).to be_nil
26
+ end
27
+
28
+ it 'nullifies empty body' do
29
+ expect(process('').body).to be_nil
30
+ end
31
+
32
+ it 'parses json body' do
33
+ response = process('{"a":1}')
34
+ expect(response.body).to eq('a' => 1)
35
+ expect(response.env[:raw_body]).to be_nil
36
+ end
37
+ end
38
+
39
+ context 'with preserving raw' do
40
+ let(:options) { { preserve_raw: true } }
41
+
42
+ it 'parses json body' do
43
+ response = process('{"a":1}')
44
+ expect(response.body).to eq('a' => 1)
45
+ expect(response.env[:raw_body]).to eq('{"a":1}')
46
+ end
47
+ end
48
+
49
+ context 'with default regexp type matching' do
50
+ it 'parses json body of correct type' do
51
+ response = process('{"a":1}', 'application/x-json')
52
+ expect(response.body).to eq('a' => 1)
53
+ end
54
+
55
+ it 'ignores json body of incorrect type' do
56
+ response = process('{"a":1}', 'text/json-xml')
57
+ expect(response.body).to eq('{"a":1}')
58
+ end
59
+ end
60
+
61
+ context 'with array type matching' do
62
+ let(:options) { { content_type: %w[a/b c/d] } }
63
+
64
+ it 'parses json body of correct type' do
65
+ expect(process('{"a":1}', 'a/b').body).to be_a(Hash)
66
+ expect(process('{"a":1}', 'c/d').body).to be_a(Hash)
67
+ end
68
+
69
+ it 'ignores json body of incorrect type' do
70
+ expect(process('{"a":1}', 'a/d').body).not_to be_a(Hash)
71
+ end
72
+ end
73
+
74
+ it 'chokes on invalid json' do
75
+ expect { process('{!') }.to raise_error(Faraday::ParsingError)
76
+ end
77
+
78
+ it 'includes the response on the ParsingError instance' do
79
+ process('{') { |env| env[:response] = Faraday::Response.new }
80
+ raise 'Parsing should have failed.'
81
+ rescue Faraday::ParsingError => e
82
+ expect(e.response).to be_a(Faraday::Response)
83
+ end
84
+
85
+ context 'HEAD responses' do
86
+ it "nullifies the body if it's only one space" do
87
+ response = process(' ')
88
+ expect(response.body).to be_nil
89
+ end
90
+
91
+ it "nullifies the body if it's two spaces" do
92
+ response = process(' ')
93
+ expect(response.body).to be_nil
94
+ end
95
+ end
96
+
97
+ context 'JSON options' do
98
+ let(:body) { '{"a": 1}' }
99
+ let(:result) { { a: 1 } }
100
+ let(:options) do
101
+ {
102
+ parser_options: {
103
+ symbolize_names: true
104
+ }
105
+ }
106
+ end
107
+
108
+ it 'passes relevant options to JSON parse' do
109
+ expect(::JSON).to receive(:parse)
110
+ .with(body, options[:parser_options])
111
+ .and_return(result)
112
+
113
+ response = process(body)
114
+ expect(response.body).to eq(result)
115
+ end
116
+ end
117
+ end
@@ -64,6 +64,15 @@ RSpec.describe Faraday::Response::Logger do
64
64
  expect(formatter).to receive(:response).with(an_instance_of(Faraday::Env))
65
65
  conn.get '/hello'
66
66
  end
67
+
68
+ context 'when no route' do
69
+ it 'delegates logging to the formatter' do
70
+ expect(formatter).to receive(:request).with(an_instance_of(Faraday::Env))
71
+ expect(formatter).to receive(:exception).with(an_instance_of(Faraday::Adapter::Test::Stubs::NotFound))
72
+
73
+ expect { conn.get '/noroute' }.to raise_error(Faraday::Adapter::Test::Stubs::NotFound)
74
+ end
75
+ end
67
76
  end
68
77
 
69
78
  context 'with custom formatter' do
@@ -94,6 +103,16 @@ RSpec.describe Faraday::Response::Logger do
94
103
  expect(string_io.string).to match('GET http:/hello')
95
104
  end
96
105
 
106
+ it 'logs status' do
107
+ conn.get '/hello', nil, accept: 'text/html'
108
+ expect(string_io.string).to match('Status 200')
109
+ end
110
+
111
+ it 'does not log error message by default' do
112
+ expect { conn.get '/noroute' }.to raise_error(Faraday::Adapter::Test::Stubs::NotFound)
113
+ expect(string_io.string).not_to match(%(no stubbed request for get http:/noroute))
114
+ end
115
+
97
116
  it 'logs request headers by default' do
98
117
  conn.get '/hello', nil, accept: 'text/html'
99
118
  expect(string_io.string).to match(%(Accept: "text/html))
@@ -188,6 +207,15 @@ RSpec.describe Faraday::Response::Logger do
188
207
  end
189
208
  end
190
209
 
210
+ context 'when logging errors' do
211
+ let(:logger_options) { { errors: true } }
212
+
213
+ it 'logs error message' do
214
+ expect { conn.get '/noroute' }.to raise_error(Faraday::Adapter::Test::Stubs::NotFound)
215
+ expect(string_io.string).to match(%(no stubbed request for get http:/noroute))
216
+ end
217
+ end
218
+
191
219
  context 'when using log_level' do
192
220
  let(:logger_options) { { bodies: true, log_level: :debug } }
193
221
 
@@ -29,6 +29,9 @@ RSpec.describe Faraday::Response::RaiseError do
29
29
  expect(ex.message).to eq('the server responded with status 400')
30
30
  expect(ex.response[:headers]['X-Reason']).to eq('because')
31
31
  expect(ex.response[:status]).to eq(400)
32
+ expect(ex.response_status).to eq(400)
33
+ expect(ex.response_body).to eq('keep looking')
34
+ expect(ex.response_headers['X-Reason']).to eq('because')
32
35
  end
33
36
  end
34
37
 
@@ -37,6 +40,9 @@ RSpec.describe Faraday::Response::RaiseError do
37
40
  expect(ex.message).to eq('the server responded with status 401')
38
41
  expect(ex.response[:headers]['X-Reason']).to eq('because')
39
42
  expect(ex.response[:status]).to eq(401)
43
+ expect(ex.response_status).to eq(401)
44
+ expect(ex.response_body).to eq('keep looking')
45
+ expect(ex.response_headers['X-Reason']).to eq('because')
40
46
  end
41
47
  end
42
48
 
@@ -45,6 +51,9 @@ RSpec.describe Faraday::Response::RaiseError do
45
51
  expect(ex.message).to eq('the server responded with status 403')
46
52
  expect(ex.response[:headers]['X-Reason']).to eq('because')
47
53
  expect(ex.response[:status]).to eq(403)
54
+ expect(ex.response_status).to eq(403)
55
+ expect(ex.response_body).to eq('keep looking')
56
+ expect(ex.response_headers['X-Reason']).to eq('because')
48
57
  end
49
58
  end
50
59
 
@@ -53,6 +62,9 @@ RSpec.describe Faraday::Response::RaiseError do
53
62
  expect(ex.message).to eq('the server responded with status 404')
54
63
  expect(ex.response[:headers]['X-Reason']).to eq('because')
55
64
  expect(ex.response[:status]).to eq(404)
65
+ expect(ex.response_status).to eq(404)
66
+ expect(ex.response_body).to eq('keep looking')
67
+ expect(ex.response_headers['X-Reason']).to eq('because')
56
68
  end
57
69
  end
58
70
 
@@ -61,6 +73,9 @@ RSpec.describe Faraday::Response::RaiseError do
61
73
  expect(ex.message).to eq('407 "Proxy Authentication Required"')
62
74
  expect(ex.response[:headers]['X-Reason']).to eq('because')
63
75
  expect(ex.response[:status]).to eq(407)
76
+ expect(ex.response_status).to eq(407)
77
+ expect(ex.response_body).to eq('keep looking')
78
+ expect(ex.response_headers['X-Reason']).to eq('because')
64
79
  end
65
80
  end
66
81
 
@@ -69,6 +84,9 @@ RSpec.describe Faraday::Response::RaiseError do
69
84
  expect(ex.message).to eq('the server responded with status 409')
70
85
  expect(ex.response[:headers]['X-Reason']).to eq('because')
71
86
  expect(ex.response[:status]).to eq(409)
87
+ expect(ex.response_status).to eq(409)
88
+ expect(ex.response_body).to eq('keep looking')
89
+ expect(ex.response_headers['X-Reason']).to eq('because')
72
90
  end
73
91
  end
74
92
 
@@ -77,6 +95,9 @@ RSpec.describe Faraday::Response::RaiseError do
77
95
  expect(ex.message).to eq('the server responded with status 422')
78
96
  expect(ex.response[:headers]['X-Reason']).to eq('because')
79
97
  expect(ex.response[:status]).to eq(422)
98
+ expect(ex.response_status).to eq(422)
99
+ expect(ex.response_body).to eq('keep looking')
100
+ expect(ex.response_headers['X-Reason']).to eq('because')
80
101
  end
81
102
  end
82
103
 
@@ -85,6 +106,9 @@ RSpec.describe Faraday::Response::RaiseError do
85
106
  expect(ex.message).to eq('http status could not be derived from the server response')
86
107
  expect(ex.response[:headers]['X-Reason']).to eq('nil')
87
108
  expect(ex.response[:status]).to be_nil
109
+ expect(ex.response_status).to be_nil
110
+ expect(ex.response_body).to eq('fail')
111
+ expect(ex.response_headers['X-Reason']).to eq('nil')
88
112
  end
89
113
  end
90
114
 
@@ -93,6 +117,9 @@ RSpec.describe Faraday::Response::RaiseError do
93
117
  expect(ex.message).to eq('the server responded with status 499')
94
118
  expect(ex.response[:headers]['X-Reason']).to eq('because')
95
119
  expect(ex.response[:status]).to eq(499)
120
+ expect(ex.response_status).to eq(499)
121
+ expect(ex.response_body).to eq('keep looking')
122
+ expect(ex.response_headers['X-Reason']).to eq('because')
96
123
  end
97
124
  end
98
125
 
@@ -101,6 +128,9 @@ RSpec.describe Faraday::Response::RaiseError do
101
128
  expect(ex.message).to eq('the server responded with status 500')
102
129
  expect(ex.response[:headers]['X-Error']).to eq('bailout')
103
130
  expect(ex.response[:status]).to eq(500)
131
+ expect(ex.response_status).to eq(500)
132
+ expect(ex.response_body).to eq('fail')
133
+ expect(ex.response_headers['X-Error']).to eq('bailout')
104
134
  end
105
135
  end
106
136
 
@@ -109,7 +139,7 @@ RSpec.describe Faraday::Response::RaiseError do
109
139
  Faraday.new do |b|
110
140
  b.response :raise_error
111
141
  b.adapter :test do |stub|
112
- stub.post('request?full=true', request_body, request_headers) do
142
+ stub.post(url, request_body, request_headers) do
113
143
  [400, { 'X-Reason' => 'because' }, 'keep looking']
114
144
  end
115
145
  end
@@ -117,11 +147,13 @@ RSpec.describe Faraday::Response::RaiseError do
117
147
  end
118
148
  let(:request_body) { JSON.generate({ 'item' => 'sth' }) }
119
149
  let(:request_headers) { { 'Authorization' => 'Basic 123' } }
150
+ let(:url_path) { 'request' }
151
+ let(:query_params) { 'full=true' }
152
+ let(:url) { "#{url_path}?#{query_params}" }
120
153
 
121
154
  subject(:perform_request) do
122
- conn.post 'request' do |req|
155
+ conn.post url do |req|
123
156
  req.headers['Authorization'] = 'Basic 123'
124
- req.params[:full] = true
125
157
  req.body = request_body
126
158
  end
127
159
  end
@@ -129,7 +161,8 @@ RSpec.describe Faraday::Response::RaiseError do
129
161
  it 'returns the request info in the exception' do
130
162
  expect { perform_request }.to raise_error(Faraday::BadRequestError) do |ex|
131
163
  expect(ex.response[:request][:method]).to eq(:post)
132
- expect(ex.response[:request][:url_path]).to eq('/request')
164
+ expect(ex.response[:request][:url]).to eq(URI("http:/#{url}"))
165
+ expect(ex.response[:request][:url_path]).to eq("/#{url_path}")
133
166
  expect(ex.response[:request][:params]).to eq({ 'full' => 'true' })
134
167
  expect(ex.response[:request][:headers]).to match(a_hash_including(request_headers))
135
168
  expect(ex.response[:request][:body]).to eq(request_body)
@@ -4,7 +4,7 @@ RSpec.describe Faraday::Response do
4
4
  subject { Faraday::Response.new(env) }
5
5
 
6
6
  let(:env) do
7
- Faraday::Env.from(status: 404, body: 'yikes',
7
+ Faraday::Env.from(status: 404, body: 'yikes', url: Faraday::Utils.URI('https://lostisland.github.io/faraday'),
8
8
  response_headers: { 'Content-Type' => 'text/plain' })
9
9
  end
10
10
 
@@ -30,6 +30,7 @@ RSpec.describe Faraday::Response do
30
30
  it { expect(hash[:status]).to eq(subject.status) }
31
31
  it { expect(hash[:response_headers]).to eq(subject.headers) }
32
32
  it { expect(hash[:body]).to eq(subject.body) }
33
+ it { expect(hash[:url]).to eq(subject.env.url) }
33
34
  end
34
35
 
35
36
  describe 'marshal serialization support' do
@@ -45,6 +46,7 @@ RSpec.describe Faraday::Response do
45
46
  it { expect(loaded.env[:body]).to eq(env[:body]) }
46
47
  it { expect(loaded.env[:response_headers]).to eq(env[:response_headers]) }
47
48
  it { expect(loaded.env[:status]).to eq(env[:status]) }
49
+ it { expect(loaded.env[:url]).to eq(env[:url]) }
48
50
  end
49
51
 
50
52
  describe '#on_complete' do
@@ -57,26 +57,44 @@ RSpec.describe Faraday::Utils::Headers do
57
57
  end
58
58
 
59
59
  describe '#parse' do
60
- before { subject.parse(headers) }
61
-
62
60
  context 'when response headers leave http status line out' do
63
61
  let(:headers) { "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n" }
64
62
 
63
+ before { subject.parse(headers) }
64
+
65
65
  it { expect(subject.keys).to eq(%w[Content-Type]) }
66
66
  it { expect(subject['Content-Type']).to eq('text/html') }
67
67
  it { expect(subject['content-type']).to eq('text/html') }
68
68
  end
69
69
 
70
70
  context 'when response headers values include a colon' do
71
- let(:headers) { "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nLocation: http://sushi.com/\r\n\r\n" }
71
+ let(:headers) { "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nLocation: http://httpbingo.org/\r\n\r\n" }
72
72
 
73
- it { expect(subject['location']).to eq('http://sushi.com/') }
73
+ before { subject.parse(headers) }
74
+
75
+ it { expect(subject['location']).to eq('http://httpbingo.org/') }
74
76
  end
75
77
 
76
78
  context 'when response headers include a blank line' do
77
79
  let(:headers) { "HTTP/1.1 200 OK\r\n\r\nContent-Type: text/html\r\n\r\n" }
78
80
 
81
+ before { subject.parse(headers) }
82
+
79
83
  it { expect(subject['content-type']).to eq('text/html') }
80
84
  end
85
+
86
+ context 'when response headers include already stored keys' do
87
+ let(:headers) { "HTTP/1.1 200 OK\r\nX-Numbers: 123\r\n\r\n" }
88
+
89
+ before do
90
+ h = subject
91
+ h[:x_numbers] = 8
92
+ h.parse(headers)
93
+ end
94
+
95
+ it do
96
+ expect(subject[:x_numbers]).to eq('8, 123')
97
+ end
98
+ end
81
99
  end
82
100
  end
@@ -4,7 +4,7 @@ RSpec.describe Faraday::Utils do
4
4
  describe 'headers parsing' do
5
5
  let(:multi_response_headers) do
6
6
  "HTTP/1.x 500 OK\r\nContent-Type: text/html; charset=UTF-8\r\n" \
7
- "HTTP/1.x 200 OK\r\nContent-Type: application/json; charset=UTF-8\r\n\r\n"
7
+ "HTTP/1.x 200 OK\r\nContent-Type: application/json; charset=UTF-8\r\n\r\n"
8
8
  end
9
9
 
10
10
  it 'parse headers for aggregated responses' do
@@ -53,4 +53,66 @@ RSpec.describe Faraday::Utils do
53
53
  expect(headers).not_to have_key('authorization')
54
54
  end
55
55
  end
56
+
57
+ describe '.deep_merge!' do
58
+ let(:connection_options) { Faraday::ConnectionOptions.new }
59
+ let(:url) do
60
+ {
61
+ url: 'http://example.com/abc',
62
+ headers: { 'Mime-Version' => '1.0' },
63
+ request: { oauth: { consumer_key: 'anonymous' } },
64
+ ssl: { version: '2' }
65
+ }
66
+ end
67
+
68
+ it 'recursively merges the headers' do
69
+ connection_options.headers = { user_agent: 'My Agent 1.0' }
70
+ deep_merge = Faraday::Utils.deep_merge!(connection_options, url)
71
+
72
+ expect(deep_merge.headers).to eq('Mime-Version' => '1.0', user_agent: 'My Agent 1.0')
73
+ end
74
+
75
+ context 'when a target hash has an Options Struct value' do
76
+ let(:request) do
77
+ {
78
+ params_encoder: nil,
79
+ proxy: nil,
80
+ bind: nil,
81
+ timeout: nil,
82
+ open_timeout: nil,
83
+ read_timeout: nil,
84
+ write_timeout: nil,
85
+ boundary: nil,
86
+ oauth: { consumer_key: 'anonymous' },
87
+ context: nil,
88
+ on_data: nil
89
+ }
90
+ end
91
+ let(:ssl) do
92
+ {
93
+ verify: nil,
94
+ ca_file: nil,
95
+ ca_path: nil,
96
+ verify_mode: nil,
97
+ cert_store: nil,
98
+ client_cert: nil,
99
+ client_key: nil,
100
+ certificate: nil,
101
+ private_key: nil,
102
+ verify_depth: nil,
103
+ version: '2',
104
+ min_version: nil,
105
+ max_version: nil,
106
+ verify_hostname: nil
107
+ }
108
+ end
109
+
110
+ it 'does not overwrite an Options Struct value' do
111
+ deep_merge = Faraday::Utils.deep_merge!(connection_options, url)
112
+
113
+ expect(deep_merge.request.to_h).to eq(request)
114
+ expect(deep_merge.ssl.to_h).to eq(ssl)
115
+ end
116
+ end
117
+ end
56
118
  end
@@ -8,7 +8,7 @@ FakeSafeBuffer = Struct.new(:string) do
8
8
 
9
9
  def gsub(regex)
10
10
  string.gsub(regex) do
11
- match, = $&, '' =~ /a/
11
+ match, = Regexp.last_match(0), '' =~ /a/ # rubocop:disable Performance/StringInclude
12
12
  yield(match)
13
13
  end
14
14
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'multipart_parser/reader'
4
-
5
3
  module Faraday
6
4
  module HelperMethods
7
5
  def self.included(base)
@@ -86,41 +84,6 @@ module Faraday
86
84
  end
87
85
  end
88
86
 
89
- def multipart_file
90
- Faraday::FilePart.new(__FILE__, 'text/x-ruby')
91
- end
92
-
93
- # parse boundary out of a Content-Type header like:
94
- # Content-Type: multipart/form-data; boundary=gc0p4Jq0M2Yt08jU534c0p
95
- def parse_multipart_boundary(ctype)
96
- MultipartParser::Reader.extract_boundary_value(ctype)
97
- end
98
-
99
- # parse a multipart MIME message, returning a hash of any multipart errors
100
- def parse_multipart(boundary, body)
101
- reader = MultipartParser::Reader.new(boundary)
102
- result = { errors: [], parts: [] }
103
- def result.part(name)
104
- hash = self[:parts].detect { |h| h[:part].name == name }
105
- [hash[:part], hash[:body].join]
106
- end
107
-
108
- reader.on_part do |part|
109
- result[:parts] << thispart = {
110
- part: part,
111
- body: []
112
- }
113
- part.on_data do |chunk|
114
- thispart[:body] << chunk
115
- end
116
- end
117
- reader.on_error do |msg|
118
- result[:errors] << msg
119
- end
120
- reader.write(body)
121
- result
122
- end
123
-
124
87
  def method_with_body?(method)
125
88
  self.class.method_with_body?(method)
126
89
  end
@@ -33,20 +33,21 @@ shared_examples 'adapter examples' do |**options|
33
33
 
34
34
  let(:protocol) { ssl_mode? ? 'https' : 'http' }
35
35
  let(:remote) { "#{protocol}://example.com" }
36
+ let(:stub_remote) { remote }
36
37
 
37
38
  let(:conn) do
38
39
  conn_options[:ssl] ||= {}
39
- conn_options[:ssl][:ca_file] ||= ENV['SSL_FILE']
40
+ conn_options[:ssl][:ca_file] ||= ENV.fetch('SSL_FILE', nil)
41
+ conn_options[:ssl][:verify_hostname] ||= ENV['SSL_VERIFY_HOSTNAME'] == 'yes'
40
42
 
41
43
  Faraday.new(remote, conn_options) do |conn|
42
- conn.request :multipart
43
44
  conn.request :url_encoded
44
45
  conn.response :raise_error
45
46
  conn.adapter described_class, *adapter_options
46
47
  end
47
48
  end
48
49
 
49
- let!(:request_stub) { stub_request(http_method, remote) }
50
+ let!(:request_stub) { stub_request(http_method, stub_remote) }
50
51
 
51
52
  after do
52
53
  expect(request_stub).to have_been_requested unless request_stub.disabled?