faraday 0.15.0 → 2.2.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 (93) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +570 -0
  3. data/LICENSE.md +1 -1
  4. data/README.md +25 -351
  5. data/Rakefile +7 -0
  6. data/examples/client_spec.rb +97 -0
  7. data/examples/client_test.rb +118 -0
  8. data/lib/faraday/adapter/test.rb +127 -72
  9. data/lib/faraday/adapter.rb +69 -22
  10. data/lib/faraday/adapter_registry.rb +30 -0
  11. data/lib/faraday/connection.rb +309 -232
  12. data/lib/faraday/encoders/flat_params_encoder.rb +105 -0
  13. data/lib/faraday/encoders/nested_params_encoder.rb +176 -0
  14. data/lib/faraday/error.rb +119 -38
  15. data/lib/faraday/logging/formatter.rb +106 -0
  16. data/lib/faraday/methods.rb +6 -0
  17. data/lib/faraday/middleware.rb +18 -25
  18. data/lib/faraday/middleware_registry.rb +83 -0
  19. data/lib/faraday/options/connection_options.rb +22 -0
  20. data/lib/faraday/options/env.rb +181 -0
  21. data/lib/faraday/options/proxy_options.rb +32 -0
  22. data/lib/faraday/options/request_options.rb +22 -0
  23. data/lib/faraday/options/ssl_options.rb +59 -0
  24. data/lib/faraday/options.rb +41 -195
  25. data/lib/faraday/parameters.rb +4 -196
  26. data/lib/faraday/rack_builder.rb +91 -76
  27. data/lib/faraday/request/authorization.rb +37 -29
  28. data/lib/faraday/request/instrumentation.rb +47 -27
  29. data/lib/faraday/request/json.rb +55 -0
  30. data/lib/faraday/request/url_encoded.rb +45 -23
  31. data/lib/faraday/request.rb +74 -32
  32. data/lib/faraday/response/json.rb +54 -0
  33. data/lib/faraday/response/logger.rb +22 -69
  34. data/lib/faraday/response/raise_error.rb +57 -14
  35. data/lib/faraday/response.rb +26 -33
  36. data/lib/faraday/utils/headers.rb +139 -0
  37. data/lib/faraday/utils/params_hash.rb +61 -0
  38. data/lib/faraday/utils.rb +47 -251
  39. data/lib/faraday/version.rb +5 -0
  40. data/lib/faraday.rb +108 -199
  41. data/spec/external_adapters/faraday_specs_setup.rb +14 -0
  42. data/spec/faraday/adapter/test_spec.rb +377 -0
  43. data/spec/faraday/adapter_registry_spec.rb +28 -0
  44. data/spec/faraday/adapter_spec.rb +55 -0
  45. data/spec/faraday/connection_spec.rb +787 -0
  46. data/spec/faraday/error_spec.rb +60 -0
  47. data/spec/faraday/middleware_registry_spec.rb +31 -0
  48. data/spec/faraday/middleware_spec.rb +52 -0
  49. data/spec/faraday/options/env_spec.rb +70 -0
  50. data/spec/faraday/options/options_spec.rb +297 -0
  51. data/spec/faraday/options/proxy_options_spec.rb +44 -0
  52. data/spec/faraday/options/request_options_spec.rb +19 -0
  53. data/spec/faraday/params_encoders/flat_spec.rb +42 -0
  54. data/spec/faraday/params_encoders/nested_spec.rb +142 -0
  55. data/spec/faraday/rack_builder_spec.rb +317 -0
  56. data/spec/faraday/request/authorization_spec.rb +83 -0
  57. data/spec/faraday/request/instrumentation_spec.rb +74 -0
  58. data/spec/faraday/request/json_spec.rb +111 -0
  59. data/spec/faraday/request/url_encoded_spec.rb +82 -0
  60. data/spec/faraday/request_spec.rb +109 -0
  61. data/spec/faraday/response/json_spec.rb +117 -0
  62. data/spec/faraday/response/logger_spec.rb +220 -0
  63. data/spec/faraday/response/raise_error_spec.rb +172 -0
  64. data/spec/faraday/response_spec.rb +75 -0
  65. data/spec/faraday/utils/headers_spec.rb +82 -0
  66. data/spec/faraday/utils_spec.rb +117 -0
  67. data/spec/faraday_spec.rb +37 -0
  68. data/spec/spec_helper.rb +132 -0
  69. data/spec/support/disabling_stub.rb +14 -0
  70. data/spec/support/fake_safe_buffer.rb +15 -0
  71. data/spec/support/helper_methods.rb +96 -0
  72. data/spec/support/shared_examples/adapter.rb +104 -0
  73. data/spec/support/shared_examples/params_encoder.rb +18 -0
  74. data/spec/support/shared_examples/request_method.rb +249 -0
  75. data/spec/support/streaming_response_checker.rb +35 -0
  76. metadata +86 -34
  77. data/lib/faraday/adapter/em_http.rb +0 -243
  78. data/lib/faraday/adapter/em_http_ssl_patch.rb +0 -56
  79. data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +0 -66
  80. data/lib/faraday/adapter/em_synchrony.rb +0 -106
  81. data/lib/faraday/adapter/excon.rb +0 -79
  82. data/lib/faraday/adapter/httpclient.rb +0 -128
  83. data/lib/faraday/adapter/net_http.rb +0 -137
  84. data/lib/faraday/adapter/net_http_persistent.rb +0 -63
  85. data/lib/faraday/adapter/patron.rb +0 -100
  86. data/lib/faraday/adapter/rack.rb +0 -58
  87. data/lib/faraday/adapter/typhoeus.rb +0 -12
  88. data/lib/faraday/autoload.rb +0 -84
  89. data/lib/faraday/request/basic_authentication.rb +0 -13
  90. data/lib/faraday/request/multipart.rb +0 -68
  91. data/lib/faraday/request/retry.rb +0 -211
  92. data/lib/faraday/request/token_authentication.rb +0 -15
  93. data/lib/faraday/upload_io.rb +0 -67
@@ -1,137 +0,0 @@
1
- begin
2
- require 'net/https'
3
- rescue LoadError
4
- warn "Warning: no such file to load -- net/https. Make sure openssl is installed if you want ssl support"
5
- require 'net/http'
6
- end
7
- require 'zlib'
8
-
9
- module Faraday
10
- class Adapter
11
- class NetHttp < Faraday::Adapter
12
- NET_HTTP_EXCEPTIONS = [
13
- IOError,
14
- Errno::ECONNABORTED,
15
- Errno::ECONNREFUSED,
16
- Errno::ECONNRESET,
17
- Errno::EHOSTUNREACH,
18
- Errno::EINVAL,
19
- Errno::ENETUNREACH,
20
- Errno::EPIPE,
21
- Net::HTTPBadResponse,
22
- Net::HTTPHeaderSyntaxError,
23
- Net::ProtocolError,
24
- SocketError,
25
- Zlib::GzipFile::Error,
26
- ]
27
-
28
- NET_HTTP_EXCEPTIONS << OpenSSL::SSL::SSLError if defined?(OpenSSL)
29
- NET_HTTP_EXCEPTIONS << Net::OpenTimeout if defined?(Net::OpenTimeout)
30
-
31
- def call(env)
32
- super
33
- with_net_http_connection(env) do |http|
34
- configure_ssl(http, env[:ssl]) if env[:url].scheme == 'https' and env[:ssl]
35
- configure_request(http, env[:request])
36
-
37
- begin
38
- http_response = perform_request(http, env)
39
- rescue *NET_HTTP_EXCEPTIONS => err
40
- if defined?(OpenSSL) && OpenSSL::SSL::SSLError === err
41
- raise Faraday::SSLError, err
42
- else
43
- raise Error::ConnectionFailed, err
44
- end
45
- end
46
-
47
- save_response(env, http_response.code.to_i, http_response.body || '', nil, http_response.message) do |response_headers|
48
- http_response.each_header do |key, value|
49
- response_headers[key] = value
50
- end
51
- end
52
- end
53
-
54
- @app.call env
55
- rescue Timeout::Error, Errno::ETIMEDOUT => err
56
- raise Faraday::Error::TimeoutError, err
57
- end
58
-
59
- private
60
-
61
- def create_request(env)
62
- request = Net::HTTPGenericRequest.new \
63
- env[:method].to_s.upcase, # request method
64
- !!env[:body], # is there request body
65
- :head != env[:method], # is there response body
66
- env[:url].request_uri, # request uri path
67
- env[:request_headers] # request headers
68
-
69
- if env[:body].respond_to?(:read)
70
- request.body_stream = env[:body]
71
- else
72
- request.body = env[:body]
73
- end
74
- request
75
- end
76
-
77
- def perform_request(http, env)
78
- if :get == env[:method] and !env[:body]
79
- # prefer `get` to `request` because the former handles gzip (ruby 1.9)
80
- http.get env[:url].request_uri, env[:request_headers]
81
- else
82
- http.request create_request(env)
83
- end
84
- end
85
-
86
- def with_net_http_connection(env)
87
- yield net_http_connection(env)
88
- end
89
-
90
- def net_http_connection(env)
91
- if proxy = env[:request][:proxy]
92
- Net::HTTP::Proxy(proxy[:uri].hostname, proxy[:uri].port, proxy[:user], proxy[:password])
93
- else
94
- Net::HTTP
95
- end.new(env[:url].hostname, env[:url].port || (env[:url].scheme == 'https' ? 443 : 80))
96
- end
97
-
98
- def configure_ssl(http, ssl)
99
- http.use_ssl = true
100
- http.verify_mode = ssl_verify_mode(ssl)
101
- http.cert_store = ssl_cert_store(ssl)
102
-
103
- http.cert = ssl[:client_cert] if ssl[:client_cert]
104
- http.key = ssl[:client_key] if ssl[:client_key]
105
- http.ca_file = ssl[:ca_file] if ssl[:ca_file]
106
- http.ca_path = ssl[:ca_path] if ssl[:ca_path]
107
- http.verify_depth = ssl[:verify_depth] if ssl[:verify_depth]
108
- http.ssl_version = ssl[:version] if ssl[:version]
109
- end
110
-
111
- def configure_request(http, req)
112
- http.read_timeout = http.open_timeout = req[:timeout] if req[:timeout]
113
- http.open_timeout = req[:open_timeout] if req[:open_timeout]
114
-
115
- @config_block.call(http) if @config_block
116
- end
117
-
118
- def ssl_cert_store(ssl)
119
- return ssl[:cert_store] if ssl[:cert_store]
120
- # Use the default cert store by default, i.e. system ca certs
121
- cert_store = OpenSSL::X509::Store.new
122
- cert_store.set_default_paths
123
- cert_store
124
- end
125
-
126
- def ssl_verify_mode(ssl)
127
- ssl[:verify_mode] || begin
128
- if ssl.fetch(:verify, true)
129
- OpenSSL::SSL::VERIFY_PEER
130
- else
131
- OpenSSL::SSL::VERIFY_NONE
132
- end
133
- end
134
- end
135
- end
136
- end
137
- end
@@ -1,63 +0,0 @@
1
- module Faraday
2
- class Adapter
3
- class NetHttpPersistent < NetHttp
4
- dependency 'net/http/persistent'
5
-
6
- private
7
-
8
- def net_http_connection(env)
9
- proxy_uri = proxy_uri(env)
10
-
11
- cached_connection env[:url], proxy_uri do
12
- if Net::HTTP::Persistent.instance_method(:initialize).parameters.first == [:key, :name]
13
- Net::HTTP::Persistent.new(name: 'Faraday', proxy: proxy_uri)
14
- else
15
- Net::HTTP::Persistent.new('Faraday', proxy_uri)
16
- end
17
- end
18
- end
19
-
20
- def proxy_uri(env)
21
- proxy_uri = nil
22
- if (proxy = env[:request][:proxy])
23
- proxy_uri = ::URI::HTTP === proxy[:uri] ? proxy[:uri].dup : ::URI.parse(proxy[:uri].to_s)
24
- proxy_uri.user = proxy_uri.password = nil
25
- # awful patch for net-http-persistent 2.8 not unescaping user/password
26
- (class << proxy_uri; self; end).class_eval do
27
- define_method(:user) { proxy[:user] }
28
- define_method(:password) { proxy[:password] }
29
- end if proxy[:user]
30
- end
31
- proxy_uri
32
- end
33
-
34
- def perform_request(http, env)
35
- http.request env[:url], create_request(env)
36
- rescue Errno::ETIMEDOUT => error
37
- raise Faraday::Error::TimeoutError, error
38
- rescue Net::HTTP::Persistent::Error => error
39
- if error.message.include? 'Timeout'
40
- raise Faraday::Error::TimeoutError, error
41
- elsif error.message.include? 'connection refused'
42
- raise Faraday::Error::ConnectionFailed, error
43
- else
44
- raise
45
- end
46
- end
47
-
48
- def configure_ssl(http, ssl)
49
- http.verify_mode = ssl_verify_mode(ssl)
50
- http.cert_store = ssl_cert_store(ssl)
51
-
52
- http.certificate = ssl[:client_cert] if ssl[:client_cert]
53
- http.private_key = ssl[:client_key] if ssl[:client_key]
54
- http.ca_file = ssl[:ca_file] if ssl[:ca_file]
55
- http.ssl_version = ssl[:version] if ssl[:version]
56
- end
57
-
58
- def cached_connection(url, proxy_uri)
59
- (@cached_connection ||= {})[[url.scheme, url.host, url.port, proxy_uri]] ||= yield
60
- end
61
- end
62
- end
63
- end
@@ -1,100 +0,0 @@
1
- module Faraday
2
- class Adapter
3
- class Patron < Faraday::Adapter
4
- dependency 'patron'
5
-
6
- def call(env)
7
- super
8
- # TODO: support streaming requests
9
- env[:body] = env[:body].read if env[:body].respond_to? :read
10
-
11
- session = @session ||= create_session
12
- configure_ssl(session, env[:ssl]) if env[:url].scheme == 'https' and env[:ssl]
13
-
14
- if req = env[:request]
15
- session.timeout = session.connect_timeout = req[:timeout] if req[:timeout]
16
- session.connect_timeout = req[:open_timeout] if req[:open_timeout]
17
-
18
- if proxy = req[:proxy]
19
- proxy_uri = proxy[:uri].dup
20
- proxy_uri.user = proxy[:user] && Utils.escape(proxy[:user]).gsub('+', '%20')
21
- proxy_uri.password = proxy[:password] && Utils.escape(proxy[:password]).gsub('+', '%20')
22
- session.proxy = proxy_uri.to_s
23
- end
24
- end
25
-
26
- response = begin
27
- data = env[:body] ? env[:body].to_s : nil
28
- session.request(env[:method], env[:url].to_s, env[:request_headers], :data => data)
29
- rescue Errno::ECONNREFUSED, ::Patron::ConnectionFailed
30
- raise Error::ConnectionFailed, $!
31
- end
32
-
33
- # Remove the "HTTP/1.1 200", leaving just the reason phrase
34
- reason_phrase = response.status_line.gsub(/^.* \d{3} /, '')
35
-
36
- save_response(env, response.status, response.body, response.headers, reason_phrase)
37
-
38
- @app.call env
39
- rescue ::Patron::TimeoutError => err
40
- if connection_timed_out_message?(err.message)
41
- raise Faraday::Error::ConnectionFailed, err
42
- else
43
- raise Faraday::Error::TimeoutError, err
44
- end
45
- rescue ::Patron::Error => err
46
- if err.message.include?("code 407")
47
- raise Error::ConnectionFailed, %{407 "Proxy Authentication Required "}
48
- else
49
- raise Error::ConnectionFailed, err
50
- end
51
- end
52
-
53
- if loaded? && defined?(::Patron::Request::VALID_ACTIONS)
54
- # HAX: helps but doesn't work completely
55
- # https://github.com/toland/patron/issues/34
56
- ::Patron::Request::VALID_ACTIONS.tap do |actions|
57
- if actions[0].is_a?(Symbol)
58
- actions << :patch unless actions.include? :patch
59
- actions << :options unless actions.include? :options
60
- else
61
- # Patron 0.4.20 and up
62
- actions << "PATCH" unless actions.include? "PATCH"
63
- actions << "OPTIONS" unless actions.include? "OPTIONS"
64
- end
65
- end
66
- end
67
-
68
- def create_session
69
- session = ::Patron::Session.new
70
- @config_block.call(session) if @config_block
71
- session
72
- end
73
-
74
- def configure_ssl(session, ssl)
75
- if ssl.fetch(:verify, true)
76
- session.cacert = ssl[:ca_file]
77
- else
78
- session.insecure = true
79
- end
80
- end
81
-
82
- private
83
-
84
- CURL_TIMEOUT_MESSAGES = [ "Connection time-out",
85
- "Connection timed out",
86
- "Timed out before name resolve",
87
- "server connect has timed out",
88
- "Resolving timed out",
89
- "name lookup timed out",
90
- "timed out before SSL",
91
- "connect() timed out"
92
- ].freeze
93
-
94
- def connection_timed_out_message?(message)
95
- CURL_TIMEOUT_MESSAGES.any? { |curl_message| message.include?(curl_message) }
96
- end
97
-
98
- end
99
- end
100
- end
@@ -1,58 +0,0 @@
1
- module Faraday
2
- class Adapter
3
- # Sends requests to a Rack app.
4
- #
5
- # Examples
6
- #
7
- # class MyRackApp
8
- # def call(env)
9
- # [200, {'Content-Type' => 'text/html'}, ["hello world"]]
10
- # end
11
- # end
12
- #
13
- # Faraday.new do |conn|
14
- # conn.adapter :rack, MyRackApp.new
15
- # end
16
- class Rack < Faraday::Adapter
17
- dependency 'rack/test'
18
-
19
- # not prefixed with "HTTP_"
20
- SPECIAL_HEADERS = %w[ CONTENT_LENGTH CONTENT_TYPE ]
21
-
22
- def initialize(faraday_app, rack_app)
23
- super(faraday_app)
24
- mock_session = ::Rack::MockSession.new(rack_app)
25
- @session = ::Rack::Test::Session.new(mock_session)
26
- end
27
-
28
- def call(env)
29
- super
30
- rack_env = {
31
- :method => env[:method],
32
- :input => env[:body].respond_to?(:read) ? env[:body].read : env[:body],
33
- 'rack.url_scheme' => env[:url].scheme
34
- }
35
-
36
- env[:request_headers].each do |name, value|
37
- name = name.upcase.tr('-', '_')
38
- name = "HTTP_#{name}" unless SPECIAL_HEADERS.include? name
39
- rack_env[name] = value
40
- end if env[:request_headers]
41
-
42
- timeout = env[:request][:timeout] || env[:request][:open_timeout]
43
- response = if timeout
44
- Timer.timeout(timeout, Faraday::Error::TimeoutError) { execute_request(env, rack_env) }
45
- else
46
- execute_request(env, rack_env)
47
- end
48
-
49
- save_response(env, response.status, response.body, response.headers)
50
- @app.call env
51
- end
52
-
53
- def execute_request(env, rack_env)
54
- @session.request(env[:url].to_s, rack_env)
55
- end
56
- end
57
- end
58
- end
@@ -1,12 +0,0 @@
1
- module Faraday
2
- class Adapter
3
- # This class is just a stub, the real adapter is in https://github.com/philsturgeon/typhoeus/blob/master/lib/typhoeus/adapters/faraday.rb
4
- class Typhoeus < Faraday::Adapter
5
- # Needs to define this method in order to support Typhoeus <= 1.3.0
6
- def call; end
7
-
8
- dependency 'typhoeus'
9
- dependency 'typhoeus/adapters/faraday'
10
- end
11
- end
12
- end
@@ -1,84 +0,0 @@
1
- module Faraday
2
- # Internal: Adds the ability for other modules to manage autoloadable
3
- # constants.
4
- module AutoloadHelper
5
- # Internal: Registers the constants to be auto loaded.
6
- #
7
- # prefix - The String require prefix. If the path is inside Faraday, then
8
- # it will be prefixed with the root path of this loaded Faraday
9
- # version.
10
- # options - Hash of Symbol => String library names.
11
- #
12
- # Examples.
13
- #
14
- # Faraday.autoload_all 'faraday/foo',
15
- # :Bar => 'bar'
16
- #
17
- # # requires faraday/foo/bar to load Faraday::Bar.
18
- # Faraday::Bar
19
- #
20
- #
21
- # Returns nothing.
22
- def autoload_all(prefix, options)
23
- if prefix =~ /^faraday(\/|$)/i
24
- prefix = File.join(Faraday.root_path, prefix)
25
- end
26
- options.each do |const_name, path|
27
- autoload const_name, File.join(prefix, path)
28
- end
29
- end
30
-
31
- # Internal: Loads each autoloaded constant. If thread safety is a concern,
32
- # wrap this in a Mutex.
33
- #
34
- # Returns nothing.
35
- def load_autoloaded_constants
36
- constants.each do |const|
37
- const_get(const) if autoload?(const)
38
- end
39
- end
40
-
41
- # Internal: Filters the module's contents with those that have been already
42
- # autoloaded.
43
- #
44
- # Returns an Array of Class/Module objects.
45
- def all_loaded_constants
46
- constants.map { |c| const_get(c) }.
47
- select { |a| a.respond_to?(:loaded?) && a.loaded? }
48
- end
49
- end
50
-
51
- class Adapter
52
- extend AutoloadHelper
53
- autoload_all 'faraday/adapter',
54
- :NetHttp => 'net_http',
55
- :NetHttpPersistent => 'net_http_persistent',
56
- :EMSynchrony => 'em_synchrony',
57
- :EMHttp => 'em_http',
58
- :Typhoeus => 'typhoeus',
59
- :Patron => 'patron',
60
- :Excon => 'excon',
61
- :Test => 'test',
62
- :Rack => 'rack',
63
- :HTTPClient => 'httpclient'
64
- end
65
-
66
- class Request
67
- extend AutoloadHelper
68
- autoload_all 'faraday/request',
69
- :UrlEncoded => 'url_encoded',
70
- :Multipart => 'multipart',
71
- :Retry => 'retry',
72
- :Authorization => 'authorization',
73
- :BasicAuthentication => 'basic_authentication',
74
- :TokenAuthentication => 'token_authentication',
75
- :Instrumentation => 'instrumentation'
76
- end
77
-
78
- class Response
79
- extend AutoloadHelper
80
- autoload_all 'faraday/response',
81
- :RaiseError => 'raise_error',
82
- :Logger => 'logger'
83
- end
84
- end
@@ -1,13 +0,0 @@
1
- require 'base64'
2
-
3
- module Faraday
4
- class Request::BasicAuthentication < Request.load_middleware(:authorization)
5
- # Public
6
- def self.header(login, pass)
7
- value = Base64.encode64([login, pass].join(':'))
8
- value.gsub!("\n", '')
9
- super(:Basic, value)
10
- end
11
- end
12
- end
13
-
@@ -1,68 +0,0 @@
1
- require File.expand_path("../url_encoded", __FILE__)
2
- require 'securerandom'
3
-
4
- module Faraday
5
- class Request::Multipart < Request::UrlEncoded
6
- self.mime_type = 'multipart/form-data'.freeze
7
- DEFAULT_BOUNDARY_PREFIX = "-----------RubyMultipartPost".freeze unless defined? DEFAULT_BOUNDARY_PREFIX
8
-
9
- def call(env)
10
- match_content_type(env) do |params|
11
- env.request.boundary ||= unique_boundary
12
- env.request_headers[CONTENT_TYPE] += "; boundary=#{env.request.boundary}"
13
- env.body = create_multipart(env, params)
14
- end
15
- @app.call env
16
- end
17
-
18
- def process_request?(env)
19
- type = request_type(env)
20
- env.body.respond_to?(:each_key) and !env.body.empty? and (
21
- (type.empty? and has_multipart?(env.body)) or
22
- type == self.class.mime_type
23
- )
24
- end
25
-
26
- def has_multipart?(obj)
27
- # string is an enum in 1.8, returning list of itself
28
- if obj.respond_to?(:each) && !obj.is_a?(String)
29
- (obj.respond_to?(:values) ? obj.values : obj).each do |val|
30
- return true if (val.respond_to?(:content_type) || has_multipart?(val))
31
- end
32
- end
33
- false
34
- end
35
-
36
- def create_multipart(env, params)
37
- boundary = env.request.boundary
38
- parts = process_params(params) do |key, value|
39
- Faraday::Parts::Part.new(boundary, key, value)
40
- end
41
- parts << Faraday::Parts::EpiloguePart.new(boundary)
42
-
43
- body = Faraday::CompositeReadIO.new(parts)
44
- env.request_headers[Faraday::Env::ContentLength] = body.length.to_s
45
- return body
46
- end
47
-
48
- def unique_boundary
49
- "#{DEFAULT_BOUNDARY_PREFIX}-#{SecureRandom.hex}"
50
- end
51
-
52
- def process_params(params, prefix = nil, pieces = nil, &block)
53
- params.inject(pieces || []) do |all, (key, value)|
54
- key = "#{prefix}[#{key}]" if prefix
55
-
56
- case value
57
- when Array
58
- values = value.inject([]) { |a,v| a << [nil, v] }
59
- process_params(values, key, all, &block)
60
- when Hash
61
- process_params(value, key, all, &block)
62
- else
63
- all << block.call(key, value)
64
- end
65
- end
66
- end
67
- end
68
- end