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,211 +0,0 @@
1
- module Faraday
2
- # Catches exceptions and retries each request a limited number of times.
3
- #
4
- # By default, it retries 2 times and handles only timeout exceptions. It can
5
- # be configured with an arbitrary number of retries, a list of exceptions to
6
- # handle, a retry interval, a percentage of randomness to add to the retry
7
- # interval, and a backoff factor.
8
- #
9
- # Examples
10
- #
11
- # Faraday.new do |conn|
12
- # conn.request :retry, max: 2, interval: 0.05,
13
- # interval_randomness: 0.5, backoff_factor: 2,
14
- # exceptions: [CustomException, 'Timeout::Error']
15
- # conn.adapter ...
16
- # end
17
- #
18
- # This example will result in a first interval that is random between 0.05 and 0.075 and a second
19
- # interval that is random between 0.1 and 0.15
20
- #
21
- class Request::Retry < Faraday::Middleware
22
-
23
- IDEMPOTENT_METHODS = [:delete, :get, :head, :options, :put]
24
-
25
- class Options < Faraday::Options.new(:max, :interval, :max_interval, :interval_randomness,
26
- :backoff_factor, :exceptions, :methods, :retry_if, :retry_block,
27
- :retry_statuses)
28
-
29
- DEFAULT_CHECK = lambda { |env,exception| false }
30
-
31
- def self.from(value)
32
- if Integer === value
33
- new(value)
34
- else
35
- super(value)
36
- end
37
- end
38
-
39
- def max
40
- (self[:max] ||= 2).to_i
41
- end
42
-
43
- def interval
44
- (self[:interval] ||= 0).to_f
45
- end
46
-
47
- def max_interval
48
- (self[:max_interval] ||= Float::MAX).to_f
49
- end
50
-
51
- def interval_randomness
52
- (self[:interval_randomness] ||= 0).to_f
53
- end
54
-
55
- def backoff_factor
56
- (self[:backoff_factor] ||= 1).to_f
57
- end
58
-
59
- def exceptions
60
- Array(self[:exceptions] ||= [Errno::ETIMEDOUT, 'Timeout::Error',
61
- Error::TimeoutError,
62
- Faraday::Error::RetriableResponse])
63
- end
64
-
65
- def methods
66
- Array(self[:methods] ||= IDEMPOTENT_METHODS)
67
- end
68
-
69
- def retry_if
70
- self[:retry_if] ||= DEFAULT_CHECK
71
- end
72
-
73
- def retry_block
74
- self[:retry_block] ||= Proc.new {}
75
- end
76
-
77
- def retry_statuses
78
- Array(self[:retry_statuses] ||= [])
79
- end
80
- end
81
-
82
- # Public: Initialize middleware
83
- #
84
- # Options:
85
- # max - Maximum number of retries (default: 2)
86
- # interval - Pause in seconds between retries (default: 0)
87
- # interval_randomness - The maximum random interval amount expressed
88
- # as a float between 0 and 1 to use in addition to the
89
- # interval. (default: 0)
90
- # max_interval - An upper limit for the interval (default: Float::MAX)
91
- # backoff_factor - The amount to multiple each successive retry's
92
- # interval amount by in order to provide backoff
93
- # (default: 1)
94
- # exceptions - The list of exceptions to handle. Exceptions can be
95
- # given as Class, Module, or String. (default:
96
- # [Errno::ETIMEDOUT, 'Timeout::Error',
97
- # Error::TimeoutError, Faraday::Error::RetriableResponse])
98
- # methods - A list of HTTP methods to retry without calling retry_if. Pass
99
- # an empty Array to call retry_if for all exceptions.
100
- # (defaults to the idempotent HTTP methods in IDEMPOTENT_METHODS)
101
- # retry_if - block that will receive the env object and the exception raised
102
- # and should decide if the code should retry still the action or
103
- # not independent of the retry count. This would be useful
104
- # if the exception produced is non-recoverable or if the
105
- # the HTTP method called is not idempotent.
106
- # (defaults to return false)
107
- # retry_block - block that is executed after every retry. Request environment, middleware options,
108
- # current number of retries and the exception is passed to the block as parameters.
109
- def initialize(app, options = nil)
110
- super(app)
111
- @options = Options.from(options)
112
- @errmatch = build_exception_matcher(@options.exceptions)
113
- end
114
-
115
- def calculate_sleep_amount(retries, env)
116
- retry_after = calculate_retry_after(env)
117
- retry_interval = calculate_retry_interval(retries)
118
-
119
- return if retry_after && retry_after > @options.max_interval
120
-
121
- retry_after && retry_after >= retry_interval ? retry_after : retry_interval
122
- end
123
-
124
- def call(env)
125
- retries = @options.max
126
- request_body = env[:body]
127
- begin
128
- env[:body] = request_body # after failure env[:body] is set to the response body
129
- @app.call(env).tap do |resp|
130
- raise Faraday::Error::RetriableResponse.new(nil, resp) if @options.retry_statuses.include?(resp.status)
131
- end
132
- rescue @errmatch => exception
133
- if retries > 0 && retry_request?(env, exception)
134
- retries -= 1
135
- rewind_files(request_body)
136
- @options.retry_block.call(env, @options, retries, exception)
137
- if (sleep_amount = calculate_sleep_amount(retries + 1, env))
138
- sleep sleep_amount
139
- retry
140
- end
141
- end
142
-
143
- if exception.is_a?(Faraday::Error::RetriableResponse)
144
- exception.response
145
- else
146
- raise
147
- end
148
- end
149
- end
150
-
151
- # Private: construct an exception matcher object.
152
- #
153
- # An exception matcher for the rescue clause can usually be any object that
154
- # responds to `===`, but for Ruby 1.8 it has to be a Class or Module.
155
- def build_exception_matcher(exceptions)
156
- matcher = Module.new
157
- (class << matcher; self; end).class_eval do
158
- define_method(:===) do |error|
159
- exceptions.any? do |ex|
160
- if ex.is_a? Module
161
- error.is_a? ex
162
- else
163
- error.class.to_s == ex.to_s
164
- end
165
- end
166
- end
167
- end
168
- matcher
169
- end
170
-
171
- private
172
-
173
- def retry_request?(env, exception)
174
- @options.methods.include?(env[:method]) || @options.retry_if.call(env, exception)
175
- end
176
-
177
- def rewind_files(body)
178
- return unless body.is_a?(Hash)
179
- body.each do |_, value|
180
- if value.is_a? UploadIO
181
- value.rewind
182
- end
183
- end
184
- end
185
-
186
- # MDN spec for Retry-After header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After
187
- def calculate_retry_after(env)
188
- response_headers = env[:response_headers]
189
- return unless response_headers
190
-
191
- retry_after_value = env[:response_headers]["Retry-After"]
192
-
193
- # Try to parse date from the header value
194
- begin
195
- datetime = DateTime.rfc2822(retry_after_value)
196
- datetime.to_time - Time.now.utc
197
- rescue ArgumentError
198
- retry_after_value.to_f
199
- end
200
- end
201
-
202
- def calculate_retry_interval(retries)
203
- retry_index = @options.max - retries
204
- current_interval = @options.interval * (@options.backoff_factor ** retry_index)
205
- current_interval = [current_interval, @options.max_interval].min
206
- random_interval = rand * @options.interval_randomness.to_f * @options.interval
207
-
208
- current_interval + random_interval
209
- end
210
- end
211
- end
@@ -1,15 +0,0 @@
1
- module Faraday
2
- class Request::TokenAuthentication < Request.load_middleware(:authorization)
3
- # Public
4
- def self.header(token, options = nil)
5
- options ||= {}
6
- options[:token] = token
7
- super(:Token, options)
8
- end
9
-
10
- def initialize(app, token, options = nil)
11
- super(app, token, options)
12
- end
13
- end
14
- end
15
-
@@ -1,67 +0,0 @@
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