faraday 0.16.0 → 0.17.4

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 (90) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +232 -0
  3. data/LICENSE.md +1 -1
  4. data/README.md +358 -18
  5. data/Rakefile +13 -0
  6. data/lib/faraday/adapter/em_http.rb +97 -140
  7. data/lib/faraday/adapter/em_http_ssl_patch.rb +17 -23
  8. data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +15 -18
  9. data/lib/faraday/adapter/em_synchrony.rb +60 -104
  10. data/lib/faraday/adapter/excon.rb +55 -100
  11. data/lib/faraday/adapter/httpclient.rb +39 -61
  12. data/lib/faraday/adapter/net_http.rb +51 -103
  13. data/lib/faraday/adapter/net_http_persistent.rb +28 -49
  14. data/lib/faraday/adapter/patron.rb +35 -54
  15. data/lib/faraday/adapter/rack.rb +12 -28
  16. data/lib/faraday/adapter/test.rb +53 -86
  17. data/lib/faraday/adapter/typhoeus.rb +1 -4
  18. data/lib/faraday/adapter.rb +22 -36
  19. data/lib/faraday/autoload.rb +36 -47
  20. data/lib/faraday/connection.rb +179 -321
  21. data/lib/faraday/deprecate.rb +109 -0
  22. data/lib/faraday/error.rb +79 -21
  23. data/lib/faraday/middleware.rb +28 -4
  24. data/lib/faraday/options.rb +183 -32
  25. data/lib/faraday/parameters.rb +197 -4
  26. data/lib/faraday/rack_builder.rb +55 -66
  27. data/lib/faraday/request/authorization.rb +30 -42
  28. data/lib/faraday/request/basic_authentication.rb +7 -14
  29. data/lib/faraday/request/instrumentation.rb +27 -45
  30. data/lib/faraday/request/multipart.rb +48 -79
  31. data/lib/faraday/request/retry.rb +171 -197
  32. data/lib/faraday/request/token_authentication.rb +10 -15
  33. data/lib/faraday/request/url_encoded.rb +23 -41
  34. data/lib/faraday/request.rb +36 -68
  35. data/lib/faraday/response/logger.rb +69 -22
  36. data/lib/faraday/response/raise_error.rb +18 -36
  37. data/lib/faraday/response.rb +13 -20
  38. data/lib/faraday/upload_io.rb +67 -0
  39. data/lib/faraday/utils.rb +245 -28
  40. data/lib/faraday.rb +174 -93
  41. data/spec/faraday/deprecate_spec.rb +147 -0
  42. data/spec/faraday/error_spec.rb +102 -0
  43. data/spec/faraday/response/raise_error_spec.rb +106 -0
  44. data/spec/spec_helper.rb +105 -0
  45. data/test/adapters/default_test.rb +14 -0
  46. data/test/adapters/em_http_test.rb +30 -0
  47. data/test/adapters/em_synchrony_test.rb +32 -0
  48. data/test/adapters/excon_test.rb +30 -0
  49. data/test/adapters/httpclient_test.rb +34 -0
  50. data/test/adapters/integration.rb +263 -0
  51. data/test/adapters/logger_test.rb +136 -0
  52. data/test/adapters/net_http_persistent_test.rb +114 -0
  53. data/test/adapters/net_http_test.rb +79 -0
  54. data/test/adapters/patron_test.rb +40 -0
  55. data/test/adapters/rack_test.rb +38 -0
  56. data/test/adapters/test_middleware_test.rb +157 -0
  57. data/test/adapters/typhoeus_test.rb +38 -0
  58. data/test/authentication_middleware_test.rb +65 -0
  59. data/test/composite_read_io_test.rb +109 -0
  60. data/test/connection_test.rb +738 -0
  61. data/test/env_test.rb +268 -0
  62. data/test/helper.rb +75 -0
  63. data/test/live_server.rb +67 -0
  64. data/test/middleware/instrumentation_test.rb +88 -0
  65. data/test/middleware/retry_test.rb +282 -0
  66. data/test/middleware_stack_test.rb +260 -0
  67. data/test/multibyte.txt +1 -0
  68. data/test/options_test.rb +333 -0
  69. data/test/parameters_test.rb +157 -0
  70. data/test/request_middleware_test.rb +126 -0
  71. data/test/response_middleware_test.rb +72 -0
  72. data/test/strawberry.rb +2 -0
  73. data/test/utils_test.rb +98 -0
  74. metadata +50 -25
  75. data/lib/faraday/adapter_registry.rb +0 -28
  76. data/lib/faraday/dependency_loader.rb +0 -37
  77. data/lib/faraday/encoders/flat_params_encoder.rb +0 -94
  78. data/lib/faraday/encoders/nested_params_encoder.rb +0 -171
  79. data/lib/faraday/file_part.rb +0 -128
  80. data/lib/faraday/logging/formatter.rb +0 -92
  81. data/lib/faraday/middleware_registry.rb +0 -129
  82. data/lib/faraday/options/connection_options.rb +0 -22
  83. data/lib/faraday/options/env.rb +0 -181
  84. data/lib/faraday/options/proxy_options.rb +0 -28
  85. data/lib/faraday/options/request_options.rb +0 -21
  86. data/lib/faraday/options/ssl_options.rb +0 -59
  87. data/lib/faraday/param_part.rb +0 -53
  88. data/lib/faraday/utils/headers.rb +0 -139
  89. data/lib/faraday/utils/params_hash.rb +0 -61
  90. data/spec/external_adapters/faraday_specs_setup.rb +0 -14
@@ -1,54 +1,36 @@
1
- # frozen_string_literal: true
2
-
3
1
  module Faraday
4
- class Request
5
- # Middleware for supporting urlencoded requests.
6
- class UrlEncoded < Faraday::Middleware
7
- CONTENT_TYPE = 'Content-Type' unless defined? CONTENT_TYPE
2
+ class Request::UrlEncoded < Faraday::Middleware
3
+ CONTENT_TYPE = 'Content-Type'.freeze unless defined? CONTENT_TYPE
8
4
 
9
- class << self
10
- attr_accessor :mime_type
11
- end
12
- self.mime_type = 'application/x-www-form-urlencoded'
5
+ class << self
6
+ attr_accessor :mime_type
7
+ end
8
+ self.mime_type = 'application/x-www-form-urlencoded'.freeze
13
9
 
14
- # Encodes as "application/x-www-form-urlencoded" if not already encoded or
15
- # of another type.
16
- #
17
- # @param env [Faraday::Env]
18
- def call(env)
19
- match_content_type(env) do |data|
20
- params = Faraday::Utils::ParamsHash[data]
21
- env.body = params.to_query(env.params_encoder)
22
- end
23
- @app.call env
10
+ def call(env)
11
+ match_content_type(env) do |data|
12
+ params = Faraday::Utils::ParamsHash[data]
13
+ env.body = params.to_query(env.params_encoder)
24
14
  end
15
+ @app.call env
16
+ end
25
17
 
26
- # @param env [Faraday::Env]
27
- # @yield [request_body] Body of the request
28
- def match_content_type(env)
29
- return unless process_request?(env)
30
-
18
+ def match_content_type(env)
19
+ if process_request?(env)
31
20
  env.request_headers[CONTENT_TYPE] ||= self.class.mime_type
32
21
  yield(env.body) unless env.body.respond_to?(:to_str)
33
22
  end
23
+ end
34
24
 
35
- # @param env [Faraday::Env]
36
- #
37
- # @return [Boolean] True if the request has a body and its Content-Type is
38
- # urlencoded.
39
- def process_request?(env)
40
- type = request_type(env)
41
- env.body && (type.empty? || (type == self.class.mime_type))
42
- end
25
+ def process_request?(env)
26
+ type = request_type(env)
27
+ env.body and (type.empty? or type == self.class.mime_type)
28
+ end
43
29
 
44
- # @param env [Faraday::Env]
45
- #
46
- # @return [String]
47
- def request_type(env)
48
- type = env.request_headers[CONTENT_TYPE].to_s
49
- type = type.split(';', 2).first if type.index(';')
50
- type
51
- end
30
+ def request_type(env)
31
+ type = env.request_headers[CONTENT_TYPE].to_s
32
+ type = type.split(';', 2).first if type.index(';')
33
+ type
52
34
  end
53
35
  end
54
36
  end
@@ -1,9 +1,6 @@
1
- # frozen_string_literal: true
2
-
3
1
  module Faraday
4
- # Used to setup URLs, params, headers, and the request body in a sane manner.
2
+ # Used to setup urls, params, headers, and the request body in a sane manner.
5
3
  #
6
- # @example
7
4
  # @connection.post do |req|
8
5
  # req.url 'http://localhost', 'a' => '1' # 'http://localhost?a=1'
9
6
  # req.headers['b'] = '2' # Header
@@ -12,53 +9,25 @@ module Faraday
12
9
  # req.body = 'abc'
13
10
  # end
14
11
  #
15
- # @!attribute method
16
- # @return [Symbol] the HTTP method of the Request
17
- # @!attribute path
18
- # @return [URI, String] the path
19
- # @!attribute params
20
- # @return [Hash] query parameters
21
- # @!attribute headers
22
- # @return [Faraday::Utils::Headers] headers
23
- # @!attribute body
24
- # @return [Hash] body
25
- # @!attribute options
26
- # @return [RequestOptions] options
27
- #
28
- # rubocop:disable Style/StructInheritance
29
12
  class Request < Struct.new(:method, :path, :params, :headers, :body, :options)
30
- # rubocop:enable Style/StructInheritance
31
-
32
13
  extend MiddlewareRegistry
33
14
 
34
- register_middleware File.expand_path('request', __dir__),
35
- url_encoded: [:UrlEncoded, 'url_encoded'],
36
- multipart: [:Multipart, 'multipart'],
37
- retry: [:Retry, 'retry'],
38
- authorization: [:Authorization, 'authorization'],
39
- basic_auth: [
40
- :BasicAuthentication,
41
- 'basic_authentication'
42
- ],
43
- token_auth: [
44
- :TokenAuthentication,
45
- 'token_authentication'
46
- ],
47
- instrumentation: [:Instrumentation, 'instrumentation']
15
+ register_middleware File.expand_path('../request', __FILE__),
16
+ :url_encoded => [:UrlEncoded, 'url_encoded'],
17
+ :multipart => [:Multipart, 'multipart'],
18
+ :retry => [:Retry, 'retry'],
19
+ :authorization => [:Authorization, 'authorization'],
20
+ :basic_auth => [:BasicAuthentication, 'basic_authentication'],
21
+ :token_auth => [:TokenAuthentication, 'token_authentication'],
22
+ :instrumentation => [:Instrumentation, 'instrumentation']
48
23
 
49
- # @param request_method [String]
50
- # @yield [request] for block customization, if block given
51
- # @yieldparam request [Request]
52
- # @return [Request]
53
24
  def self.create(request_method)
54
25
  new(request_method).tap do |request|
55
26
  yield(request) if block_given?
56
27
  end
57
28
  end
58
29
 
59
- # Replace params, preserving the existing hash type.
60
- #
61
- # @param hash [Hash] new params
30
+ # Public: Replace params, preserving the existing hash type
62
31
  def params=(hash)
63
32
  if params
64
33
  params.replace hash
@@ -67,9 +36,7 @@ module Faraday
67
36
  end
68
37
  end
69
38
 
70
- # Replace request headers, preserving the existing hash type.
71
- #
72
- # @param hash [Hash] new headers
39
+ # Public: Replace request headers, preserving the existing hash type
73
40
  def headers=(hash)
74
41
  if headers
75
42
  headers.replace hash
@@ -78,14 +45,9 @@ module Faraday
78
45
  end
79
46
  end
80
47
 
81
- # Update path and params.
82
- #
83
- # @param path [URI, String]
84
- # @param params [Hash, nil]
85
- # @return [void]
86
48
  def url(path, params = nil)
87
49
  if path.respond_to? :query
88
- if (query = path.query)
50
+ if query = path.query
89
51
  path = path.dup
90
52
  path.query = nil
91
53
  end
@@ -99,35 +61,25 @@ module Faraday
99
61
  self.params.update(params) if params
100
62
  end
101
63
 
102
- # @param key [Object] key to look up in headers
103
- # @return [Object] value of the given header name
104
64
  def [](key)
105
65
  headers[key]
106
66
  end
107
67
 
108
- # @param key [Object] key of header to write
109
- # @param value [Object] value of header
110
68
  def []=(key, value)
111
69
  headers[key] = value
112
70
  end
113
71
 
114
- # Marshal serialization support.
115
- #
116
- # @return [Hash] the hash ready to be serialized in Marshal.
117
72
  def marshal_dump
118
73
  {
119
- method: method,
120
- body: body,
121
- headers: headers,
122
- path: path,
123
- params: params,
124
- options: options
74
+ :method => method,
75
+ :body => body,
76
+ :headers => headers,
77
+ :path => path,
78
+ :params => params,
79
+ :options => options
125
80
  }
126
81
  end
127
82
 
128
- # Marshal serialization support.
129
- # Restores the instance variables according to the +serialised+.
130
- # @param serialised [Hash] the serialised object.
131
83
  def marshal_load(serialised)
132
84
  self.method = serialised[:method]
133
85
  self.body = serialised[:body]
@@ -137,10 +89,26 @@ module Faraday
137
89
  self.options = serialised[:options]
138
90
  end
139
91
 
140
- # @return [Env] the Env for this Request
92
+ # ENV Keys
93
+ # :method - a symbolized request method (:get, :post)
94
+ # :body - the request body that will eventually be converted to a string.
95
+ # :url - URI instance for the current request.
96
+ # :status - HTTP response status code
97
+ # :request_headers - hash of HTTP Headers to be sent to the server
98
+ # :response_headers - Hash of HTTP headers from the server
99
+ # :parallel_manager - sent if the connection is in parallel mode
100
+ # :request - Hash of options for configuring the request.
101
+ # :timeout - open/read timeout Integer in seconds
102
+ # :open_timeout - read timeout Integer in seconds
103
+ # :proxy - Hash of proxy options
104
+ # :uri - Proxy Server URI
105
+ # :user - Proxy server username
106
+ # :password - Proxy server password
107
+ # :ssl - Hash of options for configuring SSL requests.
141
108
  def to_env(connection)
142
109
  Env.new(method, body, connection.build_exclusive_url(path, params),
143
- options, headers, connection.ssl, connection.parallel_manager)
110
+ options, headers, connection.ssl, connection.parallel_manager)
144
111
  end
145
112
  end
146
113
  end
114
+
@@ -1,33 +1,80 @@
1
- # frozen_string_literal: true
2
-
3
1
  require 'forwardable'
4
- require 'faraday/logging/formatter'
5
2
 
6
3
  module Faraday
7
- class Response
8
- # Logger is a middleware that logs internal events in the HTTP request
9
- # lifecycle to a given Logger object. By default, this logs to STDOUT. See
10
- # Faraday::Logging::Formatter to see specifically what is logged.
11
- class Logger < Middleware
12
- def initialize(app, logger = nil, options = {})
13
- super(app)
14
- logger ||= begin
15
- require 'logger'
16
- ::Logger.new($stdout)
17
- end
18
- formatter_class = options.delete(:formatter) || Logging::Formatter
19
- @formatter = formatter_class.new(logger: logger, options: options)
20
- yield @formatter if block_given?
4
+ class Response::Logger < Response::Middleware
5
+ extend Forwardable
6
+
7
+ DEFAULT_OPTIONS = { :headers => true, :bodies => false }
8
+
9
+ def initialize(app, logger = nil, options = {})
10
+ super(app)
11
+ @logger = logger || begin
12
+ require 'logger'
13
+ ::Logger.new($stdout)
14
+ end
15
+ @filter = []
16
+ @options = DEFAULT_OPTIONS.merge(options)
17
+ yield self if block_given?
18
+ end
19
+
20
+ def_delegators :@logger, :debug, :info, :warn, :error, :fatal
21
+
22
+ def call(env)
23
+ info('request') { "#{env.method.upcase} #{apply_filters(env.url.to_s)}" }
24
+ debug('request') { apply_filters( dump_headers env.request_headers ) } if log_headers?(:request)
25
+ debug('request') { apply_filters( dump_body(env[:body]) ) } if env[:body] && log_body?(:request)
26
+ super
27
+ end
28
+
29
+ def on_complete(env)
30
+ info('response') { "Status #{env.status.to_s}" }
31
+ debug('response') { apply_filters( dump_headers env.response_headers ) } if log_headers?(:response)
32
+ debug('response') { apply_filters( dump_body env[:body] ) } if env[:body] && log_body?(:response)
33
+ end
34
+
35
+ def filter(filter_word, filter_replacement)
36
+ @filter.push([ filter_word, filter_replacement ])
37
+ end
38
+
39
+ private
40
+
41
+ def dump_headers(headers)
42
+ headers.map { |k, v| "#{k}: #{v.inspect}" }.join("\n")
43
+ end
44
+
45
+ def dump_body(body)
46
+ if body.respond_to?(:to_str)
47
+ body.to_str
48
+ else
49
+ pretty_inspect(body)
50
+ end
51
+ end
52
+
53
+ def pretty_inspect(body)
54
+ require 'pp' unless body.respond_to?(:pretty_inspect)
55
+ body.pretty_inspect
56
+ end
57
+
58
+ def log_headers?(type)
59
+ case @options[:headers]
60
+ when Hash then @options[:headers][type]
61
+ else @options[:headers]
21
62
  end
63
+ end
22
64
 
23
- def call(env)
24
- @formatter.request(env)
25
- super
65
+ def log_body?(type)
66
+ case @options[:bodies]
67
+ when Hash then @options[:bodies][type]
68
+ else @options[:bodies]
26
69
  end
70
+ end
27
71
 
28
- def on_complete(env)
29
- @formatter.response(env)
72
+ def apply_filters(output)
73
+ @filter.each do |pattern, replacement|
74
+ output = output.to_s.gsub(pattern, replacement)
30
75
  end
76
+ output
31
77
  end
78
+
32
79
  end
33
80
  end
@@ -1,43 +1,25 @@
1
- # frozen_string_literal: true
2
-
3
1
  module Faraday
4
- class Response
5
- # RaiseError is a Faraday middleware that raises exceptions on common HTTP
6
- # client or server error responses.
7
- class RaiseError < Middleware
8
- # rubocop:disable Naming/ConstantName
9
- ClientErrorStatuses = (400...500).freeze
10
- ServerErrorStatuses = (500...600).freeze
11
- # rubocop:enable Naming/ConstantName
2
+ class Response::RaiseError < Response::Middleware
3
+ ClientErrorStatuses = 400...600
12
4
 
13
- def on_complete(env)
14
- case env[:status]
15
- when 400
16
- raise Faraday::BadRequestError, response_values(env)
17
- when 401
18
- raise Faraday::UnauthorizedError, response_values(env)
19
- when 403
20
- raise Faraday::ForbiddenError, response_values(env)
21
- when 404
22
- raise Faraday::ResourceNotFound, response_values(env)
23
- when 407
24
- # mimic the behavior that we get with proxy requests with HTTPS
25
- msg = %(407 "Proxy Authentication Required")
26
- raise Faraday::ProxyAuthError.new(msg, response_values(env))
27
- when 409
28
- raise Faraday::ConflictError, response_values(env)
29
- when 422
30
- raise Faraday::UnprocessableEntityError, response_values(env)
31
- when ClientErrorStatuses
32
- raise Faraday::ClientError, response_values(env)
33
- when ServerErrorStatuses
34
- raise Faraday::ServerError, response_values(env)
35
- end
5
+ def on_complete(env)
6
+ case env[:status]
7
+ when 404
8
+ raise Faraday::ResourceNotFound, response_values(env)
9
+ when 407
10
+ # mimic the behavior that we get with proxy requests with HTTPS
11
+ raise Faraday::ConnectionFailed.new(
12
+ %{407 "Proxy Authentication Required "},
13
+ response_values(env))
14
+ when ClientErrorStatuses
15
+ raise Faraday::ClientError, response_values(env)
16
+ when nil
17
+ raise Faraday::NilStatusError, response_values(env)
36
18
  end
19
+ end
37
20
 
38
- def response_values(env)
39
- { status: env.status, headers: env.response_headers, body: env.body }
40
- end
21
+ def response_values(env)
22
+ {:status => env.status, :headers => env.response_headers, :body => env.body}
41
23
  end
42
24
  end
43
25
  end
@@ -1,9 +1,6 @@
1
- # frozen_string_literal: true
2
-
3
1
  require 'forwardable'
4
2
 
5
3
  module Faraday
6
- # Response represents an HTTP response from making an HTTP request.
7
4
  class Response
8
5
  # Used for simple response middleware.
9
6
  class Middleware < Faraday::Middleware
@@ -23,9 +20,9 @@ module Faraday
23
20
  extend Forwardable
24
21
  extend MiddlewareRegistry
25
22
 
26
- register_middleware File.expand_path('response', __dir__),
27
- raise_error: [:RaiseError, 'raise_error'],
28
- logger: [:Logger, 'logger']
23
+ register_middleware File.expand_path('../response', __FILE__),
24
+ :raise_error => [:RaiseError, 'raise_error'],
25
+ :logger => [:Logger, 'logger']
29
26
 
30
27
  def initialize(env = nil)
31
28
  @env = Env.from(env) if env
@@ -34,6 +31,8 @@ module Faraday
34
31
 
35
32
  attr_reader :env
36
33
 
34
+ def_delegators :env, :to_hash
35
+
37
36
  def status
38
37
  finished? ? env.status : nil
39
38
  end
@@ -61,31 +60,26 @@ module Faraday
61
60
  else
62
61
  yield(env)
63
62
  end
64
- self
63
+ return self
65
64
  end
66
65
 
67
66
  def finish(env)
68
- raise 'response already finished' if finished?
69
-
67
+ raise "response already finished" if finished?
70
68
  @env = env.is_a?(Env) ? env : Env.from(env)
71
69
  @on_complete_callbacks.each { |callback| callback.call(@env) }
72
- self
70
+ return self
73
71
  end
74
72
 
75
73
  def success?
76
74
  finished? && env.success?
77
75
  end
78
76
 
79
- def to_hash
80
- {
81
- status: env.status, body: env.body,
82
- response_headers: env.response_headers
83
- }
84
- end
85
-
86
77
  # because @on_complete_callbacks cannot be marshalled
87
78
  def marshal_dump
88
- finished? ? to_hash : nil
79
+ !finished? ? nil : {
80
+ :status => @env.status, :body => @env.body,
81
+ :response_headers => @env.response_headers
82
+ }
89
83
  end
90
84
 
91
85
  def marshal_load(env)
@@ -96,9 +90,8 @@ module Faraday
96
90
  # Useful for applying request params after restoring a marshalled Response.
97
91
  def apply_request(request_env)
98
92
  raise "response didn't finish yet" unless finished?
99
-
100
93
  @env = Env.from(request_env).update(@env)
101
- self
94
+ return self
102
95
  end
103
96
  end
104
97
  end
@@ -0,0 +1,67 @@
1
+ begin
2
+ require 'composite_io'
3
+ require 'parts'
4
+ require 'stringio'
5
+ rescue LoadError
6
+ $stderr.puts "Install the multipart-post gem."
7
+ raise
8
+ end
9
+
10
+ module Faraday
11
+ # Similar but not compatible with ::CompositeReadIO provided by multipart-post.
12
+ class CompositeReadIO
13
+ def initialize(*parts)
14
+ @parts = parts.flatten
15
+ @ios = @parts.map { |part| part.to_io }
16
+ @index = 0
17
+ end
18
+
19
+ def length
20
+ @parts.inject(0) { |sum, part| sum + part.length }
21
+ end
22
+
23
+ def rewind
24
+ @ios.each { |io| io.rewind }
25
+ @index = 0
26
+ end
27
+
28
+ # Read from IOs in order until `length` bytes have been received.
29
+ def read(length = nil, outbuf = nil)
30
+ got_result = false
31
+ outbuf = outbuf ? outbuf.replace("") : ""
32
+
33
+ while io = current_io
34
+ if result = io.read(length)
35
+ got_result ||= !result.nil?
36
+ result.force_encoding("BINARY") if result.respond_to?(:force_encoding)
37
+ outbuf << result
38
+ length -= result.length if length
39
+ break if length == 0
40
+ end
41
+ advance_io
42
+ end
43
+ (!got_result && length) ? nil : outbuf
44
+ end
45
+
46
+ def close
47
+ @ios.each { |io| io.close }
48
+ end
49
+
50
+ def ensure_open_and_readable
51
+ # Rubinius compatibility
52
+ end
53
+
54
+ private
55
+
56
+ def current_io
57
+ @ios[@index]
58
+ end
59
+
60
+ def advance_io
61
+ @index += 1
62
+ end
63
+ end
64
+
65
+ UploadIO = ::UploadIO
66
+ Parts = ::Parts
67
+ end