faraday 1.0.0 → 1.3.1

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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +104 -0
  3. data/LICENSE.md +1 -1
  4. data/README.md +4 -5
  5. data/examples/client_spec.rb +1 -1
  6. data/lib/faraday.rb +51 -41
  7. data/lib/faraday/adapter.rb +1 -1
  8. data/lib/faraday/adapter/em_http.rb +18 -14
  9. data/lib/faraday/adapter/em_synchrony.rb +16 -13
  10. data/lib/faraday/adapter/excon.rb +2 -2
  11. data/lib/faraday/adapter/httpclient.rb +2 -1
  12. data/lib/faraday/adapter/net_http_persistent.rb +1 -1
  13. data/lib/faraday/adapter/typhoeus.rb +1 -1
  14. data/lib/faraday/adapter_registry.rb +3 -1
  15. data/lib/faraday/autoload.rb +1 -2
  16. data/lib/faraday/connection.rb +5 -4
  17. data/lib/faraday/encoders/flat_params_encoder.rb +9 -2
  18. data/lib/faraday/encoders/nested_params_encoder.rb +7 -2
  19. data/lib/faraday/error.rb +20 -0
  20. data/lib/faraday/methods.rb +6 -0
  21. data/lib/faraday/middleware.rb +14 -4
  22. data/lib/faraday/options.rb +4 -8
  23. data/lib/faraday/rack_builder.rb +13 -12
  24. data/lib/faraday/request.rb +20 -10
  25. data/lib/faraday/request/authorization.rb +3 -1
  26. data/lib/faraday/request/multipart.rb +10 -3
  27. data/lib/faraday/request/retry.rb +2 -2
  28. data/lib/faraday/request/url_encoded.rb +3 -1
  29. data/lib/faraday/response.rb +4 -7
  30. data/lib/faraday/response/raise_error.rb +12 -1
  31. data/lib/faraday/utils.rb +11 -3
  32. data/lib/faraday/utils/headers.rb +2 -2
  33. data/lib/faraday/version.rb +5 -0
  34. data/spec/faraday/adapter/em_http_spec.rb +1 -1
  35. data/spec/faraday/adapter/em_synchrony_spec.rb +1 -1
  36. data/spec/faraday/adapter/patron_spec.rb +1 -1
  37. data/spec/faraday/adapter/test_spec.rb +260 -0
  38. data/spec/faraday/connection_spec.rb +30 -0
  39. data/spec/faraday/error_spec.rb +15 -0
  40. data/spec/faraday/middleware_spec.rb +32 -6
  41. data/spec/faraday/params_encoders/flat_spec.rb +8 -0
  42. data/spec/faraday/params_encoders/nested_spec.rb +8 -0
  43. data/spec/faraday/rack_builder_spec.rb +150 -1
  44. data/spec/faraday/request/authorization_spec.rb +2 -2
  45. data/spec/faraday/request/multipart_spec.rb +41 -13
  46. data/spec/faraday/request/retry_spec.rb +1 -1
  47. data/spec/faraday/request/url_encoded_spec.rb +13 -0
  48. data/spec/faraday/request_spec.rb +16 -5
  49. data/spec/faraday/response/middleware_spec.rb +16 -0
  50. data/spec/faraday/response/raise_error_spec.rb +63 -0
  51. data/spec/support/shared_examples/adapter.rb +2 -1
  52. data/spec/support/shared_examples/request_method.rb +39 -11
  53. metadata +37 -7
  54. data/UPGRADING.md +0 -55
  55. data/lib/faraday/adapter/net_http.rb +0 -209
@@ -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,42 @@ 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')
134
+ end
135
+ end
136
+
137
+ describe 'request info' do
138
+ let(:conn) do
139
+ Faraday.new do |b|
140
+ b.response :raise_error
141
+ b.adapter :test do |stub|
142
+ stub.post('request?full=true', request_body, request_headers) do
143
+ [400, { 'X-Reason' => 'because' }, 'keep looking']
144
+ end
145
+ end
146
+ end
147
+ end
148
+ let(:request_body) { JSON.generate({ 'item' => 'sth' }) }
149
+ let(:request_headers) { { 'Authorization' => 'Basic 123' } }
150
+
151
+ subject(:perform_request) do
152
+ conn.post 'request' do |req|
153
+ req.headers['Authorization'] = 'Basic 123'
154
+ req.params[:full] = true
155
+ req.body = request_body
156
+ end
157
+ end
158
+
159
+ it 'returns the request info in the exception' do
160
+ expect { perform_request }.to raise_error(Faraday::BadRequestError) do |ex|
161
+ expect(ex.response[:request][:method]).to eq(:post)
162
+ expect(ex.response[:request][:url_path]).to eq('/request')
163
+ expect(ex.response[:request][:params]).to eq({ 'full' => 'true' })
164
+ expect(ex.response[:request][:headers]).to match(a_hash_including(request_headers))
165
+ expect(ex.response[:request][:body]).to eq(request_body)
166
+ end
104
167
  end
105
168
  end
106
169
  end
@@ -33,6 +33,7 @@ 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] ||= {}
@@ -46,7 +47,7 @@ shared_examples 'adapter examples' do |**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?
@@ -1,5 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ shared_examples 'proxy examples' do
4
+ it 'handles requests with proxy' do
5
+ res = conn.public_send(http_method, '/')
6
+
7
+ expect(res.status).to eq(200)
8
+ end
9
+
10
+ it 'handles proxy failures' do
11
+ request_stub.to_return(status: 407)
12
+
13
+ expect { conn.public_send(http_method, '/') }.to raise_error(Faraday::ProxyAuthError)
14
+ end
15
+ end
16
+
3
17
  shared_examples 'a request method' do |http_method|
4
18
  let(:query_or_body) { method_with_body?(http_method) ? :body : :query }
5
19
  let(:response) { conn.public_send(http_method, '/') }
@@ -13,8 +27,8 @@ shared_examples 'a request method' do |http_method|
13
27
  end
14
28
 
15
29
  it 'handles headers with multiple values' do
16
- request_stub.to_return(headers: { 'Set-Cookie' => 'one, two' })
17
- expect(response.headers['set-cookie']).to eq('one, two')
30
+ request_stub.to_return(headers: { 'Set-Cookie' => 'name=value' })
31
+ expect(response.headers['set-cookie']).to eq('name=value')
18
32
  end
19
33
 
20
34
  it 'retrieves the response headers' do
@@ -119,7 +133,7 @@ shared_examples 'a request method' do |http_method|
119
133
  request_stub.with(headers: { 'Content-Type' => %r{\Amultipart/form-data} }) do |request|
120
134
  # WebMock does not support matching body for multipart/form-data requests yet :(
121
135
  # https://github.com/bblimke/webmock/issues/623
122
- request.body =~ /RubyMultipartPost/
136
+ request.body.include?('RubyMultipartPost')
123
137
  end
124
138
  conn.public_send(http_method, '/', payload)
125
139
  end
@@ -218,17 +232,31 @@ shared_examples 'a request method' do |http_method|
218
232
  end
219
233
  end
220
234
 
221
- it 'handles requests with proxy' do
222
- conn_options[:proxy] = 'http://google.co.uk'
235
+ context 'when a proxy is provided as option' do
236
+ before do
237
+ conn_options[:proxy] = 'http://env-proxy.com:80'
238
+ end
223
239
 
224
- res = conn.public_send(http_method, '/')
225
- expect(res.status).to eq(200)
240
+ include_examples 'proxy examples'
226
241
  end
227
242
 
228
- it 'handles proxy failures' do
229
- conn_options[:proxy] = 'http://google.co.uk'
230
- request_stub.to_return(status: 407)
243
+ context 'when http_proxy env variable is set' do
244
+ let(:proxy_url) { 'http://env-proxy.com:80' }
231
245
 
232
- expect { conn.public_send(http_method, '/') }.to raise_error(Faraday::ProxyAuthError)
246
+ around do |example|
247
+ with_env 'http_proxy' => proxy_url do
248
+ example.run
249
+ end
250
+ end
251
+
252
+ include_examples 'proxy examples'
253
+
254
+ context 'when the env proxy is ignored' do
255
+ around do |example|
256
+ with_env_proxy_disabled(&example)
257
+ end
258
+
259
+ include_examples 'proxy examples'
260
+ end
233
261
  end
234
262
  end
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: 1.0.0
4
+ version: 1.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - "@technoweenie"
@@ -10,8 +10,22 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2020-01-01 00:00:00.000000000 Z
13
+ date: 2021-04-16 00:00:00.000000000 Z
14
14
  dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: faraday-net_http
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - "~>"
20
+ - !ruby/object:Gem::Version
21
+ version: '1.0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - "~>"
27
+ - !ruby/object:Gem::Version
28
+ version: '1.0'
15
29
  - !ruby/object:Gem::Dependency
16
30
  name: multipart-post
17
31
  requirement: !ruby/object:Gem::Requirement
@@ -32,6 +46,20 @@ dependencies:
32
46
  - - "<"
33
47
  - !ruby/object:Gem::Version
34
48
  version: '3'
49
+ - !ruby/object:Gem::Dependency
50
+ name: ruby2_keywords
51
+ requirement: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: 0.0.4
56
+ type: :runtime
57
+ prerelease: false
58
+ version_requirements: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: 0.0.4
35
63
  description:
36
64
  email: technoweenie@gmail.com
37
65
  executables: []
@@ -42,7 +70,6 @@ files:
42
70
  - LICENSE.md
43
71
  - README.md
44
72
  - Rakefile
45
- - UPGRADING.md
46
73
  - examples/client_spec.rb
47
74
  - examples/client_test.rb
48
75
  - lib/faraday.rb
@@ -53,7 +80,6 @@ files:
53
80
  - lib/faraday/adapter/em_synchrony/parallel_manager.rb
54
81
  - lib/faraday/adapter/excon.rb
55
82
  - lib/faraday/adapter/httpclient.rb
56
- - lib/faraday/adapter/net_http.rb
57
83
  - lib/faraday/adapter/net_http_persistent.rb
58
84
  - lib/faraday/adapter/patron.rb
59
85
  - lib/faraday/adapter/rack.rb
@@ -68,6 +94,7 @@ files:
68
94
  - lib/faraday/error.rb
69
95
  - lib/faraday/file_part.rb
70
96
  - lib/faraday/logging/formatter.rb
97
+ - lib/faraday/methods.rb
71
98
  - lib/faraday/middleware.rb
72
99
  - lib/faraday/middleware_registry.rb
73
100
  - lib/faraday/options.rb
@@ -93,6 +120,7 @@ files:
93
120
  - lib/faraday/utils.rb
94
121
  - lib/faraday/utils/headers.rb
95
122
  - lib/faraday/utils/params_hash.rb
123
+ - lib/faraday/version.rb
96
124
  - spec/external_adapters/faraday_specs_setup.rb
97
125
  - spec/faraday/adapter/em_http_spec.rb
98
126
  - spec/faraday/adapter/em_synchrony_spec.rb
@@ -102,6 +130,7 @@ files:
102
130
  - spec/faraday/adapter/net_http_spec.rb
103
131
  - spec/faraday/adapter/patron_spec.rb
104
132
  - spec/faraday/adapter/rack_spec.rb
133
+ - spec/faraday/adapter/test_spec.rb
105
134
  - spec/faraday/adapter/typhoeus_spec.rb
106
135
  - spec/faraday/adapter_registry_spec.rb
107
136
  - spec/faraday/adapter_spec.rb
@@ -143,25 +172,26 @@ licenses:
143
172
  - MIT
144
173
  metadata:
145
174
  homepage_uri: https://lostisland.github.io/faraday
146
- changelog_uri: https://github.com/lostisland/faraday/releases/tag/v1.0.0
175
+ changelog_uri: https://github.com/lostisland/faraday/releases/tag/v1.3.1
147
176
  source_code_uri: https://github.com/lostisland/faraday
148
177
  bug_tracker_uri: https://github.com/lostisland/faraday/issues
149
178
  post_install_message:
150
179
  rdoc_options: []
151
180
  require_paths:
152
181
  - lib
182
+ - spec/external_adapters
153
183
  required_ruby_version: !ruby/object:Gem::Requirement
154
184
  requirements:
155
185
  - - ">="
156
186
  - !ruby/object:Gem::Version
157
- version: '2.3'
187
+ version: '2.4'
158
188
  required_rubygems_version: !ruby/object:Gem::Requirement
159
189
  requirements:
160
190
  - - ">="
161
191
  - !ruby/object:Gem::Version
162
192
  version: '0'
163
193
  requirements: []
164
- rubygems_version: 3.1.2
194
+ rubygems_version: 3.0.3.1
165
195
  signing_key:
166
196
  specification_version: 4
167
197
  summary: HTTP/REST API client library.
data/UPGRADING.md DELETED
@@ -1,55 +0,0 @@
1
- ## Faraday 1.0
2
-
3
- ### Errors
4
- * Removes sub-class constants definition from `Faraday::Error`. A sub-class (e.g. `ClientError`) was previously accessible
5
- either through the `Faraday` module (e.g. `Faraday::ClientError`) or through the `Faraday::Error` class (e.g. `Faraday::Error::ClientError`).
6
- The latter is no longer available and the former should be used instead, so check your `rescue`s.
7
- * Introduces a new `Faraday::ServerError` (5xx status codes) alongside the existing `Faraday::ClientError` (4xx status codes).
8
- Please note `Faraday::ClientError` was previously used for both.
9
- * Introduces new Errors that describe the most common REST status codes:
10
- * Faraday::BadRequestError (400)
11
- * Faraday::UnauthorizedError (401)
12
- * Faraday::ForbiddenError (403)
13
- * Faraday::ProxyAuthError (407). Please note this raised a `Faraday::ConnectionFailed` before.
14
- * Faraday::ConflictError (409)
15
- * Faraday::UnprocessableEntityError (422)
16
- * The following error classes have changed the hierarchy to better mirror their real-world usage and semantic meaning:
17
- * TimeoutError < ServerError (was < ClientError)
18
- * ConnectionFailed < Error (was < ClientError)
19
- * SSLError < Error (was < ClientError)
20
- * ParsingError < Error (was < ClientError)
21
- * RetriableResponse < Error (was < ClientError)
22
-
23
- ### Custom adapters
24
- If you have written a custom adapter, please be aware that `env.body` is now an alias to the two new properties `request_body` and `response_body`.
25
- This should work without you noticing if your adapter inherits from `Faraday::Adapter` and calls `save_response`, but if it doesn't, then please ensure you set the `status` BEFORE the `body` while processing the response.
26
-
27
- ### Others
28
- * Dropped support for jruby and Rubinius.
29
- * Officially supports Ruby 2.4+
30
- * In order to specify the adapter you now MUST use the `#adapter` method on the connection builder. If you don't do so and your adapter inherits from `Faraday::Adapter` then Faraday will raise an exception. Otherwise, Faraday will automatically push the default adapter at the end of the stack causing your request to be executed twice.
31
- ```ruby
32
- class OfficialAdapter < Faraday::Adapter
33
- ...
34
- end
35
-
36
- class MyAdapter
37
- ...
38
- end
39
-
40
- # This will raise an exception
41
- conn = Faraday.new(...) do |f|
42
- f.use OfficialAdapter
43
- end
44
-
45
- # This will cause Faraday inserting the default adapter at the end of the stack
46
- conn = Faraday.new(...) do |f|
47
- f.use MyAdapter
48
- end
49
-
50
- # You MUST use `adapter` method
51
- conn = Faraday.new(...) do |f|
52
- f.adapter AnyAdapter
53
- end
54
- ```
55
-
@@ -1,209 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- begin
4
- require 'net/https'
5
- rescue LoadError
6
- warn 'Warning: no such file to load -- net/https. ' \
7
- 'Make sure openssl is installed if you want ssl support'
8
- require 'net/http'
9
- end
10
- require 'zlib'
11
-
12
- module Faraday
13
- class Adapter
14
- # Net::HTTP adapter.
15
- class NetHttp < Faraday::Adapter
16
- exceptions = [
17
- IOError,
18
- Errno::EADDRNOTAVAIL,
19
- Errno::ECONNABORTED,
20
- Errno::ECONNREFUSED,
21
- Errno::ECONNRESET,
22
- Errno::EHOSTUNREACH,
23
- Errno::EINVAL,
24
- Errno::ENETUNREACH,
25
- Errno::EPIPE,
26
- Net::HTTPBadResponse,
27
- Net::HTTPHeaderSyntaxError,
28
- Net::ProtocolError,
29
- SocketError,
30
- Zlib::GzipFile::Error
31
- ]
32
-
33
- exceptions << OpenSSL::SSL::SSLError if defined?(OpenSSL)
34
- exceptions << Net::OpenTimeout if defined?(Net::OpenTimeout)
35
-
36
- NET_HTTP_EXCEPTIONS = exceptions.freeze
37
-
38
- def initialize(app = nil, opts = {}, &block)
39
- @ssl_cert_store = nil
40
- super(app, opts, &block)
41
- end
42
-
43
- def build_connection(env)
44
- net_http_connection(env).tap do |http|
45
- if http.respond_to?(:use_ssl=)
46
- http.use_ssl = env[:url].scheme == 'https'
47
- end
48
- configure_ssl(http, env[:ssl])
49
- configure_request(http, env[:request])
50
- end
51
- end
52
-
53
- def net_http_connection(env)
54
- klass = if (proxy = env[:request][:proxy])
55
- Net::HTTP::Proxy(proxy[:uri].hostname, proxy[:uri].port,
56
- proxy[:user], proxy[:password])
57
- else
58
- Net::HTTP
59
- end
60
- port = env[:url].port || (env[:url].scheme == 'https' ? 443 : 80)
61
- klass.new(env[:url].hostname, port)
62
- end
63
-
64
- def call(env)
65
- super
66
- http_response = connection(env) do |http|
67
- begin
68
- perform_request(http, env)
69
- rescue *NET_HTTP_EXCEPTIONS => e
70
- if defined?(OpenSSL) && e.is_a?(OpenSSL::SSL::SSLError)
71
- raise Faraday::SSLError, e
72
- end
73
-
74
- raise Faraday::ConnectionFailed, e
75
- end
76
- end
77
-
78
- save_response(env, http_response.code.to_i,
79
- http_response.body || +'', nil,
80
- http_response.message) do |response_headers|
81
- http_response.each_header do |key, value|
82
- response_headers[key] = value
83
- end
84
- end
85
-
86
- @app.call env
87
- rescue Timeout::Error, Errno::ETIMEDOUT => e
88
- raise Faraday::TimeoutError, e
89
- end
90
-
91
- private
92
-
93
- def create_request(env)
94
- request = Net::HTTPGenericRequest.new \
95
- env[:method].to_s.upcase, # request method
96
- !!env[:body], # is there request body
97
- env[:method] != :head, # is there response body
98
- env[:url].request_uri, # request uri path
99
- env[:request_headers] # request headers
100
-
101
- if env[:body].respond_to?(:read)
102
- request.body_stream = env[:body]
103
- else
104
- request.body = env[:body]
105
- end
106
- request
107
- end
108
-
109
- def perform_request(http, env)
110
- if env[:request].stream_response?
111
- size = 0
112
- yielded = false
113
- http_response = request_with_wrapped_block(http, env) do |chunk|
114
- if chunk.bytesize.positive? || size.positive?
115
- yielded = true
116
- size += chunk.bytesize
117
- env[:request].on_data.call(chunk, size)
118
- end
119
- end
120
- env[:request].on_data.call(+'', 0) unless yielded
121
- # Net::HTTP returns something,
122
- # but it's not meaningful according to the docs.
123
- http_response.body = nil
124
- http_response
125
- else
126
- request_with_wrapped_block(http, env)
127
- end
128
- end
129
-
130
- def request_with_wrapped_block(http, env, &block)
131
- if (env[:method] == :get) && !env[:body]
132
- # prefer `get` to `request` because the former handles gzip (ruby 1.9)
133
- request_via_get_method(http, env, &block)
134
- else
135
- request_via_request_method(http, env, &block)
136
- end
137
- end
138
-
139
- def request_via_get_method(http, env, &block)
140
- http.get env[:url].request_uri, env[:request_headers], &block
141
- end
142
-
143
- def request_via_request_method(http, env, &block)
144
- if block_given?
145
- http.request create_request(env) do |response|
146
- response.read_body(&block)
147
- end
148
- else
149
- http.request create_request(env)
150
- end
151
- end
152
-
153
- def configure_ssl(http, ssl)
154
- return unless ssl
155
-
156
- http.verify_mode = ssl_verify_mode(ssl)
157
- http.cert_store = ssl_cert_store(ssl)
158
-
159
- http.cert = ssl[:client_cert] if ssl[:client_cert]
160
- http.key = ssl[:client_key] if ssl[:client_key]
161
- http.ca_file = ssl[:ca_file] if ssl[:ca_file]
162
- http.ca_path = ssl[:ca_path] if ssl[:ca_path]
163
- http.verify_depth = ssl[:verify_depth] if ssl[:verify_depth]
164
- http.ssl_version = ssl[:version] if ssl[:version]
165
- http.min_version = ssl[:min_version] if ssl[:min_version]
166
- http.max_version = ssl[:max_version] if ssl[:max_version]
167
- end
168
-
169
- def configure_request(http, req)
170
- if (sec = request_timeout(:read, req))
171
- http.read_timeout = sec
172
- end
173
-
174
- if (sec = http.respond_to?(:write_timeout=) &&
175
- request_timeout(:write, req))
176
- http.write_timeout = sec
177
- end
178
-
179
- if (sec = request_timeout(:open, req))
180
- http.open_timeout = sec
181
- end
182
-
183
- # Only set if Net::Http supports it, since Ruby 2.5.
184
- http.max_retries = 0 if http.respond_to?(:max_retries=)
185
-
186
- @config_block&.call(http)
187
- end
188
-
189
- def ssl_cert_store(ssl)
190
- return ssl[:cert_store] if ssl[:cert_store]
191
-
192
- @ssl_cert_store ||= begin
193
- # Use the default cert store by default, i.e. system ca certs
194
- OpenSSL::X509::Store.new.tap(&:set_default_paths)
195
- end
196
- end
197
-
198
- def ssl_verify_mode(ssl)
199
- ssl[:verify_mode] || begin
200
- if ssl.fetch(:verify, true)
201
- OpenSSL::SSL::VERIFY_PEER
202
- else
203
- OpenSSL::SSL::VERIFY_NONE
204
- end
205
- end
206
- end
207
- end
208
- end
209
- end