faraday 0.16.0 → 0.17.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 (54) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.md +1 -1
  3. data/README.md +347 -18
  4. data/lib/faraday/adapter/em_http.rb +99 -142
  5. data/lib/faraday/adapter/em_http_ssl_patch.rb +17 -23
  6. data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +15 -18
  7. data/lib/faraday/adapter/em_synchrony.rb +60 -104
  8. data/lib/faraday/adapter/excon.rb +55 -100
  9. data/lib/faraday/adapter/httpclient.rb +39 -61
  10. data/lib/faraday/adapter/net_http.rb +51 -104
  11. data/lib/faraday/adapter/net_http_persistent.rb +27 -48
  12. data/lib/faraday/adapter/patron.rb +35 -54
  13. data/lib/faraday/adapter/rack.rb +12 -28
  14. data/lib/faraday/adapter/test.rb +53 -86
  15. data/lib/faraday/adapter/typhoeus.rb +1 -4
  16. data/lib/faraday/adapter.rb +22 -36
  17. data/lib/faraday/autoload.rb +36 -47
  18. data/lib/faraday/connection.rb +179 -321
  19. data/lib/faraday/error.rb +33 -67
  20. data/lib/faraday/middleware.rb +28 -4
  21. data/lib/faraday/options.rb +186 -35
  22. data/lib/faraday/parameters.rb +197 -4
  23. data/lib/faraday/rack_builder.rb +56 -67
  24. data/lib/faraday/request/authorization.rb +30 -42
  25. data/lib/faraday/request/basic_authentication.rb +7 -14
  26. data/lib/faraday/request/instrumentation.rb +27 -45
  27. data/lib/faraday/request/multipart.rb +48 -79
  28. data/lib/faraday/request/retry.rb +170 -197
  29. data/lib/faraday/request/token_authentication.rb +10 -15
  30. data/lib/faraday/request/url_encoded.rb +23 -41
  31. data/lib/faraday/request.rb +36 -68
  32. data/lib/faraday/response/logger.rb +69 -22
  33. data/lib/faraday/response/raise_error.rb +14 -36
  34. data/lib/faraday/response.rb +16 -23
  35. data/lib/faraday/upload_io.rb +67 -0
  36. data/lib/faraday/utils.rb +245 -28
  37. data/lib/faraday.rb +175 -93
  38. metadata +5 -22
  39. data/lib/faraday/adapter_registry.rb +0 -28
  40. data/lib/faraday/dependency_loader.rb +0 -37
  41. data/lib/faraday/encoders/flat_params_encoder.rb +0 -94
  42. data/lib/faraday/encoders/nested_params_encoder.rb +0 -171
  43. data/lib/faraday/file_part.rb +0 -128
  44. data/lib/faraday/logging/formatter.rb +0 -92
  45. data/lib/faraday/middleware_registry.rb +0 -129
  46. data/lib/faraday/options/connection_options.rb +0 -22
  47. data/lib/faraday/options/env.rb +0 -181
  48. data/lib/faraday/options/proxy_options.rb +0 -28
  49. data/lib/faraday/options/request_options.rb +0 -21
  50. data/lib/faraday/options/ssl_options.rb +0 -59
  51. data/lib/faraday/param_part.rb +0 -53
  52. data/lib/faraday/utils/headers.rb +0 -139
  53. data/lib/faraday/utils/params_hash.rb +0 -61
  54. data/spec/external_adapters/faraday_specs_setup.rb +0 -14
@@ -1,10 +1,7 @@
1
- # frozen_string_literal: true
2
-
3
1
  require 'uri'
4
2
 
5
3
  module Faraday
6
4
  class Adapter
7
- # EventMachine Synchrony adapter.
8
5
  class EMSynchrony < Faraday::Adapter
9
6
  include EMHttp::Options
10
7
 
@@ -16,8 +13,7 @@ module Faraday
16
13
 
17
14
  self.supports_parallel = true
18
15
 
19
- # @return [ParallelManager]
20
- def self.setup_parallel_manager(_options = nil)
16
+ def self.setup_parallel_manager(options = {})
21
17
  ParallelManager.new
22
18
  end
23
19
 
@@ -27,110 +23,73 @@ module Faraday
27
23
 
28
24
  http_method = env[:method].to_s.downcase.to_sym
29
25
 
26
+ # Queue requests for parallel execution.
30
27
  if env[:parallel_manager]
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
37
-
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
46
-
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
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
72
34
 
73
- private
35
+ # Finalize the response object with values from `env`.
36
+ env[:response].finish(env)
37
+ end
74
38
 
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)
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
82
53
  end
83
54
 
84
- save_response(env, resp.response_header.status,
85
- resp.response) do |resp_headers|
86
- resp.response_header.each do |name, value|
55
+ raise client.error if client.error
56
+
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|
87
61
  resp_headers[name.to_sym] = value
88
62
  end
89
63
  end
90
-
91
- # Finalize the response object with values from `env`.
92
- env[:response].finish(env)
93
64
  end
94
- end
95
-
96
- def execute_single_request(env, request, http_method)
97
- block = -> { request.send(http_method, request_config(env)) }
98
- client = call_block(block)
99
65
 
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
- )
66
+ @app.call env
67
+ rescue Errno::ECONNREFUSED
68
+ raise Error::ConnectionFailed, $!
69
+ rescue EventMachine::Connectify::CONNECTError => err
70
+ if err.message.include?("Proxy Authentication Required")
71
+ raise Error::ConnectionFailed, %{407 "Proxy Authentication Required "}
72
+ else
73
+ raise Error::ConnectionFailed, err
109
74
  end
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
75
+ rescue Errno::ETIMEDOUT => err
76
+ raise Error::TimeoutError, err
77
+ rescue RuntimeError => err
78
+ if err.message == "connection closed by server"
79
+ raise Error::ConnectionFailed, err
80
+ else
81
+ raise
116
82
  end
117
- end
118
-
119
- def call_block(block)
120
- client = nil
121
-
122
- if EM.reactor_running?
123
- client = block.call
83
+ rescue => err
84
+ if defined?(OpenSSL) && OpenSSL::SSL::SSLError === err
85
+ raise Faraday::SSLError, err
124
86
  else
125
- EM.run do
126
- Fiber.new do
127
- client = block.call
128
- EM.stop
129
- end.resume
130
- end
87
+ raise
131
88
  end
89
+ end
132
90
 
133
- client
91
+ def create_request(env)
92
+ EventMachine::HttpRequest.new(Utils::URI(env[:url].to_s), connection_config(env).merge(@connection_options))
134
93
  end
135
94
  end
136
95
  end
@@ -138,13 +97,10 @@ end
138
97
 
139
98
  require 'faraday/adapter/em_synchrony/parallel_manager'
140
99
 
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
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?
@@ -1,47 +1,74 @@
1
- # frozen_string_literal: true
2
-
3
1
  module Faraday
4
2
  class Adapter
5
- # Excon adapter.
6
3
  class Excon < Faraday::Adapter
7
4
  dependency 'excon'
8
5
 
9
6
  def call(env)
10
7
  super
11
8
 
12
- opts = opts_from_env(env)
13
- conn = create_connection(env, opts)
14
-
15
- req_opts = {
16
- method: env[:method].to_s.upcase,
17
- headers: env[:request_headers],
18
- body: read_body(env)
19
- }
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
20
26
 
21
- req = env[:request]
22
- if req&.stream_response?
23
- total = 0
24
- req_opts[:response_block] = lambda do |chunk, _remain, _total|
25
- req.on_data.call(chunk, total += chunk.size)
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]
26
32
  end
27
- end
28
33
 
29
- resp = conn.request(req_opts)
30
- save_response(env, resp.status.to_i, resp.body, resp.headers,
31
- resp.reason_phrase)
34
+ if req[:open_timeout]
35
+ opts[:connect_timeout] = req[:open_timeout]
36
+ end
32
37
 
33
- @app.call(env)
34
- rescue ::Excon::Errors::SocketError => e
35
- raise Faraday::TimeoutError, e if e.message =~ /\btimeout\b/
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
48
+ end
36
49
 
37
- raise Faraday::SSLError, e if e.message =~ /\bcertificate\b/
50
+ conn = create_connection(env, opts)
38
51
 
39
- raise Faraday::ConnectionFailed, e
40
- rescue ::Excon::Errors::Timeout => e
41
- raise Faraday::TimeoutError, e
52
+ resp = conn.request \
53
+ :method => env[:method].to_s.upcase,
54
+ :headers => env[:request_headers],
55
+ :body => read_body(env)
56
+
57
+ save_response(env, resp.status.to_i, resp.body, resp.headers, resp.reason_phrase)
58
+
59
+ @app.call env
60
+ rescue ::Excon::Errors::SocketError => err
61
+ if err.message =~ /\btimeout\b/
62
+ raise Error::TimeoutError, err
63
+ elsif err.message =~ /\bcertificate\b/
64
+ raise Faraday::SSLError, err
65
+ else
66
+ raise Error::ConnectionFailed, err
67
+ end
68
+ rescue ::Excon::Errors::Timeout => err
69
+ raise Error::TimeoutError, err
42
70
  end
43
71
 
44
- # @return [Excon]
45
72
  def create_connection(env, opts)
46
73
  ::Excon.new(env[:url].to_s, opts.merge(@connection_options))
47
74
  end
@@ -50,78 +77,6 @@ module Faraday
50
77
  def read_body(env)
51
78
  env[:body].respond_to?(:read) ? env[:body].read : env[:body]
52
79
  end
53
-
54
- private
55
-
56
- def opts_from_env(env)
57
- opts = {}
58
- amend_opts_with_ssl!(opts, env[:ssl]) if needs_ssl_settings?(env)
59
-
60
- if (req = env[:request])
61
- amend_opts_with_timeouts!(opts, req)
62
- amend_opts_with_proxy_settings!(opts, req)
63
- end
64
-
65
- opts
66
- end
67
-
68
- def needs_ssl_settings?(env)
69
- env[:url].scheme == 'https' && env[:ssl]
70
- end
71
-
72
- OPTS_KEYS = [
73
- %i[client_cert client_cert],
74
- %i[client_key client_key],
75
- %i[certificate certificate],
76
- %i[private_key private_key],
77
- %i[ssl_ca_path ca_path],
78
- %i[ssl_ca_file ca_file],
79
- %i[ssl_version version],
80
- %i[ssl_min_version min_version],
81
- %i[ssl_max_version max_version]
82
- ].freeze
83
-
84
- def amend_opts_with_ssl!(opts, ssl)
85
- opts[:ssl_verify_peer] = !!ssl.fetch(:verify, true)
86
- # https://github.com/geemus/excon/issues/106
87
- # https://github.com/jruby/jruby-ossl/issues/19
88
- opts[:nonblock] = false
89
-
90
- OPTS_KEYS.each do |(key_in_opts, key_in_ssl)|
91
- next unless ssl[key_in_ssl]
92
-
93
- opts[key_in_opts] = ssl[key_in_ssl]
94
- end
95
- end
96
-
97
- def amend_opts_with_timeouts!(opts, req)
98
- timeout = req[:timeout]
99
- return unless timeout
100
-
101
- opts[:read_timeout] = timeout
102
- opts[:connect_timeout] = timeout
103
- opts[:write_timeout] = timeout
104
-
105
- open_timeout = req[:open_timeout]
106
- return unless open_timeout
107
-
108
- opts[:connect_timeout] = open_timeout
109
- end
110
-
111
- def amend_opts_with_proxy_settings!(opts, req)
112
- opts[:proxy] = proxy_settings_for_opts(req[:proxy]) if req[:proxy]
113
- end
114
-
115
- def proxy_settings_for_opts(proxy)
116
- {
117
- host: proxy[:uri].host,
118
- hostname: proxy[:uri].hostname,
119
- port: proxy[:uri].port,
120
- scheme: proxy[:uri].scheme,
121
- user: proxy[:user],
122
- password: proxy[:password]
123
- }
124
- end
125
80
  end
126
81
  end
127
82
  end
@@ -1,12 +1,8 @@
1
- # frozen_string_literal: true
2
-
3
1
  module Faraday
4
2
  class Adapter
5
- # HTTPClient adapter.
6
3
  class HTTPClient < Faraday::Adapter
7
4
  dependency 'httpclient'
8
5
 
9
- # @return [HTTPClient]
10
6
  def client
11
7
  @client ||= ::HTTPClient.new
12
8
  end
@@ -17,76 +13,65 @@ module Faraday
17
13
  # enable compression
18
14
  client.transparent_gzip_decompression = true
19
15
 
20
- if (req = env[:request])
21
- if (proxy = req[:proxy])
16
+ if req = env[:request]
17
+ if proxy = req[:proxy]
22
18
  configure_proxy proxy
23
19
  end
24
20
 
25
- if (bind = req[:bind])
21
+ if bind = req[:bind]
26
22
  configure_socket bind
27
23
  end
28
24
 
29
25
  configure_timeouts req
30
26
  end
31
27
 
32
- if env[:url].scheme == 'https' && (ssl = env[:ssl])
28
+ if env[:url].scheme == 'https' && ssl = env[:ssl]
33
29
  configure_ssl ssl
34
30
  end
35
31
 
36
32
  configure_client
37
33
 
38
- # TODO: Don't stream yet.
34
+ # TODO Don't stream yet.
39
35
  # https://github.com/nahi/httpclient/pull/90
40
36
  env[:body] = env[:body].read if env[:body].respond_to? :read
41
37
 
42
38
  resp = client.request env[:method], env[:url],
43
- body: env[:body],
44
- header: env[:request_headers]
39
+ :body => env[:body],
40
+ :header => env[:request_headers]
45
41
 
46
- if (req = env[:request]).stream_response?
47
- warn "Streaming downloads for #{self.class.name} " \
48
- 'are not yet implemented.'
49
- req.on_data.call(resp.body, resp.body.bytesize)
50
- end
51
42
  save_response env, resp.status, resp.body, resp.headers, resp.reason
52
43
 
53
44
  @app.call env
54
45
  rescue ::HTTPClient::TimeoutError, Errno::ETIMEDOUT
55
- raise Faraday::TimeoutError, $ERROR_INFO
56
- rescue ::HTTPClient::BadResponseError => e
57
- if e.message.include?('status 407')
58
- raise Faraday::ConnectionFailed,
59
- %(407 "Proxy Authentication Required ")
46
+ raise Faraday::Error::TimeoutError, $!
47
+ rescue ::HTTPClient::BadResponseError => err
48
+ if err.message.include?('status 407')
49
+ raise Faraday::Error::ConnectionFailed, %{407 "Proxy Authentication Required "}
50
+ else
51
+ raise Faraday::Error::ClientError, $!
60
52
  end
61
-
62
- raise Faraday::ClientError, $ERROR_INFO
63
- rescue Errno::EADDRNOTAVAIL, Errno::ECONNREFUSED, IOError, SocketError
64
- raise Faraday::ConnectionFailed, $ERROR_INFO
65
- rescue StandardError => e
66
- if defined?(OpenSSL) && e.is_a?(OpenSSL::SSL::SSLError)
67
- raise Faraday::SSLError, e
53
+ rescue Errno::ECONNREFUSED, IOError, SocketError
54
+ raise Faraday::Error::ConnectionFailed, $!
55
+ rescue => err
56
+ if defined?(OpenSSL) && OpenSSL::SSL::SSLError === err
57
+ raise Faraday::SSLError, err
58
+ else
59
+ raise
68
60
  end
69
-
70
- raise
71
61
  end
72
62
 
73
- # @param bind [Hash]
74
63
  def configure_socket(bind)
75
64
  client.socket_local.host = bind[:host]
76
65
  client.socket_local.port = bind[:port]
77
66
  end
78
67
 
79
- # Configure proxy URI and any user credentials.
80
- #
81
- # @param proxy [Hash]
82
68
  def configure_proxy(proxy)
83
69
  client.proxy = proxy[:uri]
84
- return unless proxy[:user] && proxy[:password]
85
-
86
- client.set_proxy_auth(proxy[:user], proxy[:password])
70
+ if proxy[:user] && proxy[:password]
71
+ client.set_proxy_auth proxy[:user], proxy[:password]
72
+ end
87
73
  end
88
74
 
89
- # @param ssl [Hash]
90
75
  def configure_ssl(ssl)
91
76
  ssl_config = client.ssl_config
92
77
  ssl_config.verify_mode = ssl_verify_mode(ssl)
@@ -99,47 +84,40 @@ module Faraday
99
84
  ssl_config.verify_depth = ssl[:verify_depth] if ssl[:verify_depth]
100
85
  end
101
86
 
102
- # @param req [Hash]
103
87
  def configure_timeouts(req)
104
- configure_timeout(req) if req[:timeout]
105
- configure_open_timeout(req) if req[:open_timeout]
106
- end
107
-
108
- def configure_timeout(req)
109
- client.connect_timeout = req[:timeout]
110
- client.receive_timeout = req[:timeout]
111
- client.send_timeout = req[:timeout]
112
- end
88
+ if req[:timeout]
89
+ client.connect_timeout = req[:timeout]
90
+ client.receive_timeout = req[:timeout]
91
+ client.send_timeout = req[:timeout]
92
+ end
113
93
 
114
- def configure_open_timeout(req)
115
- client.connect_timeout = req[:open_timeout]
116
- client.send_timeout = req[:open_timeout]
94
+ if req[:open_timeout]
95
+ client.connect_timeout = req[:open_timeout]
96
+ client.send_timeout = req[:open_timeout]
97
+ end
117
98
  end
118
99
 
119
100
  def configure_client
120
- @config_block&.call(client)
101
+ @config_block.call(client) if @config_block
121
102
  end
122
103
 
123
- # @param ssl [Hash]
124
- # @return [OpenSSL::X509::Store]
125
104
  def ssl_cert_store(ssl)
126
105
  return ssl[:cert_store] if ssl[:cert_store]
127
-
128
106
  # Memoize the cert store so that the same one is passed to
129
- # HTTPClient each time, to avoid resyncing SSL sessions when
107
+ # HTTPClient each time, to avoid resyncing SSL sesions when
130
108
  # it's changed
131
- @ssl_cert_store ||= begin
109
+ @cert_store ||= begin
132
110
  # Use the default cert store by default, i.e. system ca certs
133
- OpenSSL::X509::Store.new.tap(&:set_default_paths)
111
+ cert_store = OpenSSL::X509::Store.new
112
+ cert_store.set_default_paths
113
+ cert_store
134
114
  end
135
115
  end
136
116
 
137
- # @param ssl [Hash]
138
117
  def ssl_verify_mode(ssl)
139
118
  ssl[:verify_mode] || begin
140
119
  if ssl.fetch(:verify, true)
141
- OpenSSL::SSL::VERIFY_PEER |
142
- OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
120
+ OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
143
121
  else
144
122
  OpenSSL::SSL::VERIFY_NONE
145
123
  end