faraday 0.17.3 → 1.0.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 (134) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +52 -8
  3. data/LICENSE.md +1 -1
  4. data/README.md +18 -358
  5. data/Rakefile +1 -7
  6. data/UPGRADING.md +55 -0
  7. data/examples/client_spec.rb +65 -0
  8. data/examples/client_test.rb +79 -0
  9. data/lib/faraday/adapter/em_http.rb +141 -99
  10. data/lib/faraday/adapter/em_http_ssl_patch.rb +24 -18
  11. data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +18 -15
  12. data/lib/faraday/adapter/em_synchrony.rb +104 -60
  13. data/lib/faraday/adapter/excon.rb +98 -56
  14. data/lib/faraday/adapter/httpclient.rb +82 -59
  15. data/lib/faraday/adapter/net_http.rb +119 -62
  16. data/lib/faraday/adapter/net_http_persistent.rb +50 -27
  17. data/lib/faraday/adapter/patron.rb +80 -43
  18. data/lib/faraday/adapter/rack.rb +30 -13
  19. data/lib/faraday/adapter/test.rb +86 -53
  20. data/lib/faraday/adapter/typhoeus.rb +4 -1
  21. data/lib/faraday/adapter.rb +82 -22
  22. data/lib/faraday/adapter_registry.rb +28 -0
  23. data/lib/faraday/autoload.rb +47 -36
  24. data/lib/faraday/connection.rb +312 -182
  25. data/lib/faraday/dependency_loader.rb +37 -0
  26. data/lib/faraday/encoders/flat_params_encoder.rb +98 -0
  27. data/lib/faraday/encoders/nested_params_encoder.rb +171 -0
  28. data/lib/faraday/error.rb +9 -35
  29. data/lib/faraday/file_part.rb +128 -0
  30. data/lib/faraday/logging/formatter.rb +105 -0
  31. data/lib/faraday/middleware.rb +12 -28
  32. data/lib/faraday/middleware_registry.rb +129 -0
  33. data/lib/faraday/options/connection_options.rb +22 -0
  34. data/lib/faraday/options/env.rb +181 -0
  35. data/lib/faraday/options/proxy_options.rb +28 -0
  36. data/lib/faraday/options/request_options.rb +22 -0
  37. data/lib/faraday/options/ssl_options.rb +59 -0
  38. data/lib/faraday/options.rb +32 -183
  39. data/lib/faraday/param_part.rb +53 -0
  40. data/lib/faraday/parameters.rb +4 -197
  41. data/lib/faraday/rack_builder.rb +66 -55
  42. data/lib/faraday/request/authorization.rb +42 -30
  43. data/lib/faraday/request/basic_authentication.rb +14 -7
  44. data/lib/faraday/request/instrumentation.rb +45 -27
  45. data/lib/faraday/request/multipart.rb +79 -48
  46. data/lib/faraday/request/retry.rb +197 -171
  47. data/lib/faraday/request/token_authentication.rb +15 -10
  48. data/lib/faraday/request/url_encoded.rb +41 -23
  49. data/lib/faraday/request.rb +68 -36
  50. data/lib/faraday/response/logger.rb +22 -69
  51. data/lib/faraday/response/raise_error.rb +38 -18
  52. data/lib/faraday/response.rb +20 -13
  53. data/lib/faraday/utils/headers.rb +139 -0
  54. data/lib/faraday/utils/params_hash.rb +61 -0
  55. data/lib/faraday/utils.rb +28 -245
  56. data/lib/faraday.rb +93 -174
  57. data/spec/external_adapters/faraday_specs_setup.rb +14 -0
  58. data/spec/faraday/adapter/em_http_spec.rb +47 -0
  59. data/spec/faraday/adapter/em_synchrony_spec.rb +16 -0
  60. data/spec/faraday/adapter/excon_spec.rb +49 -0
  61. data/spec/faraday/adapter/httpclient_spec.rb +73 -0
  62. data/spec/faraday/adapter/net_http_persistent_spec.rb +57 -0
  63. data/spec/faraday/adapter/net_http_spec.rb +64 -0
  64. data/spec/faraday/adapter/patron_spec.rb +18 -0
  65. data/spec/faraday/adapter/rack_spec.rb +8 -0
  66. data/spec/faraday/adapter/typhoeus_spec.rb +7 -0
  67. data/spec/faraday/adapter_registry_spec.rb +28 -0
  68. data/spec/faraday/adapter_spec.rb +55 -0
  69. data/spec/faraday/composite_read_io_spec.rb +80 -0
  70. data/spec/faraday/connection_spec.rb +691 -0
  71. data/spec/faraday/error_spec.rb +0 -57
  72. data/spec/faraday/middleware_spec.rb +26 -0
  73. data/spec/faraday/options/env_spec.rb +70 -0
  74. data/spec/faraday/options/options_spec.rb +297 -0
  75. data/spec/faraday/options/proxy_options_spec.rb +37 -0
  76. data/spec/faraday/options/request_options_spec.rb +19 -0
  77. data/spec/faraday/params_encoders/flat_spec.rb +34 -0
  78. data/spec/faraday/params_encoders/nested_spec.rb +134 -0
  79. data/spec/faraday/rack_builder_spec.rb +196 -0
  80. data/spec/faraday/request/authorization_spec.rb +88 -0
  81. data/spec/faraday/request/instrumentation_spec.rb +76 -0
  82. data/spec/faraday/request/multipart_spec.rb +274 -0
  83. data/spec/faraday/request/retry_spec.rb +242 -0
  84. data/spec/faraday/request/url_encoded_spec.rb +70 -0
  85. data/spec/faraday/request_spec.rb +109 -0
  86. data/spec/faraday/response/logger_spec.rb +220 -0
  87. data/spec/faraday/response/middleware_spec.rb +52 -0
  88. data/spec/faraday/response/raise_error_spec.rb +15 -15
  89. data/spec/faraday/response_spec.rb +75 -0
  90. data/spec/faraday/utils/headers_spec.rb +82 -0
  91. data/spec/faraday/utils_spec.rb +56 -0
  92. data/spec/faraday_spec.rb +37 -0
  93. data/spec/spec_helper.rb +63 -36
  94. data/spec/support/disabling_stub.rb +14 -0
  95. data/spec/support/fake_safe_buffer.rb +15 -0
  96. data/spec/support/helper_methods.rb +133 -0
  97. data/spec/support/shared_examples/adapter.rb +104 -0
  98. data/spec/support/shared_examples/params_encoder.rb +18 -0
  99. data/spec/support/shared_examples/request_method.rb +234 -0
  100. data/spec/support/streaming_response_checker.rb +35 -0
  101. data/spec/support/webmock_rack_app.rb +68 -0
  102. metadata +65 -37
  103. data/lib/faraday/deprecate.rb +0 -107
  104. data/lib/faraday/upload_io.rb +0 -67
  105. data/spec/faraday/deprecate_spec.rb +0 -69
  106. data/test/adapters/default_test.rb +0 -14
  107. data/test/adapters/em_http_test.rb +0 -30
  108. data/test/adapters/em_synchrony_test.rb +0 -32
  109. data/test/adapters/excon_test.rb +0 -30
  110. data/test/adapters/httpclient_test.rb +0 -34
  111. data/test/adapters/integration.rb +0 -263
  112. data/test/adapters/logger_test.rb +0 -136
  113. data/test/adapters/net_http_persistent_test.rb +0 -114
  114. data/test/adapters/net_http_test.rb +0 -79
  115. data/test/adapters/patron_test.rb +0 -40
  116. data/test/adapters/rack_test.rb +0 -38
  117. data/test/adapters/test_middleware_test.rb +0 -157
  118. data/test/adapters/typhoeus_test.rb +0 -38
  119. data/test/authentication_middleware_test.rb +0 -65
  120. data/test/composite_read_io_test.rb +0 -109
  121. data/test/connection_test.rb +0 -738
  122. data/test/env_test.rb +0 -268
  123. data/test/helper.rb +0 -75
  124. data/test/live_server.rb +0 -67
  125. data/test/middleware/instrumentation_test.rb +0 -88
  126. data/test/middleware/retry_test.rb +0 -282
  127. data/test/middleware_stack_test.rb +0 -260
  128. data/test/multibyte.txt +0 -1
  129. data/test/options_test.rb +0 -333
  130. data/test/parameters_test.rb +0 -157
  131. data/test/request_middleware_test.rb +0 -126
  132. data/test/response_middleware_test.rb +0 -72
  133. data/test/strawberry.rb +0 -2
  134. data/test/utils_test.rb +0 -98
@@ -1,7 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'uri'
2
4
 
3
5
  module Faraday
4
6
  class Adapter
7
+ # EventMachine Synchrony adapter.
5
8
  class EMSynchrony < Faraday::Adapter
6
9
  include EMHttp::Options
7
10
 
@@ -13,7 +16,8 @@ module Faraday
13
16
 
14
17
  self.supports_parallel = true
15
18
 
16
- def self.setup_parallel_manager(options = {})
19
+ # @return [ParallelManager]
20
+ def self.setup_parallel_manager(_options = nil)
17
21
  ParallelManager.new
18
22
  end
19
23
 
@@ -23,73 +27,110 @@ module Faraday
23
27
 
24
28
  http_method = env[:method].to_s.downcase.to_sym
25
29
 
26
- # Queue requests for parallel execution.
27
30
  if env[:parallel_manager]
28
- env[:parallel_manager].add(request, http_method, request_config(env)) do |resp|
29
- save_response(env, resp.response_header.status, resp.response) do |resp_headers|
30
- resp.response_header.each do |name, value|
31
- resp_headers[name.to_sym] = value
32
- end
33
- end
31
+ # Queue requests for parallel execution.
32
+ execute_parallel_request(env, request, http_method)
33
+ else
34
+ # Execute single request.
35
+ execute_single_request(env, request, http_method)
36
+ end
34
37
 
35
- # Finalize the response object with values from `env`.
36
- env[:response].finish(env)
37
- end
38
+ @app.call env
39
+ rescue Errno::ECONNREFUSED
40
+ raise Faraday::ConnectionFailed, $ERROR_INFO
41
+ rescue EventMachine::Connectify::CONNECTError => e
42
+ if e.message.include?('Proxy Authentication Required')
43
+ raise Faraday::ConnectionFailed,
44
+ %(407 "Proxy Authentication Required")
45
+ end
38
46
 
39
- # Execute single request.
40
- else
41
- client = nil
42
- block = lambda { request.send(http_method, request_config(env)) }
43
-
44
- if !EM.reactor_running?
45
- EM.run do
46
- Fiber.new {
47
- client = block.call
48
- EM.stop
49
- }.resume
50
- end
51
- else
52
- client = block.call
53
- end
47
+ raise Faraday::ConnectionFailed, e
48
+ rescue Errno::ETIMEDOUT => e
49
+ raise Faraday::TimeoutError, e
50
+ rescue RuntimeError => e
51
+ if e.message == 'connection closed by server'
52
+ raise Faraday::ConnectionFailed, e
53
+ end
54
+
55
+ raise Faraday::TimeoutError, e if e.message.include?('timeout error')
56
+
57
+ raise
58
+ rescue StandardError => e
59
+ if defined?(OpenSSL) && e.is_a?(OpenSSL::SSL::SSLError)
60
+ raise Faraday::SSLError, e
61
+ end
62
+
63
+ raise
64
+ end
65
+
66
+ def create_request(env)
67
+ EventMachine::HttpRequest.new(
68
+ Utils::URI(env[:url].to_s),
69
+ connection_config(env).merge(@connection_options)
70
+ )
71
+ end
54
72
 
55
- raise client.error if client.error
73
+ private
56
74
 
57
- status = client.response_header.status
58
- reason = client.response_header.http_reason
59
- save_response(env, status, client.response, nil, reason) do |resp_headers|
60
- client.response_header.each do |name, value|
75
+ def execute_parallel_request(env, request, http_method)
76
+ env[:parallel_manager].add(request, http_method,
77
+ request_config(env)) do |resp|
78
+ if (req = env[:request]).stream_response?
79
+ warn "Streaming downloads for #{self.class.name} " \
80
+ 'are not yet implemented.'
81
+ req.on_data.call(resp.response, resp.response.bytesize)
82
+ end
83
+
84
+ save_response(env, resp.response_header.status,
85
+ resp.response) do |resp_headers|
86
+ resp.response_header.each do |name, value|
61
87
  resp_headers[name.to_sym] = value
62
88
  end
63
89
  end
90
+
91
+ # Finalize the response object with values from `env`.
92
+ env[:response].finish(env)
64
93
  end
94
+ end
65
95
 
66
- @app.call env
67
- rescue Errno::ECONNREFUSED
68
- raise Faraday::ConnectionFailed, $!
69
- rescue EventMachine::Connectify::CONNECTError => err
70
- if err.message.include?("Proxy Authentication Required")
71
- raise Faraday::ConnectionFailed, %{407 "Proxy Authentication Required "}
72
- else
73
- raise Faraday::ConnectionFailed, err
96
+ def execute_single_request(env, request, http_method)
97
+ block = -> { request.send(http_method, request_config(env)) }
98
+ client = call_block(block)
99
+
100
+ raise client.error if client&.error
101
+
102
+ if env[:request].stream_response?
103
+ warn "Streaming downloads for #{self.class.name} " \
104
+ 'are not yet implemented.'
105
+ env[:request].on_data.call(
106
+ client.response,
107
+ client.response.bytesize
108
+ )
74
109
  end
75
- rescue Errno::ETIMEDOUT => err
76
- raise Faraday::TimeoutError, err
77
- rescue RuntimeError => err
78
- if err.message == "connection closed by server"
79
- raise Faraday::ConnectionFailed, err
80
- else
81
- raise
110
+ status = client.response_header.status
111
+ reason = client.response_header.http_reason
112
+ save_response(env, status, client.response, nil, reason) do |headers|
113
+ client.response_header.each do |name, value|
114
+ headers[name.to_sym] = value
115
+ end
82
116
  end
83
- rescue => err
84
- if defined?(OpenSSL) && OpenSSL::SSL::SSLError === err
85
- raise Faraday::SSLError, err
117
+ end
118
+
119
+ def call_block(block)
120
+ client = nil
121
+
122
+ if EM.reactor_running?
123
+ client = block.call
86
124
  else
87
- raise
125
+ EM.run do
126
+ Fiber.new do
127
+ client = block.call
128
+ EM.stop
129
+ end.resume
130
+ end
88
131
  end
89
- end
90
132
 
91
- def create_request(env)
92
- EventMachine::HttpRequest.new(Utils::URI(env[:url].to_s), connection_config(env).merge(@connection_options))
133
+ client
93
134
  end
94
135
  end
95
136
  end
@@ -97,10 +138,13 @@ end
97
138
 
98
139
  require 'faraday/adapter/em_synchrony/parallel_manager'
99
140
 
100
- begin
101
- require 'openssl'
102
- rescue LoadError
103
- warn "Warning: no such file to load -- openssl. Make sure it is installed if you want HTTPS support"
104
- else
105
- require 'faraday/adapter/em_http_ssl_patch'
106
- end if Faraday::Adapter::EMSynchrony.loaded?
141
+ if Faraday::Adapter::EMSynchrony.loaded?
142
+ begin
143
+ require 'openssl'
144
+ rescue LoadError
145
+ warn 'Warning: no such file to load -- openssl. ' \
146
+ 'Make sure it is installed if you want HTTPS support'
147
+ else
148
+ require 'faraday/adapter/em_http_ssl_patch'
149
+ end
150
+ end
@@ -1,81 +1,123 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Faraday
2
4
  class Adapter
5
+ # Excon adapter.
3
6
  class Excon < Faraday::Adapter
4
7
  dependency 'excon'
5
8
 
9
+ def build_connection(env)
10
+ opts = opts_from_env(env)
11
+ ::Excon.new(env[:url].to_s, opts.merge(@connection_options))
12
+ end
13
+
6
14
  def call(env)
7
15
  super
8
16
 
9
- opts = {}
10
- if env[:url].scheme == 'https' && ssl = env[:ssl]
11
- opts[:ssl_verify_peer] = !!ssl.fetch(:verify, true)
12
- opts[:ssl_ca_path] = ssl[:ca_path] if ssl[:ca_path]
13
- opts[:ssl_ca_file] = ssl[:ca_file] if ssl[:ca_file]
14
- opts[:client_cert] = ssl[:client_cert] if ssl[:client_cert]
15
- opts[:client_key] = ssl[:client_key] if ssl[:client_key]
16
- opts[:certificate] = ssl[:certificate] if ssl[:certificate]
17
- opts[:private_key] = ssl[:private_key] if ssl[:private_key]
18
- opts[:ssl_version] = ssl[:version] if ssl[:version]
19
- opts[:ssl_min_version] = ssl[:min_version] if ssl[:min_version]
20
- opts[:ssl_max_version] = ssl[:max_version] if ssl[:max_version]
21
-
22
- # https://github.com/geemus/excon/issues/106
23
- # https://github.com/jruby/jruby-ossl/issues/19
24
- opts[:nonblock] = false
25
- end
17
+ req_opts = {
18
+ method: env[:method].to_s.upcase,
19
+ headers: env[:request_headers],
20
+ body: read_body(env)
21
+ }
26
22
 
27
- if ( req = env[:request] )
28
- if req[:timeout]
29
- opts[:read_timeout] = req[:timeout]
30
- opts[:connect_timeout] = req[:timeout]
31
- opts[:write_timeout] = req[:timeout]
23
+ req = env[:request]
24
+ if req&.stream_response?
25
+ total = 0
26
+ req_opts[:response_block] = lambda do |chunk, _remain, _total|
27
+ req.on_data.call(chunk, total += chunk.size)
32
28
  end
29
+ end
33
30
 
34
- if req[:open_timeout]
35
- opts[:connect_timeout] = req[:open_timeout]
36
- end
31
+ resp = connection(env) { |http| http.request(req_opts) }
32
+ save_response(env, resp.status.to_i, resp.body, resp.headers,
33
+ resp.reason_phrase)
37
34
 
38
- if req[:proxy]
39
- opts[:proxy] = {
40
- :host => req[:proxy][:uri].host,
41
- :hostname => req[:proxy][:uri].hostname,
42
- :port => req[:proxy][:uri].port,
43
- :scheme => req[:proxy][:uri].scheme,
44
- :user => req[:proxy][:user],
45
- :password => req[:proxy][:password]
46
- }
47
- end
35
+ @app.call(env)
36
+ rescue ::Excon::Errors::SocketError => e
37
+ raise Faraday::TimeoutError, e if e.message =~ /\btimeout\b/
38
+
39
+ raise Faraday::SSLError, e if e.message =~ /\bcertificate\b/
40
+
41
+ raise Faraday::ConnectionFailed, e
42
+ rescue ::Excon::Errors::Timeout => e
43
+ raise Faraday::TimeoutError, e
44
+ end
45
+
46
+ # TODO: support streaming requests
47
+ def read_body(env)
48
+ env[:body].respond_to?(:read) ? env[:body].read : env[:body]
49
+ end
50
+
51
+ private
52
+
53
+ def opts_from_env(env)
54
+ opts = {}
55
+ amend_opts_with_ssl!(opts, env[:ssl]) if needs_ssl_settings?(env)
56
+
57
+ if (req = env[:request])
58
+ amend_opts_with_timeouts!(opts, req)
59
+ amend_opts_with_proxy_settings!(opts, req)
48
60
  end
49
61
 
50
- conn = create_connection(env, opts)
62
+ opts
63
+ end
51
64
 
52
- resp = conn.request \
53
- :method => env[:method].to_s.upcase,
54
- :headers => env[:request_headers],
55
- :body => read_body(env)
65
+ def needs_ssl_settings?(env)
66
+ env[:url].scheme == 'https' && env[:ssl]
67
+ end
56
68
 
57
- save_response(env, resp.status.to_i, resp.body, resp.headers, resp.reason_phrase)
69
+ OPTS_KEYS = [
70
+ %i[client_cert client_cert],
71
+ %i[client_key client_key],
72
+ %i[certificate certificate],
73
+ %i[private_key private_key],
74
+ %i[ssl_ca_path ca_path],
75
+ %i[ssl_ca_file ca_file],
76
+ %i[ssl_version version],
77
+ %i[ssl_min_version min_version],
78
+ %i[ssl_max_version max_version]
79
+ ].freeze
58
80
 
59
- @app.call env
60
- rescue ::Excon::Errors::SocketError => err
61
- if err.message =~ /\btimeout\b/
62
- raise Faraday::TimeoutError, err
63
- elsif err.message =~ /\bcertificate\b/
64
- raise Faraday::SSLError, err
65
- else
66
- raise Faraday::ConnectionFailed, err
81
+ def amend_opts_with_ssl!(opts, ssl)
82
+ opts[:ssl_verify_peer] = !!ssl.fetch(:verify, true)
83
+ # https://github.com/geemus/excon/issues/106
84
+ # https://github.com/jruby/jruby-ossl/issues/19
85
+ opts[:nonblock] = false
86
+
87
+ OPTS_KEYS.each do |(key_in_opts, key_in_ssl)|
88
+ next unless ssl[key_in_ssl]
89
+
90
+ opts[key_in_opts] = ssl[key_in_ssl]
67
91
  end
68
- rescue ::Excon::Errors::Timeout => err
69
- raise Faraday::TimeoutError, err
70
92
  end
71
93
 
72
- def create_connection(env, opts)
73
- ::Excon.new(env[:url].to_s, opts.merge(@connection_options))
94
+ def amend_opts_with_timeouts!(opts, req)
95
+ if (sec = request_timeout(:read, req))
96
+ opts[:read_timeout] = sec
97
+ end
98
+
99
+ if (sec = request_timeout(:write, req))
100
+ opts[:write_timeout] = sec
101
+ end
102
+
103
+ return unless (sec = request_timeout(:open, req))
104
+
105
+ opts[:connect_timeout] = sec
74
106
  end
75
107
 
76
- # TODO: support streaming requests
77
- def read_body(env)
78
- env[:body].respond_to?(:read) ? env[:body].read : env[:body]
108
+ def amend_opts_with_proxy_settings!(opts, req)
109
+ opts[:proxy] = proxy_settings_for_opts(req[:proxy]) if req[:proxy]
110
+ end
111
+
112
+ def proxy_settings_for_opts(proxy)
113
+ {
114
+ host: proxy[:uri].host,
115
+ hostname: proxy[:uri].hostname,
116
+ port: proxy[:uri].port,
117
+ scheme: proxy[:uri].scheme,
118
+ user: proxy[:user],
119
+ password: proxy[:password]
120
+ }
79
121
  end
80
122
  end
81
123
  end
@@ -1,78 +1,96 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Faraday
2
4
  class Adapter
5
+ # HTTPClient adapter.
3
6
  class HTTPClient < Faraday::Adapter
4
7
  dependency 'httpclient'
5
8
 
6
- def client
7
- @client ||= ::HTTPClient.new
8
- end
9
-
10
- def call(env)
11
- super
12
-
13
- # enable compression
14
- client.transparent_gzip_decompression = true
9
+ def build_connection(env)
10
+ @client ||= ::HTTPClient.new.tap do |cli|
11
+ # enable compression
12
+ cli.transparent_gzip_decompression = true
13
+ end
15
14
 
16
- if req = env[:request]
17
- if proxy = req[:proxy]
18
- configure_proxy proxy
15
+ if (req = env[:request])
16
+ if (proxy = req[:proxy])
17
+ configure_proxy @client, proxy
19
18
  end
20
19
 
21
- if bind = req[:bind]
22
- configure_socket bind
20
+ if (bind = req[:bind])
21
+ configure_socket @client, bind
23
22
  end
24
23
 
25
- configure_timeouts req
24
+ configure_timeouts @client, req
26
25
  end
27
26
 
28
- if env[:url].scheme == 'https' && ssl = env[:ssl]
29
- configure_ssl ssl
27
+ if env[:url].scheme == 'https' && (ssl = env[:ssl])
28
+ configure_ssl @client, ssl
30
29
  end
31
30
 
32
- configure_client
31
+ configure_client @client
32
+
33
+ @client
34
+ end
33
35
 
34
- # TODO Don't stream yet.
36
+ def call(env)
37
+ super
38
+
39
+ # TODO: Don't stream yet.
35
40
  # https://github.com/nahi/httpclient/pull/90
36
41
  env[:body] = env[:body].read if env[:body].respond_to? :read
37
42
 
38
- resp = client.request env[:method], env[:url],
39
- :body => env[:body],
40
- :header => env[:request_headers]
43
+ connection(env) do |http|
44
+ resp = http.request env[:method], env[:url],
45
+ body: env[:body],
46
+ header: env[:request_headers]
41
47
 
42
- save_response env, resp.status, resp.body, resp.headers, resp.reason
48
+ if (req = env[:request]).stream_response?
49
+ warn "Streaming downloads for #{self.class.name} " \
50
+ 'are not yet implemented.'
51
+ req.on_data.call(resp.body, resp.body.bytesize)
52
+ end
53
+ save_response env, resp.status, resp.body, resp.headers, resp.reason
43
54
 
44
- @app.call env
55
+ @app.call env
56
+ end
45
57
  rescue ::HTTPClient::TimeoutError, Errno::ETIMEDOUT
46
- raise Faraday::TimeoutError, $!
47
- rescue ::HTTPClient::BadResponseError => err
48
- if err.message.include?('status 407')
49
- raise Faraday::ConnectionFailed, %{407 "Proxy Authentication Required "}
50
- else
51
- raise Faraday::ClientError, $!
58
+ raise Faraday::TimeoutError, $ERROR_INFO
59
+ rescue ::HTTPClient::BadResponseError => e
60
+ if e.message.include?('status 407')
61
+ raise Faraday::ConnectionFailed,
62
+ %(407 "Proxy Authentication Required ")
52
63
  end
53
- rescue Errno::ECONNREFUSED, IOError, SocketError
54
- raise Faraday::ConnectionFailed, $!
55
- rescue => err
56
- if defined?(OpenSSL) && OpenSSL::SSL::SSLError === err
57
- raise Faraday::SSLError, err
58
- else
59
- raise
64
+
65
+ raise Faraday::ClientError, $ERROR_INFO
66
+ rescue Errno::EADDRNOTAVAIL, Errno::ECONNREFUSED, IOError, SocketError
67
+ raise Faraday::ConnectionFailed, $ERROR_INFO
68
+ rescue StandardError => e
69
+ if defined?(OpenSSL) && e.is_a?(OpenSSL::SSL::SSLError)
70
+ raise Faraday::SSLError, e
60
71
  end
72
+
73
+ raise
61
74
  end
62
75
 
63
- def configure_socket(bind)
76
+ # @param bind [Hash]
77
+ def configure_socket(client, bind)
64
78
  client.socket_local.host = bind[:host]
65
79
  client.socket_local.port = bind[:port]
66
80
  end
67
81
 
68
- def configure_proxy(proxy)
82
+ # Configure proxy URI and any user credentials.
83
+ #
84
+ # @param proxy [Hash]
85
+ def configure_proxy(client, proxy)
69
86
  client.proxy = proxy[:uri]
70
- if proxy[:user] && proxy[:password]
71
- client.set_proxy_auth proxy[:user], proxy[:password]
72
- end
87
+ return unless proxy[:user] && proxy[:password]
88
+
89
+ client.set_proxy_auth(proxy[:user], proxy[:password])
73
90
  end
74
91
 
75
- def configure_ssl(ssl)
92
+ # @param ssl [Hash]
93
+ def configure_ssl(client, ssl)
76
94
  ssl_config = client.ssl_config
77
95
  ssl_config.verify_mode = ssl_verify_mode(ssl)
78
96
  ssl_config.cert_store = ssl_cert_store(ssl)
@@ -84,40 +102,45 @@ module Faraday
84
102
  ssl_config.verify_depth = ssl[:verify_depth] if ssl[:verify_depth]
85
103
  end
86
104
 
87
- def configure_timeouts(req)
88
- if req[:timeout]
89
- client.connect_timeout = req[:timeout]
90
- client.receive_timeout = req[:timeout]
91
- client.send_timeout = req[:timeout]
105
+ # @param req [Hash]
106
+ def configure_timeouts(client, req)
107
+ if (sec = request_timeout(:open, req))
108
+ client.connect_timeout = sec
92
109
  end
93
110
 
94
- if req[:open_timeout]
95
- client.connect_timeout = req[:open_timeout]
96
- client.send_timeout = req[:open_timeout]
111
+ if (sec = request_timeout(:write, req))
112
+ client.send_timeout = sec
97
113
  end
114
+
115
+ return unless (sec = request_timeout(:read, req))
116
+
117
+ client.receive_timeout = sec
98
118
  end
99
119
 
100
- def configure_client
101
- @config_block.call(client) if @config_block
120
+ def configure_client(client)
121
+ @config_block&.call(client)
102
122
  end
103
123
 
124
+ # @param ssl [Hash]
125
+ # @return [OpenSSL::X509::Store]
104
126
  def ssl_cert_store(ssl)
105
127
  return ssl[:cert_store] if ssl[:cert_store]
128
+
106
129
  # Memoize the cert store so that the same one is passed to
107
- # HTTPClient each time, to avoid resyncing SSL sesions when
130
+ # HTTPClient each time, to avoid resyncing SSL sessions when
108
131
  # it's changed
109
- @cert_store ||= begin
132
+ @ssl_cert_store ||= begin
110
133
  # Use the default cert store by default, i.e. system ca certs
111
- cert_store = OpenSSL::X509::Store.new
112
- cert_store.set_default_paths
113
- cert_store
134
+ OpenSSL::X509::Store.new.tap(&:set_default_paths)
114
135
  end
115
136
  end
116
137
 
138
+ # @param ssl [Hash]
117
139
  def ssl_verify_mode(ssl)
118
140
  ssl[:verify_mode] || begin
119
141
  if ssl.fetch(:verify, true)
120
- OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
142
+ OpenSSL::SSL::VERIFY_PEER |
143
+ OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
121
144
  else
122
145
  OpenSSL::SSL::VERIFY_NONE
123
146
  end