faraday 0.17.1 → 1.1.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +69 -9
- data/LICENSE.md +1 -1
- data/README.md +17 -347
- data/Rakefile +1 -7
- data/examples/client_spec.rb +65 -0
- data/examples/client_test.rb +79 -0
- data/lib/faraday.rb +94 -176
- data/lib/faraday/adapter.rb +83 -22
- data/lib/faraday/adapter/em_http.rb +143 -100
- data/lib/faraday/adapter/em_http_ssl_patch.rb +24 -18
- data/lib/faraday/adapter/em_synchrony.rb +104 -60
- data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +18 -15
- data/lib/faraday/adapter/excon.rb +98 -56
- data/lib/faraday/adapter/httpclient.rb +83 -59
- data/lib/faraday/adapter/net_http.rb +130 -63
- data/lib/faraday/adapter/net_http_persistent.rb +51 -28
- data/lib/faraday/adapter/patron.rb +80 -43
- data/lib/faraday/adapter/rack.rb +30 -13
- data/lib/faraday/adapter/test.rb +86 -53
- data/lib/faraday/adapter/typhoeus.rb +4 -1
- data/lib/faraday/adapter_registry.rb +30 -0
- data/lib/faraday/autoload.rb +47 -36
- data/lib/faraday/connection.rb +312 -182
- data/lib/faraday/dependency_loader.rb +39 -0
- data/lib/faraday/encoders/flat_params_encoder.rb +105 -0
- data/lib/faraday/encoders/nested_params_encoder.rb +176 -0
- data/lib/faraday/error.rb +46 -25
- data/lib/faraday/file_part.rb +128 -0
- data/lib/faraday/logging/formatter.rb +105 -0
- data/lib/faraday/middleware.rb +12 -28
- data/lib/faraday/middleware_registry.rb +129 -0
- data/lib/faraday/options.rb +38 -193
- data/lib/faraday/options/connection_options.rb +22 -0
- data/lib/faraday/options/env.rb +181 -0
- data/lib/faraday/options/proxy_options.rb +28 -0
- data/lib/faraday/options/request_options.rb +22 -0
- data/lib/faraday/options/ssl_options.rb +59 -0
- data/lib/faraday/param_part.rb +53 -0
- data/lib/faraday/parameters.rb +4 -197
- data/lib/faraday/rack_builder.rb +77 -65
- data/lib/faraday/request.rb +86 -44
- data/lib/faraday/request/authorization.rb +44 -30
- data/lib/faraday/request/basic_authentication.rb +14 -7
- data/lib/faraday/request/instrumentation.rb +45 -27
- data/lib/faraday/request/multipart.rb +86 -48
- data/lib/faraday/request/retry.rb +197 -171
- data/lib/faraday/request/token_authentication.rb +15 -10
- data/lib/faraday/request/url_encoded.rb +43 -23
- data/lib/faraday/response.rb +24 -14
- data/lib/faraday/response/logger.rb +22 -69
- data/lib/faraday/response/raise_error.rb +49 -18
- data/lib/faraday/utils.rb +38 -247
- data/lib/faraday/utils/headers.rb +139 -0
- data/lib/faraday/utils/params_hash.rb +61 -0
- data/spec/external_adapters/faraday_specs_setup.rb +14 -0
- data/spec/faraday/adapter/em_http_spec.rb +47 -0
- data/spec/faraday/adapter/em_synchrony_spec.rb +16 -0
- data/spec/faraday/adapter/excon_spec.rb +49 -0
- data/spec/faraday/adapter/httpclient_spec.rb +73 -0
- data/spec/faraday/adapter/net_http_persistent_spec.rb +57 -0
- data/spec/faraday/adapter/net_http_spec.rb +64 -0
- data/spec/faraday/adapter/patron_spec.rb +18 -0
- data/spec/faraday/adapter/rack_spec.rb +8 -0
- data/spec/faraday/adapter/test_spec.rb +260 -0
- data/spec/faraday/adapter/typhoeus_spec.rb +7 -0
- data/spec/faraday/adapter_registry_spec.rb +28 -0
- data/spec/faraday/adapter_spec.rb +55 -0
- data/spec/faraday/composite_read_io_spec.rb +80 -0
- data/spec/faraday/connection_spec.rb +691 -0
- data/spec/faraday/error_spec.rb +0 -57
- data/spec/faraday/middleware_spec.rb +26 -0
- data/spec/faraday/options/env_spec.rb +70 -0
- data/spec/faraday/options/options_spec.rb +297 -0
- data/spec/faraday/options/proxy_options_spec.rb +37 -0
- data/spec/faraday/options/request_options_spec.rb +19 -0
- data/spec/faraday/params_encoders/flat_spec.rb +42 -0
- data/spec/faraday/params_encoders/nested_spec.rb +142 -0
- data/spec/faraday/rack_builder_spec.rb +345 -0
- data/spec/faraday/request/authorization_spec.rb +88 -0
- data/spec/faraday/request/instrumentation_spec.rb +76 -0
- data/spec/faraday/request/multipart_spec.rb +302 -0
- data/spec/faraday/request/retry_spec.rb +242 -0
- data/spec/faraday/request/url_encoded_spec.rb +83 -0
- data/spec/faraday/request_spec.rb +120 -0
- data/spec/faraday/response/logger_spec.rb +220 -0
- data/spec/faraday/response/middleware_spec.rb +68 -0
- data/spec/faraday/response/raise_error_spec.rb +60 -16
- data/spec/faraday/response_spec.rb +75 -0
- data/spec/faraday/utils/headers_spec.rb +82 -0
- data/spec/faraday/utils_spec.rb +56 -0
- data/spec/faraday_spec.rb +37 -0
- data/spec/spec_helper.rb +63 -35
- data/spec/support/disabling_stub.rb +14 -0
- data/spec/support/fake_safe_buffer.rb +15 -0
- data/spec/support/helper_methods.rb +133 -0
- data/spec/support/shared_examples/adapter.rb +104 -0
- data/spec/support/shared_examples/params_encoder.rb +18 -0
- data/spec/support/shared_examples/request_method.rb +234 -0
- data/spec/support/streaming_response_checker.rb +35 -0
- data/spec/support/webmock_rack_app.rb +68 -0
- metadata +80 -37
- data/lib/faraday/deprecate.rb +0 -101
- data/lib/faraday/upload_io.rb +0 -67
- data/spec/faraday/deprecate_spec.rb +0 -69
- data/test/adapters/default_test.rb +0 -14
- data/test/adapters/em_http_test.rb +0 -30
- data/test/adapters/em_synchrony_test.rb +0 -32
- data/test/adapters/excon_test.rb +0 -30
- data/test/adapters/httpclient_test.rb +0 -34
- data/test/adapters/integration.rb +0 -263
- data/test/adapters/logger_test.rb +0 -136
- data/test/adapters/net_http_persistent_test.rb +0 -114
- data/test/adapters/net_http_test.rb +0 -79
- data/test/adapters/patron_test.rb +0 -40
- data/test/adapters/rack_test.rb +0 -38
- data/test/adapters/test_middleware_test.rb +0 -157
- data/test/adapters/typhoeus_test.rb +0 -38
- data/test/authentication_middleware_test.rb +0 -65
- data/test/composite_read_io_test.rb +0 -109
- data/test/connection_test.rb +0 -738
- data/test/env_test.rb +0 -268
- data/test/helper.rb +0 -75
- data/test/live_server.rb +0 -67
- data/test/middleware/instrumentation_test.rb +0 -88
- data/test/middleware/retry_test.rb +0 -282
- data/test/middleware_stack_test.rb +0 -260
- data/test/multibyte.txt +0 -1
- data/test/options_test.rb +0 -333
- data/test/parameters_test.rb +0 -157
- data/test/request_middleware_test.rb +0 -126
- data/test/response_middleware_test.rb +0 -72
- data/test/strawberry.rb +0 -2
- data/test/utils_test.rb +0 -98
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'ruby2_keywords'
|
4
|
+
|
5
|
+
module Faraday
|
6
|
+
# DependencyLoader helps Faraday adapters and middleware load dependencies.
|
7
|
+
module DependencyLoader
|
8
|
+
attr_reader :load_error
|
9
|
+
|
10
|
+
# Executes a block which should try to require and reference dependent
|
11
|
+
# libraries
|
12
|
+
def dependency(lib = nil)
|
13
|
+
lib ? require(lib) : yield
|
14
|
+
rescue LoadError, NameError => e
|
15
|
+
self.load_error = e
|
16
|
+
end
|
17
|
+
|
18
|
+
ruby2_keywords def new(*)
|
19
|
+
unless loaded?
|
20
|
+
raise "missing dependency for #{self}: #{load_error.message}"
|
21
|
+
end
|
22
|
+
|
23
|
+
super
|
24
|
+
end
|
25
|
+
|
26
|
+
def loaded?
|
27
|
+
load_error.nil?
|
28
|
+
end
|
29
|
+
|
30
|
+
def inherited(subclass)
|
31
|
+
super
|
32
|
+
subclass.send(:load_error=, load_error)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
attr_writer :load_error
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Faraday
|
4
|
+
# FlatParamsEncoder manages URI params as a flat hash. Any Array values repeat
|
5
|
+
# the parameter multiple times.
|
6
|
+
module FlatParamsEncoder
|
7
|
+
class << self
|
8
|
+
extend Forwardable
|
9
|
+
def_delegators :'Faraday::Utils', :escape, :unescape
|
10
|
+
end
|
11
|
+
|
12
|
+
# Encode converts the given param into a URI querystring. Keys and values
|
13
|
+
# will converted to strings and appropriately escaped for the URI.
|
14
|
+
#
|
15
|
+
# @param params [Hash] query arguments to convert.
|
16
|
+
#
|
17
|
+
# @example
|
18
|
+
#
|
19
|
+
# encode({a: %w[one two three], b: true, c: "C"})
|
20
|
+
# # => 'a=one&a=two&a=three&b=true&c=C'
|
21
|
+
#
|
22
|
+
# @return [String] the URI querystring (without the leading '?')
|
23
|
+
def self.encode(params)
|
24
|
+
return nil if params.nil?
|
25
|
+
|
26
|
+
unless params.is_a?(Array)
|
27
|
+
unless params.respond_to?(:to_hash)
|
28
|
+
raise TypeError,
|
29
|
+
"Can't convert #{params.class} into Hash."
|
30
|
+
end
|
31
|
+
params = params.to_hash
|
32
|
+
params = params.map do |key, value|
|
33
|
+
key = key.to_s if key.is_a?(Symbol)
|
34
|
+
[key, value]
|
35
|
+
end
|
36
|
+
|
37
|
+
# Only to be used for non-Array inputs. Arrays should preserve order.
|
38
|
+
params.sort! if @sort_params
|
39
|
+
end
|
40
|
+
|
41
|
+
# The params have form [['key1', 'value1'], ['key2', 'value2']].
|
42
|
+
buffer = +''
|
43
|
+
params.each do |key, value|
|
44
|
+
encoded_key = escape(key)
|
45
|
+
if value.nil?
|
46
|
+
buffer << "#{encoded_key}&"
|
47
|
+
elsif value.is_a?(Array)
|
48
|
+
if value.empty?
|
49
|
+
buffer << "#{encoded_key}=&"
|
50
|
+
else
|
51
|
+
value.each do |sub_value|
|
52
|
+
encoded_value = escape(sub_value)
|
53
|
+
buffer << "#{encoded_key}=#{encoded_value}&"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
else
|
57
|
+
encoded_value = escape(value)
|
58
|
+
buffer << "#{encoded_key}=#{encoded_value}&"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
buffer.chop
|
62
|
+
end
|
63
|
+
|
64
|
+
# Decode converts the given URI querystring into a hash.
|
65
|
+
#
|
66
|
+
# @param query [String] query arguments to parse.
|
67
|
+
#
|
68
|
+
# @example
|
69
|
+
#
|
70
|
+
# decode('a=one&a=two&a=three&b=true&c=C')
|
71
|
+
# # => {"a"=>["one", "two", "three"], "b"=>"true", "c"=>"C"}
|
72
|
+
#
|
73
|
+
# @return [Hash] parsed keys and value strings from the querystring.
|
74
|
+
def self.decode(query)
|
75
|
+
return nil if query.nil?
|
76
|
+
|
77
|
+
empty_accumulator = {}
|
78
|
+
|
79
|
+
split_query = (query.split('&').map do |pair|
|
80
|
+
pair.split('=', 2) if pair && !pair.empty?
|
81
|
+
end).compact
|
82
|
+
split_query.each_with_object(empty_accumulator.dup) do |pair, accu|
|
83
|
+
pair[0] = unescape(pair[0])
|
84
|
+
pair[1] = true if pair[1].nil?
|
85
|
+
if pair[1].respond_to?(:to_str)
|
86
|
+
pair[1] = unescape(pair[1].to_str.tr('+', ' '))
|
87
|
+
end
|
88
|
+
if accu[pair[0]].is_a?(Array)
|
89
|
+
accu[pair[0]] << pair[1]
|
90
|
+
elsif accu[pair[0]]
|
91
|
+
accu[pair[0]] = [accu[pair[0]], pair[1]]
|
92
|
+
else
|
93
|
+
accu[pair[0]] = pair[1]
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
class << self
|
99
|
+
attr_accessor :sort_params
|
100
|
+
end
|
101
|
+
|
102
|
+
# Useful default for OAuth and caching.
|
103
|
+
@sort_params = true
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,176 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Faraday
|
4
|
+
# Sub-module for encoding parameters into query-string.
|
5
|
+
module EncodeMethods
|
6
|
+
# @param params [nil, Array, #to_hash] parameters to be encoded
|
7
|
+
#
|
8
|
+
# @return [String] the encoded params
|
9
|
+
#
|
10
|
+
# @raise [TypeError] if params can not be converted to a Hash
|
11
|
+
def encode(params)
|
12
|
+
return nil if params.nil?
|
13
|
+
|
14
|
+
unless params.is_a?(Array)
|
15
|
+
unless params.respond_to?(:to_hash)
|
16
|
+
raise TypeError, "Can't convert #{params.class} into Hash."
|
17
|
+
end
|
18
|
+
|
19
|
+
params = params.to_hash
|
20
|
+
params = params.map do |key, value|
|
21
|
+
key = key.to_s if key.is_a?(Symbol)
|
22
|
+
[key, value]
|
23
|
+
end
|
24
|
+
|
25
|
+
# Only to be used for non-Array inputs. Arrays should preserve order.
|
26
|
+
params.sort! if @sort_params
|
27
|
+
end
|
28
|
+
|
29
|
+
# The params have form [['key1', 'value1'], ['key2', 'value2']].
|
30
|
+
buffer = +''
|
31
|
+
params.each do |parent, value|
|
32
|
+
encoded_parent = escape(parent)
|
33
|
+
buffer << "#{encode_pair(encoded_parent, value)}&"
|
34
|
+
end
|
35
|
+
buffer.chop
|
36
|
+
end
|
37
|
+
|
38
|
+
protected
|
39
|
+
|
40
|
+
def encode_pair(parent, value)
|
41
|
+
if value.is_a?(Hash)
|
42
|
+
encode_hash(parent, value)
|
43
|
+
elsif value.is_a?(Array)
|
44
|
+
encode_array(parent, value)
|
45
|
+
elsif value.nil?
|
46
|
+
parent
|
47
|
+
else
|
48
|
+
encoded_value = escape(value)
|
49
|
+
"#{parent}=#{encoded_value}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def encode_hash(parent, value)
|
54
|
+
value = value.map { |key, val| [escape(key), val] }.sort
|
55
|
+
|
56
|
+
buffer = +''
|
57
|
+
value.each do |key, val|
|
58
|
+
new_parent = "#{parent}%5B#{key}%5D"
|
59
|
+
buffer << "#{encode_pair(new_parent, val)}&"
|
60
|
+
end
|
61
|
+
buffer.chop
|
62
|
+
end
|
63
|
+
|
64
|
+
def encode_array(parent, value)
|
65
|
+
new_parent = "#{parent}%5B%5D"
|
66
|
+
return new_parent if value.empty?
|
67
|
+
|
68
|
+
buffer = +''
|
69
|
+
value.each { |val| buffer << "#{encode_pair(new_parent, val)}&" }
|
70
|
+
buffer.chop
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Sub-module for decoding query-string into parameters.
|
75
|
+
module DecodeMethods
|
76
|
+
# @param query [nil, String]
|
77
|
+
#
|
78
|
+
# @return [Array<Array, String>] the decoded params
|
79
|
+
#
|
80
|
+
# @raise [TypeError] if the nesting is incorrect
|
81
|
+
def decode(query)
|
82
|
+
return nil if query.nil?
|
83
|
+
|
84
|
+
params = {}
|
85
|
+
query.split('&').each do |pair|
|
86
|
+
next if pair.empty?
|
87
|
+
|
88
|
+
key, value = pair.split('=', 2)
|
89
|
+
key = unescape(key)
|
90
|
+
value = unescape(value.tr('+', ' ')) if value
|
91
|
+
decode_pair(key, value, params)
|
92
|
+
end
|
93
|
+
|
94
|
+
dehash(params, 0)
|
95
|
+
end
|
96
|
+
|
97
|
+
protected
|
98
|
+
|
99
|
+
SUBKEYS_REGEX = /[^\[\]]+(?:\]?\[\])?/.freeze
|
100
|
+
|
101
|
+
def decode_pair(key, value, context)
|
102
|
+
subkeys = key.scan(SUBKEYS_REGEX)
|
103
|
+
subkeys.each_with_index do |subkey, i|
|
104
|
+
is_array = subkey =~ /[\[\]]+\Z/
|
105
|
+
subkey = $` if is_array
|
106
|
+
last_subkey = i == subkeys.length - 1
|
107
|
+
|
108
|
+
context = prepare_context(context, subkey, is_array, last_subkey)
|
109
|
+
add_to_context(is_array, context, value, subkey) if last_subkey
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def prepare_context(context, subkey, is_array, last_subkey)
|
114
|
+
if !last_subkey || is_array
|
115
|
+
context = new_context(subkey, is_array, context)
|
116
|
+
end
|
117
|
+
if context.is_a?(Array) && !is_array
|
118
|
+
context = match_context(context, subkey)
|
119
|
+
end
|
120
|
+
context
|
121
|
+
end
|
122
|
+
|
123
|
+
def new_context(subkey, is_array, context)
|
124
|
+
value_type = is_array ? Array : Hash
|
125
|
+
if context[subkey] && !context[subkey].is_a?(value_type)
|
126
|
+
raise TypeError, "expected #{value_type.name} " \
|
127
|
+
"(got #{context[subkey].class.name}) for param `#{subkey}'"
|
128
|
+
end
|
129
|
+
|
130
|
+
context[subkey] ||= value_type.new
|
131
|
+
end
|
132
|
+
|
133
|
+
def match_context(context, subkey)
|
134
|
+
context << {} if !context.last.is_a?(Hash) || context.last.key?(subkey)
|
135
|
+
context.last
|
136
|
+
end
|
137
|
+
|
138
|
+
def add_to_context(is_array, context, value, subkey)
|
139
|
+
is_array ? context << value : context[subkey] = value
|
140
|
+
end
|
141
|
+
|
142
|
+
# Internal: convert a nested hash with purely numeric keys into an array.
|
143
|
+
# FIXME: this is not compatible with Rack::Utils.parse_nested_query
|
144
|
+
# @!visibility private
|
145
|
+
def dehash(hash, depth)
|
146
|
+
hash.each do |key, value|
|
147
|
+
hash[key] = dehash(value, depth + 1) if value.is_a?(Hash)
|
148
|
+
end
|
149
|
+
|
150
|
+
if depth.positive? && !hash.empty? && hash.keys.all? { |k| k =~ /^\d+$/ }
|
151
|
+
hash.sort.map(&:last)
|
152
|
+
else
|
153
|
+
hash
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
# This is the default encoder for Faraday requests.
|
159
|
+
# Using this encoder, parameters will be encoded respecting their structure,
|
160
|
+
# so you can send objects such as Arrays or Hashes as parameters
|
161
|
+
# for your requests.
|
162
|
+
module NestedParamsEncoder
|
163
|
+
class << self
|
164
|
+
attr_accessor :sort_params
|
165
|
+
|
166
|
+
extend Forwardable
|
167
|
+
def_delegators :'Faraday::Utils', :escape, :unescape
|
168
|
+
end
|
169
|
+
|
170
|
+
# Useful default for OAuth and caching.
|
171
|
+
@sort_params = true
|
172
|
+
|
173
|
+
extend EncodeMethods
|
174
|
+
extend DecodeMethods
|
175
|
+
end
|
176
|
+
end
|
data/lib/faraday/error.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'faraday/deprecate'
|
4
|
-
|
5
3
|
# Faraday namespace.
|
6
4
|
module Faraday
|
7
5
|
# Faraday error base class.
|
@@ -9,18 +7,9 @@ module Faraday
|
|
9
7
|
attr_reader :response, :wrapped_exception
|
10
8
|
|
11
9
|
def initialize(exc, response = nil)
|
12
|
-
@wrapped_exception = nil
|
13
|
-
@response = response
|
14
|
-
|
15
|
-
if exc.respond_to?(:backtrace)
|
16
|
-
super(exc.message)
|
17
|
-
@wrapped_exception = exc
|
18
|
-
elsif exc.respond_to?(:each_key)
|
19
|
-
super("the server responded with status #{exc[:status]}")
|
20
|
-
@response = exc
|
21
|
-
else
|
22
|
-
super(exc.to_s)
|
23
|
-
end
|
10
|
+
@wrapped_exception = nil unless defined?(@wrapped_exception)
|
11
|
+
@response = nil unless defined?(@response)
|
12
|
+
super(exc_msg_and_response!(exc, response))
|
24
13
|
end
|
25
14
|
|
26
15
|
def backtrace
|
@@ -38,6 +27,46 @@ module Faraday
|
|
38
27
|
inner << " #{super}" if inner.empty?
|
39
28
|
%(#<#{self.class}#{inner}>)
|
40
29
|
end
|
30
|
+
|
31
|
+
protected
|
32
|
+
|
33
|
+
# Pulls out potential parent exception and response hash, storing them in
|
34
|
+
# instance variables.
|
35
|
+
# exc - Either an Exception, a string message, or a response hash.
|
36
|
+
# response - Hash
|
37
|
+
# :status - Optional integer HTTP response status
|
38
|
+
# :headers - String key/value hash of HTTP response header
|
39
|
+
# values.
|
40
|
+
# :body - Optional string HTTP response body.
|
41
|
+
# :request - Hash
|
42
|
+
# :method - Symbol with the request HTTP method.
|
43
|
+
# :url_path - String with the url path requested.
|
44
|
+
# :params - String key/value hash of query params
|
45
|
+
# present in the request.
|
46
|
+
# :headers - String key/value hash of HTTP request
|
47
|
+
# header values.
|
48
|
+
# :body - String HTTP request body.
|
49
|
+
#
|
50
|
+
# If a subclass has to call this, then it should pass a string message
|
51
|
+
# to `super`. See NilStatusError.
|
52
|
+
def exc_msg_and_response!(exc, response = nil)
|
53
|
+
if @response.nil? && @wrapped_exception.nil?
|
54
|
+
@wrapped_exception, msg, @response = exc_msg_and_response(exc, response)
|
55
|
+
return msg
|
56
|
+
end
|
57
|
+
|
58
|
+
exc.to_s
|
59
|
+
end
|
60
|
+
|
61
|
+
# Pulls out potential parent exception and response hash.
|
62
|
+
def exc_msg_and_response(exc, response = nil)
|
63
|
+
return [exc, exc.message, response] if exc.respond_to?(:backtrace)
|
64
|
+
|
65
|
+
return [nil, "the server responded with status #{exc[:status]}", exc] \
|
66
|
+
if exc.respond_to?(:each_key)
|
67
|
+
|
68
|
+
[nil, exc.to_s, response]
|
69
|
+
end
|
41
70
|
end
|
42
71
|
|
43
72
|
# Faraday client error class. Represents 4xx status responses.
|
@@ -85,9 +114,9 @@ module Faraday
|
|
85
114
|
|
86
115
|
# Raised by Faraday::Response::RaiseError in case of a nil status in response.
|
87
116
|
class NilStatusError < ServerError
|
88
|
-
def initialize(
|
89
|
-
|
90
|
-
super(
|
117
|
+
def initialize(exc, response = nil)
|
118
|
+
exc_msg_and_response!(exc, response)
|
119
|
+
super('http status could not be derived from the server response')
|
91
120
|
end
|
92
121
|
end
|
93
122
|
|
@@ -108,12 +137,4 @@ module Faraday
|
|
108
137
|
# @see Faraday::Request::Retry
|
109
138
|
class RetriableResponse < Error
|
110
139
|
end
|
111
|
-
|
112
|
-
%i[ClientError ConnectionFailed ResourceNotFound
|
113
|
-
ParsingError TimeoutError SSLError RetriableResponse].each do |const|
|
114
|
-
Error.const_set(
|
115
|
-
const,
|
116
|
-
DeprecatedClass.proxy_class(Faraday.const_get(const))
|
117
|
-
)
|
118
|
-
end
|
119
140
|
end
|
@@ -0,0 +1,128 @@
|
|
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
|