faraday 1.2.0 → 1.4.2

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.
@@ -1,153 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'uri'
4
-
5
- module Faraday
6
- class Adapter
7
- # EventMachine Synchrony adapter.
8
- class EMSynchrony < Faraday::Adapter
9
- include EMHttp::Options
10
-
11
- dependency do
12
- require 'em-synchrony/em-http'
13
- require 'em-synchrony/em-multi'
14
- require 'fiber'
15
-
16
- require 'faraday/adapter/em_synchrony/parallel_manager'
17
-
18
- if Faraday::Adapter::EMSynchrony.loaded?
19
- begin
20
- require 'openssl'
21
- rescue LoadError
22
- warn 'Warning: no such file to load -- openssl. ' \
23
- 'Make sure it is installed if you want HTTPS support'
24
- else
25
- require 'em-http/version'
26
- if EventMachine::HttpRequest::VERSION < '1.1.6'
27
- require 'faraday/adapter/em_http_ssl_patch'
28
- end
29
- end
30
- end
31
- end
32
-
33
- self.supports_parallel = true
34
-
35
- # @return [ParallelManager]
36
- def self.setup_parallel_manager(_options = nil)
37
- ParallelManager.new
38
- end
39
-
40
- def call(env)
41
- super
42
- request = create_request(env)
43
-
44
- http_method = env[:method].to_s.downcase.to_sym
45
-
46
- if env[:parallel_manager]
47
- # Queue requests for parallel execution.
48
- execute_parallel_request(env, request, http_method)
49
- else
50
- # Execute single request.
51
- execute_single_request(env, request, http_method)
52
- end
53
-
54
- @app.call env
55
- rescue Errno::ECONNREFUSED
56
- raise Faraday::ConnectionFailed, $ERROR_INFO
57
- rescue EventMachine::Connectify::CONNECTError => e
58
- if e.message.include?('Proxy Authentication Required')
59
- raise Faraday::ConnectionFailed,
60
- %(407 "Proxy Authentication Required")
61
- end
62
-
63
- raise Faraday::ConnectionFailed, e
64
- rescue Errno::ETIMEDOUT => e
65
- raise Faraday::TimeoutError, e
66
- rescue RuntimeError => e
67
- if e.message == 'connection closed by server'
68
- raise Faraday::ConnectionFailed, e
69
- end
70
-
71
- raise Faraday::TimeoutError, e if e.message.include?('timeout error')
72
-
73
- raise
74
- rescue StandardError => e
75
- if defined?(OpenSSL) && e.is_a?(OpenSSL::SSL::SSLError)
76
- raise Faraday::SSLError, e
77
- end
78
-
79
- raise
80
- end
81
-
82
- def create_request(env)
83
- EventMachine::HttpRequest.new(
84
- Utils::URI(env[:url].to_s),
85
- connection_config(env).merge(@connection_options)
86
- )
87
- end
88
-
89
- private
90
-
91
- def execute_parallel_request(env, request, http_method)
92
- env[:parallel_manager].add(request, http_method,
93
- request_config(env)) do |resp|
94
- if (req = env[:request]).stream_response?
95
- warn "Streaming downloads for #{self.class.name} " \
96
- 'are not yet implemented.'
97
- req.on_data.call(resp.response, resp.response.bytesize)
98
- end
99
-
100
- save_response(env, resp.response_header.status,
101
- resp.response) do |resp_headers|
102
- resp.response_header.each do |name, value|
103
- resp_headers[name.to_sym] = value
104
- end
105
- end
106
-
107
- # Finalize the response object with values from `env`.
108
- env[:response].finish(env)
109
- end
110
- end
111
-
112
- def execute_single_request(env, request, http_method)
113
- block = -> { request.send(http_method, request_config(env)) }
114
- client = call_block(block)
115
-
116
- raise client.error if client&.error
117
-
118
- if env[:request].stream_response?
119
- warn "Streaming downloads for #{self.class.name} " \
120
- 'are not yet implemented.'
121
- env[:request].on_data.call(
122
- client.response,
123
- client.response.bytesize
124
- )
125
- end
126
- status = client.response_header.status
127
- reason = client.response_header.http_reason
128
- save_response(env, status, client.response, nil, reason) do |headers|
129
- client.response_header.each do |name, value|
130
- headers[name.to_sym] = value
131
- end
132
- end
133
- end
134
-
135
- def call_block(block)
136
- client = nil
137
-
138
- if EM.reactor_running?
139
- client = block.call
140
- else
141
- EM.run do
142
- Fiber.new do
143
- client = block.call
144
- EM.stop
145
- end.resume
146
- end
147
- end
148
-
149
- client
150
- end
151
- end
152
- end
153
- end
@@ -1,69 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Faraday
4
- class Adapter
5
- class EMSynchrony < Faraday::Adapter
6
- # A parallel manager for EMSynchrony.
7
- class ParallelManager
8
- # Add requests to queue.
9
- #
10
- # @param request [EM::HttpRequest]
11
- # @param method [Symbol, String] HTTP method
12
- # @param args [Array] the rest of the positional arguments
13
- def add(request, method, *args, &block)
14
- queue << {
15
- request: request,
16
- method: method,
17
- args: args,
18
- block: block
19
- }
20
- end
21
-
22
- # Run all requests on queue with `EM::Synchrony::Multi`, wrapping
23
- # it in a reactor and fiber if needed.
24
- def run
25
- result = nil
26
- if !EM.reactor_running?
27
- EM.run do
28
- Fiber.new do
29
- result = perform
30
- EM.stop
31
- end.resume
32
- end
33
- else
34
- result = perform
35
- end
36
- result
37
- end
38
-
39
- private
40
-
41
- # The request queue.
42
- def queue
43
- @queue ||= []
44
- end
45
-
46
- # Main `EM::Synchrony::Multi` performer.
47
- def perform
48
- multi = ::EM::Synchrony::Multi.new
49
-
50
- queue.each do |item|
51
- method = "a#{item[:method]}".to_sym
52
-
53
- req = item[:request].send(method, *item[:args])
54
- req.callback(&item[:block])
55
-
56
- req_name = "req_#{multi.requests.size}".to_sym
57
- multi.add(req_name, req)
58
- end
59
-
60
- # Clear the queue, so parallel manager objects can be reused.
61
- @queue = []
62
-
63
- # Block fiber until all requests have returned.
64
- multi.perform
65
- end
66
- end
67
- end
68
- end
69
- end
@@ -1,124 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Faraday
4
- class Adapter
5
- # Excon adapter.
6
- class Excon < Faraday::Adapter
7
- dependency 'excon'
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
-
14
- def call(env)
15
- super
16
-
17
- req_opts = {
18
- method: env[:method].to_s.upcase,
19
- headers: env[:request_headers],
20
- body: read_body(env)
21
- }
22
-
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)
28
- end
29
- end
30
-
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)
34
-
35
- @app.call(env)
36
- rescue ::Excon::Errors::SocketError => e
37
- raise Faraday::TimeoutError, e if e.message.match?(/\btimeout\b/)
38
-
39
- raise Faraday::SSLError, e if e.message.match?(/\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)
60
- end
61
-
62
- opts
63
- end
64
-
65
- def needs_ssl_settings?(env)
66
- env[:url].scheme == 'https' && env[:ssl]
67
- end
68
-
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
80
-
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]
91
- end
92
- end
93
-
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
106
- end
107
-
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
- }
121
- end
122
- end
123
- end
124
- end
@@ -1,220 +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
- if defined?(::OpenSSL::SSL::SSLError)
34
- exceptions << ::OpenSSL::SSL::SSLError
35
- end
36
- exceptions << ::Net::OpenTimeout if defined?(::Net::OpenTimeout)
37
-
38
- NET_HTTP_EXCEPTIONS = exceptions.freeze
39
-
40
- def initialize(app = nil, opts = {}, &block)
41
- @ssl_cert_store = nil
42
- super(app, opts, &block)
43
- end
44
-
45
- def build_connection(env)
46
- net_http_connection(env).tap do |http|
47
- if http.respond_to?(:use_ssl=)
48
- http.use_ssl = env[:url].scheme == 'https'
49
- end
50
- configure_ssl(http, env[:ssl])
51
- configure_request(http, env[:request])
52
- end
53
- end
54
-
55
- def net_http_connection(env)
56
- proxy = env[:request][:proxy]
57
- port = env[:url].port || (env[:url].scheme == 'https' ? 443 : 80)
58
- if proxy
59
- Net::HTTP.new(env[:url].hostname, port,
60
- proxy[:uri].hostname, proxy[:uri].port,
61
- proxy[:user], proxy[:password])
62
- else
63
- Net::HTTP.new(env[:url].hostname, port, nil)
64
- end
65
- end
66
-
67
- def call(env)
68
- super
69
- http_response = connection(env) do |http|
70
- begin
71
- perform_request(http, env)
72
- rescue *NET_HTTP_EXCEPTIONS => e
73
- if defined?(OpenSSL) && e.is_a?(OpenSSL::SSL::SSLError)
74
- raise Faraday::SSLError, e
75
- end
76
-
77
- raise Faraday::ConnectionFailed, e
78
- end
79
- end
80
-
81
- save_response(env, http_response.code.to_i,
82
- http_response.body || +'', nil,
83
- http_response.message) do |response_headers|
84
- http_response.each_header do |key, value|
85
- response_headers[key] = value
86
- end
87
- end
88
-
89
- @app.call env
90
- rescue Timeout::Error, Errno::ETIMEDOUT => e
91
- raise Faraday::TimeoutError, e
92
- end
93
-
94
- private
95
-
96
- def create_request(env)
97
- request = Net::HTTPGenericRequest.new \
98
- env[:method].to_s.upcase, # request method
99
- !!env[:body], # is there request body
100
- env[:method] != :head, # is there response body
101
- env[:url].request_uri, # request uri path
102
- env[:request_headers] # request headers
103
-
104
- if env[:body].respond_to?(:read)
105
- request.body_stream = env[:body]
106
- else
107
- request.body = env[:body]
108
- end
109
- request
110
- end
111
-
112
- def perform_request(http, env)
113
- if env[:request].stream_response?
114
- size = 0
115
- yielded = false
116
- http_response = request_with_wrapped_block(http, env) do |chunk|
117
- if chunk.bytesize.positive? || size.positive?
118
- yielded = true
119
- size += chunk.bytesize
120
- env[:request].on_data.call(chunk, size)
121
- end
122
- end
123
- env[:request].on_data.call(+'', 0) unless yielded
124
- # Net::HTTP returns something,
125
- # but it's not meaningful according to the docs.
126
- http_response.body = nil
127
- http_response
128
- else
129
- request_with_wrapped_block(http, env)
130
- end
131
- end
132
-
133
- def request_with_wrapped_block(http, env, &block)
134
- if (env[:method] == :get) && !env[:body]
135
- # prefer `get` to `request` because the former handles gzip (ruby 1.9)
136
- request_via_get_method(http, env, &block)
137
- else
138
- request_via_request_method(http, env, &block)
139
- end
140
- end
141
-
142
- def request_via_get_method(http, env, &block)
143
- # Must use Net::HTTP#start and pass it a block otherwise the server's
144
- # TCP socket does not close correctly.
145
- http.start do |opened_http|
146
- opened_http.get env[:url].request_uri, env[:request_headers], &block
147
- end
148
- end
149
-
150
- def request_via_request_method(http, env, &block)
151
- # Must use Net::HTTP#start and pass it a block otherwise the server's
152
- # TCP socket does not close correctly.
153
- http.start do |opened_http|
154
- if block_given?
155
- opened_http.request create_request(env) do |response|
156
- response.read_body(&block)
157
- end
158
- else
159
- opened_http.request create_request(env)
160
- end
161
- end
162
- end
163
-
164
- def configure_ssl(http, ssl)
165
- return unless ssl
166
-
167
- http.verify_mode = ssl_verify_mode(ssl)
168
- http.cert_store = ssl_cert_store(ssl)
169
-
170
- http.cert = ssl[:client_cert] if ssl[:client_cert]
171
- http.key = ssl[:client_key] if ssl[:client_key]
172
- http.ca_file = ssl[:ca_file] if ssl[:ca_file]
173
- http.ca_path = ssl[:ca_path] if ssl[:ca_path]
174
- http.verify_depth = ssl[:verify_depth] if ssl[:verify_depth]
175
- http.ssl_version = ssl[:version] if ssl[:version]
176
- http.min_version = ssl[:min_version] if ssl[:min_version]
177
- http.max_version = ssl[:max_version] if ssl[:max_version]
178
- end
179
-
180
- def configure_request(http, req)
181
- if (sec = request_timeout(:read, req))
182
- http.read_timeout = sec
183
- end
184
-
185
- if (sec = http.respond_to?(:write_timeout=) &&
186
- request_timeout(:write, req))
187
- http.write_timeout = sec
188
- end
189
-
190
- if (sec = request_timeout(:open, req))
191
- http.open_timeout = sec
192
- end
193
-
194
- # Only set if Net::Http supports it, since Ruby 2.5.
195
- http.max_retries = 0 if http.respond_to?(:max_retries=)
196
-
197
- @config_block&.call(http)
198
- end
199
-
200
- def ssl_cert_store(ssl)
201
- return ssl[:cert_store] if ssl[:cert_store]
202
-
203
- @ssl_cert_store ||= begin
204
- # Use the default cert store by default, i.e. system ca certs
205
- OpenSSL::X509::Store.new.tap(&:set_default_paths)
206
- end
207
- end
208
-
209
- def ssl_verify_mode(ssl)
210
- ssl[:verify_mode] || begin
211
- if ssl.fetch(:verify, true)
212
- OpenSSL::SSL::VERIFY_PEER
213
- else
214
- OpenSSL::SSL::VERIFY_NONE
215
- end
216
- end
217
- end
218
- end
219
- end
220
- end