faraday 1.0.1 → 1.10.3

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 (68) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +104 -0
  3. data/LICENSE.md +1 -1
  4. data/README.md +3 -5
  5. data/examples/client_spec.rb +35 -3
  6. data/examples/client_test.rb +41 -2
  7. data/lib/faraday/adapter/test.rb +59 -43
  8. data/lib/faraday/adapter.rb +2 -12
  9. data/lib/faraday/autoload.rb +2 -10
  10. data/lib/faraday/connection.rb +37 -9
  11. data/lib/faraday/dependency_loader.rb +3 -1
  12. data/lib/faraday/deprecate.rb +110 -0
  13. data/lib/faraday/encoders/flat_params_encoder.rb +9 -2
  14. data/lib/faraday/encoders/nested_params_encoder.rb +7 -2
  15. data/lib/faraday/error.rb +20 -6
  16. data/lib/faraday/methods.rb +6 -0
  17. data/lib/faraday/middleware.rb +14 -4
  18. data/lib/faraday/options/proxy_options.rb +4 -0
  19. data/lib/faraday/options.rb +4 -8
  20. data/lib/faraday/rack_builder.rb +13 -12
  21. data/lib/faraday/request/authorization.rb +14 -7
  22. data/lib/faraday/request/json.rb +55 -0
  23. data/lib/faraday/request.rb +19 -11
  24. data/lib/faraday/response/json.rb +54 -0
  25. data/lib/faraday/response/logger.rb +2 -4
  26. data/lib/faraday/response/raise_error.rb +12 -1
  27. data/lib/faraday/response.rb +3 -7
  28. data/lib/faraday/utils/headers.rb +2 -2
  29. data/lib/faraday/utils.rb +2 -2
  30. data/lib/faraday/version.rb +5 -0
  31. data/lib/faraday.rb +67 -40
  32. data/spec/faraday/adapter/em_http_spec.rb +39 -37
  33. data/spec/faraday/adapter/em_synchrony_spec.rb +11 -9
  34. data/spec/faraday/adapter/test_spec.rb +377 -0
  35. data/spec/faraday/connection_spec.rb +45 -0
  36. data/spec/faraday/deprecate_spec.rb +147 -0
  37. data/spec/faraday/error_spec.rb +15 -0
  38. data/spec/faraday/middleware_spec.rb +32 -6
  39. data/spec/faraday/options/proxy_options_spec.rb +7 -0
  40. data/spec/faraday/params_encoders/flat_spec.rb +8 -0
  41. data/spec/faraday/params_encoders/nested_spec.rb +8 -0
  42. data/spec/faraday/rack_builder_spec.rb +149 -0
  43. data/spec/faraday/request/authorization_spec.rb +10 -2
  44. data/spec/faraday/request/json_spec.rb +111 -0
  45. data/spec/faraday/request_spec.rb +16 -5
  46. data/spec/faraday/response/json_spec.rb +119 -0
  47. data/spec/faraday/response/raise_error_spec.rb +63 -0
  48. data/spec/spec_helper.rb +2 -0
  49. data/spec/support/shared_examples/adapter.rb +2 -1
  50. data/spec/support/shared_examples/request_method.rb +39 -11
  51. metadata +156 -30
  52. data/lib/faraday/adapter/em_http.rb +0 -286
  53. data/lib/faraday/adapter/em_http_ssl_patch.rb +0 -62
  54. data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +0 -69
  55. data/lib/faraday/adapter/em_synchrony.rb +0 -150
  56. data/lib/faraday/adapter/excon.rb +0 -124
  57. data/lib/faraday/adapter/httpclient.rb +0 -152
  58. data/lib/faraday/adapter/net_http.rb +0 -219
  59. data/lib/faraday/adapter/net_http_persistent.rb +0 -91
  60. data/lib/faraday/adapter/patron.rb +0 -132
  61. data/lib/faraday/adapter/rack.rb +0 -75
  62. data/lib/faraday/file_part.rb +0 -128
  63. data/lib/faraday/param_part.rb +0 -53
  64. data/lib/faraday/request/multipart.rb +0 -99
  65. data/lib/faraday/request/retry.rb +0 -239
  66. data/spec/faraday/adapter/net_http_persistent_spec.rb +0 -57
  67. data/spec/faraday/request/multipart_spec.rb +0 -274
  68. data/spec/faraday/request/retry_spec.rb +0 -242
@@ -1,219 +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
- klass = if (proxy = env[:request][:proxy])
57
- Net::HTTP::Proxy(proxy[:uri].hostname, proxy[:uri].port,
58
- proxy[:user], proxy[:password])
59
- else
60
- Net::HTTP
61
- end
62
- port = env[:url].port || (env[:url].scheme == 'https' ? 443 : 80)
63
- klass.new(env[:url].hostname, port)
64
- end
65
-
66
- def call(env)
67
- super
68
- http_response = connection(env) do |http|
69
- begin
70
- perform_request(http, env)
71
- rescue *NET_HTTP_EXCEPTIONS => e
72
- if defined?(OpenSSL) && e.is_a?(OpenSSL::SSL::SSLError)
73
- raise Faraday::SSLError, e
74
- end
75
-
76
- raise Faraday::ConnectionFailed, e
77
- end
78
- end
79
-
80
- save_response(env, http_response.code.to_i,
81
- http_response.body || +'', nil,
82
- http_response.message) do |response_headers|
83
- http_response.each_header do |key, value|
84
- response_headers[key] = value
85
- end
86
- end
87
-
88
- @app.call env
89
- rescue Timeout::Error, Errno::ETIMEDOUT => e
90
- raise Faraday::TimeoutError, e
91
- end
92
-
93
- private
94
-
95
- def create_request(env)
96
- request = Net::HTTPGenericRequest.new \
97
- env[:method].to_s.upcase, # request method
98
- !!env[:body], # is there request body
99
- env[:method] != :head, # is there response body
100
- env[:url].request_uri, # request uri path
101
- env[:request_headers] # request headers
102
-
103
- if env[:body].respond_to?(:read)
104
- request.body_stream = env[:body]
105
- else
106
- request.body = env[:body]
107
- end
108
- request
109
- end
110
-
111
- def perform_request(http, env)
112
- if env[:request].stream_response?
113
- size = 0
114
- yielded = false
115
- http_response = request_with_wrapped_block(http, env) do |chunk|
116
- if chunk.bytesize.positive? || size.positive?
117
- yielded = true
118
- size += chunk.bytesize
119
- env[:request].on_data.call(chunk, size)
120
- end
121
- end
122
- env[:request].on_data.call(+'', 0) unless yielded
123
- # Net::HTTP returns something,
124
- # but it's not meaningful according to the docs.
125
- http_response.body = nil
126
- http_response
127
- else
128
- request_with_wrapped_block(http, env)
129
- end
130
- end
131
-
132
- def request_with_wrapped_block(http, env, &block)
133
- if (env[:method] == :get) && !env[:body]
134
- # prefer `get` to `request` because the former handles gzip (ruby 1.9)
135
- request_via_get_method(http, env, &block)
136
- else
137
- request_via_request_method(http, env, &block)
138
- end
139
- end
140
-
141
- def request_via_get_method(http, env, &block)
142
- # Must use Net::HTTP#start and pass it a block otherwise the server's
143
- # TCP socket does not close correctly.
144
- http.start do |opened_http|
145
- opened_http.get env[:url].request_uri, env[:request_headers], &block
146
- end
147
- end
148
-
149
- def request_via_request_method(http, env, &block)
150
- # Must use Net::HTTP#start and pass it a block otherwise the server's
151
- # TCP socket does not close correctly.
152
- http.start do |opened_http|
153
- if block_given?
154
- opened_http.request create_request(env) do |response|
155
- response.read_body(&block)
156
- end
157
- else
158
- opened_http.request create_request(env)
159
- end
160
- end
161
- end
162
-
163
- def configure_ssl(http, ssl)
164
- return unless ssl
165
-
166
- http.verify_mode = ssl_verify_mode(ssl)
167
- http.cert_store = ssl_cert_store(ssl)
168
-
169
- http.cert = ssl[:client_cert] if ssl[:client_cert]
170
- http.key = ssl[:client_key] if ssl[:client_key]
171
- http.ca_file = ssl[:ca_file] if ssl[:ca_file]
172
- http.ca_path = ssl[:ca_path] if ssl[:ca_path]
173
- http.verify_depth = ssl[:verify_depth] if ssl[:verify_depth]
174
- http.ssl_version = ssl[:version] if ssl[:version]
175
- http.min_version = ssl[:min_version] if ssl[:min_version]
176
- http.max_version = ssl[:max_version] if ssl[:max_version]
177
- end
178
-
179
- def configure_request(http, req)
180
- if (sec = request_timeout(:read, req))
181
- http.read_timeout = sec
182
- end
183
-
184
- if (sec = http.respond_to?(:write_timeout=) &&
185
- request_timeout(:write, req))
186
- http.write_timeout = sec
187
- end
188
-
189
- if (sec = request_timeout(:open, req))
190
- http.open_timeout = sec
191
- end
192
-
193
- # Only set if Net::Http supports it, since Ruby 2.5.
194
- http.max_retries = 0 if http.respond_to?(:max_retries=)
195
-
196
- @config_block&.call(http)
197
- end
198
-
199
- def ssl_cert_store(ssl)
200
- return ssl[:cert_store] if ssl[:cert_store]
201
-
202
- @ssl_cert_store ||= begin
203
- # Use the default cert store by default, i.e. system ca certs
204
- OpenSSL::X509::Store.new.tap(&:set_default_paths)
205
- end
206
- end
207
-
208
- def ssl_verify_mode(ssl)
209
- ssl[:verify_mode] || begin
210
- if ssl.fetch(:verify, true)
211
- OpenSSL::SSL::VERIFY_PEER
212
- else
213
- OpenSSL::SSL::VERIFY_NONE
214
- end
215
- end
216
- end
217
- end
218
- end
219
- end
@@ -1,91 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Faraday
4
- class Adapter
5
- # Net::HTTP::Persistent adapter.
6
- class NetHttpPersistent < NetHttp
7
- dependency 'net/http/persistent'
8
-
9
- private
10
-
11
- def net_http_connection(env)
12
- @cached_connection ||=
13
- if Net::HTTP::Persistent.instance_method(:initialize)
14
- .parameters.first == %i[key name]
15
- options = { name: 'Faraday' }
16
- if @connection_options.key?(:pool_size)
17
- options[:pool_size] = @connection_options[:pool_size]
18
- end
19
- Net::HTTP::Persistent.new(**options)
20
- else
21
- Net::HTTP::Persistent.new('Faraday')
22
- end
23
-
24
- proxy_uri = proxy_uri(env)
25
- if @cached_connection.proxy_uri != proxy_uri
26
- @cached_connection.proxy = proxy_uri
27
- end
28
- @cached_connection
29
- end
30
-
31
- def proxy_uri(env)
32
- proxy_uri = nil
33
- if (proxy = env[:request][:proxy])
34
- proxy_uri = if proxy[:uri].is_a?(::URI::HTTP)
35
- proxy[:uri].dup
36
- else
37
- ::URI.parse(proxy[:uri].to_s)
38
- end
39
- proxy_uri.user = proxy_uri.password = nil
40
- # awful patch for net-http-persistent 2.8
41
- # not unescaping user/password
42
- if proxy[:user]
43
- (class << proxy_uri; self; end).class_eval do
44
- define_method(:user) { proxy[:user] }
45
- define_method(:password) { proxy[:password] }
46
- end
47
- end
48
- end
49
- proxy_uri
50
- end
51
-
52
- def perform_request(http, env)
53
- http.request env[:url], create_request(env)
54
- rescue Errno::ETIMEDOUT => e
55
- raise Faraday::TimeoutError, e
56
- rescue Net::HTTP::Persistent::Error => e
57
- raise Faraday::TimeoutError, e if e.message.include? 'Timeout'
58
-
59
- if e.message.include? 'connection refused'
60
- raise Faraday::ConnectionFailed, e
61
- end
62
-
63
- raise
64
- end
65
-
66
- SSL_CONFIGURATIONS = {
67
- certificate: :client_cert,
68
- private_key: :client_key,
69
- ca_file: :ca_file,
70
- ssl_version: :version,
71
- min_version: :min_version,
72
- max_version: :max_version
73
- }.freeze
74
-
75
- def configure_ssl(http, ssl)
76
- return unless ssl
77
-
78
- http_set(http, :verify_mode, ssl_verify_mode(ssl))
79
- http_set(http, :cert_store, ssl_cert_store(ssl))
80
-
81
- SSL_CONFIGURATIONS
82
- .select { |_, key| ssl[key] }
83
- .each { |target, key| http_set(http, target, ssl[key]) }
84
- end
85
-
86
- def http_set(http, attr, value)
87
- http.send("#{attr}=", value) if http.send(attr) != value
88
- end
89
- end
90
- end
91
- end
@@ -1,132 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Faraday
4
- class Adapter
5
- # Patron adapter.
6
- class Patron < Faraday::Adapter
7
- dependency 'patron'
8
-
9
- def build_connection(env)
10
- session = ::Patron::Session.new
11
- @config_block&.call(session)
12
- if (env[:url].scheme == 'https') && env[:ssl]
13
- configure_ssl(session, env[:ssl])
14
- end
15
-
16
- if (req = env[:request])
17
- configure_timeouts(session, req)
18
- configure_proxy(session, req[:proxy])
19
- end
20
-
21
- session
22
- end
23
-
24
- def call(env)
25
- super
26
- # TODO: support streaming requests
27
- env[:body] = env[:body].read if env[:body].respond_to? :read
28
-
29
- response = connection(env) do |session|
30
- begin
31
- data = env[:body] ? env[:body].to_s : nil
32
- session.request(env[:method], env[:url].to_s,
33
- env[:request_headers], data: data)
34
- rescue Errno::ECONNREFUSED, ::Patron::ConnectionFailed
35
- raise Faraday::ConnectionFailed, $ERROR_INFO
36
- end
37
- end
38
-
39
- if (req = env[:request]).stream_response?
40
- warn "Streaming downloads for #{self.class.name} " \
41
- 'are not yet implemented.'
42
- req.on_data.call(response.body, response.body.bytesize)
43
- end
44
- # Remove the "HTTP/1.1 200", leaving just the reason phrase
45
- reason_phrase = response.status_line.gsub(/^.* \d{3} /, '')
46
-
47
- save_response(env, response.status, response.body,
48
- response.headers, reason_phrase)
49
-
50
- @app.call env
51
- rescue ::Patron::TimeoutError => e
52
- if connection_timed_out_message?(e.message)
53
- raise Faraday::ConnectionFailed, e
54
- end
55
-
56
- raise Faraday::TimeoutError, e
57
- rescue ::Patron::Error => e
58
- if e.message.include?('code 407')
59
- raise Faraday::ConnectionFailed,
60
- %(407 "Proxy Authentication Required ")
61
- end
62
-
63
- raise Faraday::ConnectionFailed, e
64
- end
65
-
66
- if loaded? && defined?(::Patron::Request::VALID_ACTIONS)
67
- # HAX: helps but doesn't work completely
68
- # https://github.com/toland/patron/issues/34
69
- ::Patron::Request::VALID_ACTIONS.tap do |actions|
70
- if actions[0].is_a?(Symbol)
71
- actions << :patch unless actions.include? :patch
72
- actions << :options unless actions.include? :options
73
- else
74
- # Patron 0.4.20 and up
75
- actions << 'PATCH' unless actions.include? 'PATCH'
76
- actions << 'OPTIONS' unless actions.include? 'OPTIONS'
77
- end
78
- end
79
- end
80
-
81
- def configure_ssl(session, ssl)
82
- if ssl.fetch(:verify, true)
83
- session.cacert = ssl[:ca_file]
84
- else
85
- session.insecure = true
86
- end
87
- end
88
-
89
- def configure_timeouts(session, req)
90
- return unless req
91
-
92
- if (sec = request_timeout(:read, req))
93
- session.timeout = sec
94
- end
95
-
96
- return unless (sec = request_timeout(:open, req))
97
-
98
- session.connect_timeout = sec
99
- end
100
-
101
- def configure_proxy(session, proxy)
102
- return unless proxy
103
-
104
- proxy_uri = proxy[:uri].dup
105
- proxy_uri.user = proxy[:user] &&
106
- Utils.escape(proxy[:user]).gsub('+', '%20')
107
- proxy_uri.password = proxy[:password] &&
108
- Utils.escape(proxy[:password]).gsub('+', '%20')
109
- session.proxy = proxy_uri.to_s
110
- end
111
-
112
- private
113
-
114
- CURL_TIMEOUT_MESSAGES = [
115
- 'Connection time-out',
116
- 'Connection timed out',
117
- 'Timed out before name resolve',
118
- 'server connect has timed out',
119
- 'Resolving timed out',
120
- 'name lookup timed out',
121
- 'timed out before SSL',
122
- 'connect() timed out'
123
- ].freeze
124
-
125
- def connection_timed_out_message?(message)
126
- CURL_TIMEOUT_MESSAGES.any? do |curl_message|
127
- message.include?(curl_message)
128
- end
129
- end
130
- end
131
- end
132
- end
@@ -1,75 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Faraday
4
- class Adapter
5
- # Sends requests to a Rack app.
6
- #
7
- # @example
8
- #
9
- # class MyRackApp
10
- # def call(env)
11
- # [200, {'Content-Type' => 'text/html'}, ["hello world"]]
12
- # end
13
- # end
14
- #
15
- # Faraday.new do |conn|
16
- # conn.adapter :rack, MyRackApp.new
17
- # end
18
- class Rack < Faraday::Adapter
19
- dependency 'rack/test'
20
-
21
- # not prefixed with "HTTP_"
22
- SPECIAL_HEADERS = %w[CONTENT_LENGTH CONTENT_TYPE].freeze
23
-
24
- def initialize(faraday_app, rack_app)
25
- super(faraday_app)
26
- mock_session = ::Rack::MockSession.new(rack_app)
27
- @session = ::Rack::Test::Session.new(mock_session)
28
- end
29
-
30
- def call(env)
31
- super
32
- rack_env = build_rack_env(env)
33
-
34
- env[:request_headers]&.each do |name, value|
35
- name = name.upcase.tr('-', '_')
36
- name = "HTTP_#{name}" unless SPECIAL_HEADERS.include? name
37
- rack_env[name] = value
38
- end
39
-
40
- timeout = request_timeout(:open, env[:request])
41
- timeout ||= request_timeout(:read, env[:request])
42
- response = if timeout
43
- Timer.timeout(timeout, Faraday::TimeoutError) do
44
- execute_request(env, rack_env)
45
- end
46
- else
47
- execute_request(env, rack_env)
48
- end
49
-
50
- if (req = env[:request]).stream_response?
51
- warn "Streaming downloads for #{self.class.name} " \
52
- 'are not yet implemented.'
53
- req.on_data.call(response.body, response.body.bytesize)
54
- end
55
-
56
- save_response(env, response.status, response.body, response.headers)
57
- @app.call env
58
- end
59
-
60
- private
61
-
62
- def execute_request(env, rack_env)
63
- @session.request(env[:url].to_s, rack_env)
64
- end
65
-
66
- def build_rack_env(env)
67
- {
68
- method: env[:method],
69
- input: env[:body].respond_to?(:read) ? env[:body].read : env[:body],
70
- 'rack.url_scheme' => env[:url].scheme
71
- }
72
- end
73
- end
74
- end
75
- end
@@ -1,128 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'stringio'
4
-
5
- # multipart-post gem
6
- require 'composite_io'
7
- require 'parts'
8
-
9
- module Faraday
10
- # Multipart value used to POST a binary data from a file or
11
- #
12
- # @example
13
- # payload = { file: Faraday::FilePart.new("file_name.ext", "content/type") }
14
- # http.post("/upload", payload)
15
- #
16
-
17
- # @!method initialize(filename_or_io, content_type, filename = nil, opts = {})
18
- #
19
- # @param filename_or_io [String, IO] Either a String filename to a local
20
- # file or an open IO object.
21
- # @param content_type [String] String content type of the file data.
22
- # @param filename [String] Optional String filename, usually to add context
23
- # to a given IO object.
24
- # @param opts [Hash] Optional Hash of String key/value pairs to describethis
25
- # this uploaded file. Expected Header keys include:
26
- # * Content-Transfer-Encoding - Defaults to "binary"
27
- # * Content-Disposition - Defaults to "form-data"
28
- # * Content-Type - Defaults to the content_type argument.
29
- # * Content-ID - Optional.
30
- #
31
- # @return [Faraday::FilePart]
32
- #
33
- # @!attribute [r] content_type
34
- # The uploaded binary data's content type.
35
- #
36
- # @return [String]
37
- #
38
- # @!attribute [r] original_filename
39
- # The base filename, taken either from the filename_or_io or filename
40
- # arguments in #initialize.
41
- #
42
- # @return [String]
43
- #
44
- # @!attribute [r] opts
45
- # Extra String key/value pairs to make up the header for this uploaded file.
46
- #
47
- # @return [Hash]
48
- #
49
- # @!attribute [r] io
50
- # The open IO object for the uploaded file.
51
- #
52
- # @return [IO]
53
- FilePart = ::UploadIO
54
-
55
- # Multipart value used to POST a file.
56
- #
57
- # @deprecated Use FilePart instead of this class. It behaves identically, with
58
- # a matching name to ParamPart.
59
- UploadIO = ::UploadIO
60
-
61
- Parts = ::Parts
62
-
63
- # Similar to, but not compatible with CompositeReadIO provided by the
64
- # multipart-post gem.
65
- # https://github.com/nicksieger/multipart-post/blob/master/lib/composite_io.rb
66
- class CompositeReadIO
67
- def initialize(*parts)
68
- @parts = parts.flatten
69
- @ios = @parts.map(&:to_io)
70
- @index = 0
71
- end
72
-
73
- # @return [Integer] sum of the lengths of all the parts
74
- def length
75
- @parts.inject(0) { |sum, part| sum + part.length }
76
- end
77
-
78
- # Rewind each of the IOs and reset the index to 0.
79
- #
80
- # @return [void]
81
- def rewind
82
- @ios.each(&:rewind)
83
- @index = 0
84
- end
85
-
86
- # Read from IOs in order until `length` bytes have been received.
87
- #
88
- # @param length [Integer, nil]
89
- # @param outbuf [String, nil]
90
- def read(length = nil, outbuf = nil)
91
- got_result = false
92
- outbuf = outbuf ? (+outbuf).replace('') : +''
93
-
94
- while (io = current_io)
95
- if (result = io.read(length))
96
- got_result ||= !result.nil?
97
- result.force_encoding('BINARY') if result.respond_to?(:force_encoding)
98
- outbuf << result
99
- length -= result.length if length
100
- break if length&.zero?
101
- end
102
- advance_io
103
- end
104
- !got_result && length ? nil : outbuf
105
- end
106
-
107
- # Close each of the IOs.
108
- #
109
- # @return [void]
110
- def close
111
- @ios.each(&:close)
112
- end
113
-
114
- def ensure_open_and_readable
115
- # Rubinius compatibility
116
- end
117
-
118
- private
119
-
120
- def current_io
121
- @ios[@index]
122
- end
123
-
124
- def advance_io
125
- @index += 1
126
- end
127
- end
128
- end
@@ -1,53 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Faraday
4
- # Multipart value used to POST data with a content type.
5
- class ParamPart
6
- # @param value [String] Uploaded content as a String.
7
- # @param content_type [String] String content type of the value.
8
- # @param content_id [String] Optional String of this value's Content-ID.
9
- #
10
- # @return [Faraday::ParamPart]
11
- def initialize(value, content_type, content_id = nil)
12
- @value = value
13
- @content_type = content_type
14
- @content_id = content_id
15
- end
16
-
17
- # Converts this value to a form part.
18
- #
19
- # @param boundary [String] String multipart boundary that must not exist in
20
- # the content exactly.
21
- # @param key [String] String key name for this value.
22
- #
23
- # @return [Faraday::Parts::Part]
24
- def to_part(boundary, key)
25
- Faraday::Parts::Part.new(boundary, key, value, headers)
26
- end
27
-
28
- # Returns a Hash of String key/value pairs.
29
- #
30
- # @return [Hash]
31
- def headers
32
- {
33
- 'Content-Type' => content_type,
34
- 'Content-ID' => content_id
35
- }
36
- end
37
-
38
- # The content to upload.
39
- #
40
- # @return [String]
41
- attr_reader :value
42
-
43
- # The value's content type.
44
- #
45
- # @return [String]
46
- attr_reader :content_type
47
-
48
- # The value's content ID, if given.
49
- #
50
- # @return [String, nil]
51
- attr_reader :content_id
52
- end
53
- end