faraday 0.9.1 → 0.16.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 (98) hide show
  1. checksums.yaml +5 -5
  2. data/LICENSE.md +1 -1
  3. data/README.md +30 -195
  4. data/lib/faraday/adapter/em_http.rb +148 -99
  5. data/lib/faraday/adapter/em_http_ssl_patch.rb +24 -18
  6. data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +18 -15
  7. data/lib/faraday/adapter/em_synchrony.rb +107 -49
  8. data/lib/faraday/adapter/excon.rb +102 -55
  9. data/lib/faraday/adapter/httpclient.rb +80 -36
  10. data/lib/faraday/adapter/net_http.rb +119 -44
  11. data/lib/faraday/adapter/net_http_persistent.rb +68 -27
  12. data/lib/faraday/adapter/patron.rb +76 -34
  13. data/lib/faraday/adapter/rack.rb +28 -12
  14. data/lib/faraday/adapter/test.rb +136 -52
  15. data/lib/faraday/adapter/typhoeus.rb +7 -115
  16. data/lib/faraday/adapter.rb +43 -20
  17. data/lib/faraday/adapter_registry.rb +28 -0
  18. data/lib/faraday/autoload.rb +47 -36
  19. data/lib/faraday/connection.rb +359 -165
  20. data/lib/faraday/dependency_loader.rb +37 -0
  21. data/lib/faraday/encoders/flat_params_encoder.rb +94 -0
  22. data/lib/faraday/encoders/nested_params_encoder.rb +171 -0
  23. data/lib/faraday/error.rb +71 -24
  24. data/lib/faraday/file_part.rb +128 -0
  25. data/lib/faraday/logging/formatter.rb +92 -0
  26. data/lib/faraday/middleware.rb +4 -28
  27. data/lib/faraday/middleware_registry.rb +129 -0
  28. data/lib/faraday/options/connection_options.rb +22 -0
  29. data/lib/faraday/options/env.rb +181 -0
  30. data/lib/faraday/options/proxy_options.rb +28 -0
  31. data/lib/faraday/options/request_options.rb +21 -0
  32. data/lib/faraday/options/ssl_options.rb +59 -0
  33. data/lib/faraday/options.rb +57 -185
  34. data/lib/faraday/param_part.rb +53 -0
  35. data/lib/faraday/parameters.rb +4 -180
  36. data/lib/faraday/rack_builder.rb +74 -38
  37. data/lib/faraday/request/authorization.rb +42 -31
  38. data/lib/faraday/request/basic_authentication.rb +14 -7
  39. data/lib/faraday/request/instrumentation.rb +45 -27
  40. data/lib/faraday/request/multipart.rb +81 -45
  41. data/lib/faraday/request/retry.rb +212 -121
  42. data/lib/faraday/request/token_authentication.rb +15 -10
  43. data/lib/faraday/request/url_encoded.rb +41 -23
  44. data/lib/faraday/request.rb +84 -30
  45. data/lib/faraday/response/logger.rb +22 -48
  46. data/lib/faraday/response/raise_error.rb +36 -14
  47. data/lib/faraday/response.rb +29 -18
  48. data/lib/faraday/utils/headers.rb +139 -0
  49. data/lib/faraday/utils/params_hash.rb +61 -0
  50. data/lib/faraday/utils.rb +28 -216
  51. data/lib/faraday.rb +102 -204
  52. data/spec/external_adapters/faraday_specs_setup.rb +14 -0
  53. metadata +24 -94
  54. data/.document +0 -6
  55. data/CHANGELOG.md +0 -20
  56. data/CONTRIBUTING.md +0 -36
  57. data/Gemfile +0 -25
  58. data/Rakefile +0 -71
  59. data/faraday.gemspec +0 -34
  60. data/lib/faraday/upload_io.rb +0 -67
  61. data/script/cached-bundle +0 -46
  62. data/script/console +0 -7
  63. data/script/generate_certs +0 -42
  64. data/script/package +0 -7
  65. data/script/proxy-server +0 -42
  66. data/script/release +0 -17
  67. data/script/s3-put +0 -71
  68. data/script/server +0 -36
  69. data/script/test +0 -172
  70. data/test/adapters/default_test.rb +0 -14
  71. data/test/adapters/em_http_test.rb +0 -20
  72. data/test/adapters/em_synchrony_test.rb +0 -20
  73. data/test/adapters/excon_test.rb +0 -20
  74. data/test/adapters/httpclient_test.rb +0 -21
  75. data/test/adapters/integration.rb +0 -254
  76. data/test/adapters/logger_test.rb +0 -82
  77. data/test/adapters/net_http_persistent_test.rb +0 -20
  78. data/test/adapters/net_http_test.rb +0 -14
  79. data/test/adapters/patron_test.rb +0 -20
  80. data/test/adapters/rack_test.rb +0 -31
  81. data/test/adapters/test_middleware_test.rb +0 -114
  82. data/test/adapters/typhoeus_test.rb +0 -28
  83. data/test/authentication_middleware_test.rb +0 -65
  84. data/test/composite_read_io_test.rb +0 -111
  85. data/test/connection_test.rb +0 -522
  86. data/test/env_test.rb +0 -218
  87. data/test/helper.rb +0 -81
  88. data/test/live_server.rb +0 -67
  89. data/test/middleware/instrumentation_test.rb +0 -88
  90. data/test/middleware/retry_test.rb +0 -177
  91. data/test/middleware_stack_test.rb +0 -173
  92. data/test/multibyte.txt +0 -1
  93. data/test/options_test.rb +0 -252
  94. data/test/parameters_test.rb +0 -64
  95. data/test/request_middleware_test.rb +0 -142
  96. data/test/response_middleware_test.rb +0 -72
  97. data/test/strawberry.rb +0 -2
  98. data/test/utils_test.rb +0 -58
@@ -1,148 +1,239 @@
1
+ # frozen_string_literal: true
2
+
1
3
  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, :interval_randomness, :backoff_factor,
26
- :exceptions, :methods, :retry_if)
27
- DEFAULT_CHECK = lambda { |env,exception| false }
28
-
29
- def self.from(value)
30
- if Fixnum === value
31
- new(value)
32
- else
33
- super(value)
4
+ class Request
5
+ # Catches exceptions and retries each request a limited number of times.
6
+ #
7
+ # By default, it retries 2 times and handles only timeout exceptions. It can
8
+ # be configured with an arbitrary number of retries, a list of exceptions to
9
+ # handle, a retry interval, a percentage of randomness to add to the retry
10
+ # interval, and a backoff factor.
11
+ #
12
+ # @example Configure Retry middleware using intervals
13
+ # Faraday.new do |conn|
14
+ # conn.request(:retry, max: 2,
15
+ # interval: 0.05,
16
+ # interval_randomness: 0.5,
17
+ # backoff_factor: 2,
18
+ # exceptions: [CustomException, 'Timeout::Error'])
19
+ #
20
+ # conn.adapter(:net_http) # NB: Last middleware must be the adapter
21
+ # end
22
+ #
23
+ # This example will result in a first interval that is random between 0.05
24
+ # and 0.075 and a second interval that is random between 0.1 and 0.15.
25
+ class Retry < Faraday::Middleware
26
+ DEFAULT_EXCEPTIONS = [
27
+ Errno::ETIMEDOUT, 'Timeout::Error',
28
+ Faraday::TimeoutError, Faraday::RetriableResponse
29
+ ].freeze
30
+ IDEMPOTENT_METHODS = %i[delete get head options put].freeze
31
+
32
+ # Options contains the configurable parameters for the Retry middleware.
33
+ class Options < Faraday::Options.new(:max, :interval, :max_interval,
34
+ :interval_randomness,
35
+ :backoff_factor, :exceptions,
36
+ :methods, :retry_if, :retry_block,
37
+ :retry_statuses)
38
+
39
+ DEFAULT_CHECK = ->(_env, _exception) { false }
40
+
41
+ def self.from(value)
42
+ if value.is_a?(Integer)
43
+ new(value)
44
+ else
45
+ super(value)
46
+ end
34
47
  end
35
- end
36
48
 
37
- def max
38
- (self[:max] ||= 2).to_i
39
- end
49
+ def max
50
+ (self[:max] ||= 2).to_i
51
+ end
40
52
 
41
- def interval
42
- (self[:interval] ||= 0).to_f
43
- end
53
+ def interval
54
+ (self[:interval] ||= 0).to_f
55
+ end
56
+
57
+ def max_interval
58
+ (self[:max_interval] ||= Float::MAX).to_f
59
+ end
44
60
 
45
- def interval_randomness
46
- (self[:interval_randomness] ||= 0).to_i
61
+ def interval_randomness
62
+ (self[:interval_randomness] ||= 0).to_f
63
+ end
64
+
65
+ def backoff_factor
66
+ (self[:backoff_factor] ||= 1).to_f
67
+ end
68
+
69
+ def exceptions
70
+ Array(self[:exceptions] ||= DEFAULT_EXCEPTIONS)
71
+ end
72
+
73
+ def methods
74
+ Array(self[:methods] ||= IDEMPOTENT_METHODS)
75
+ end
76
+
77
+ def retry_if
78
+ self[:retry_if] ||= DEFAULT_CHECK
79
+ end
80
+
81
+ def retry_block
82
+ self[:retry_block] ||= proc {}
83
+ end
84
+
85
+ def retry_statuses
86
+ Array(self[:retry_statuses] ||= [])
87
+ end
47
88
  end
48
89
 
49
- def backoff_factor
50
- (self[:backoff_factor] ||= 1).to_f
90
+ # @param app [#call]
91
+ # @param options [Hash]
92
+ # @option options [Integer] :max (2) Maximum number of retries
93
+ # @option options [Integer] :interval (0) Pause in seconds between retries
94
+ # @option options [Integer] :interval_randomness (0) The maximum random
95
+ # interval amount expressed as a float between
96
+ # 0 and 1 to use in addition to the interval.
97
+ # @option options [Integer] :max_interval (Float::MAX) An upper limit
98
+ # for the interval
99
+ # @option options [Integer] :backoff_factor (1) The amount to multiply
100
+ # each successive retry's interval amount by in order to provide backoff
101
+ # @option options [Array] :exceptions ([ Errno::ETIMEDOUT,
102
+ # 'Timeout::Error', Faraday::TimeoutError, Faraday::RetriableResponse])
103
+ # The list of exceptions to handle. Exceptions can be given as
104
+ # Class, Module, or String.
105
+ # @option options [Array] :methods (the idempotent HTTP methods
106
+ # in IDEMPOTENT_METHODS) A list of HTTP methods to retry without
107
+ # calling retry_if. Pass an empty Array to call retry_if
108
+ # for all exceptions.
109
+ # @option options [Block] :retry_if (false) block that will receive
110
+ # the env object and the exception raised
111
+ # and should decide if the code should retry still the action or
112
+ # not independent of the retry count. This would be useful
113
+ # if the exception produced is non-recoverable or if the
114
+ # the HTTP method called is not idempotent.
115
+ # @option options [Block] :retry_block block that is executed after
116
+ # every retry. Request environment, middleware options, current number
117
+ # of retries and the exception is passed to the block as parameters.
118
+ # @option options [Array] :retry_statuses Array of Integer HTTP status
119
+ # codes or a single Integer value that determines whether to raise
120
+ # a Faraday::RetriableResponse exception based on the HTTP status code
121
+ # of an HTTP response.
122
+ def initialize(app, options = nil)
123
+ super(app)
124
+ @options = Options.from(options)
125
+ @errmatch = build_exception_matcher(@options.exceptions)
51
126
  end
52
127
 
53
- def exceptions
54
- Array(self[:exceptions] ||= [Errno::ETIMEDOUT, 'Timeout::Error',
55
- Error::TimeoutError])
128
+ def calculate_sleep_amount(retries, env)
129
+ retry_after = calculate_retry_after(env)
130
+ retry_interval = calculate_retry_interval(retries)
131
+
132
+ return if retry_after && retry_after > @options.max_interval
133
+
134
+ if retry_after && retry_after >= retry_interval
135
+ retry_after
136
+ else
137
+ retry_interval
138
+ end
56
139
  end
57
140
 
58
- def methods
59
- Array(self[:methods] ||= IDEMPOTENT_METHODS)
141
+ # @param env [Faraday::Env]
142
+ def call(env)
143
+ retries = @options.max
144
+ request_body = env[:body]
145
+ begin
146
+ # after failure env[:body] is set to the response body
147
+ env[:body] = request_body
148
+ @app.call(env).tap do |resp|
149
+ if @options.retry_statuses.include?(resp.status)
150
+ raise Faraday::RetriableResponse.new(nil, resp)
151
+ end
152
+ end
153
+ rescue @errmatch => e
154
+ if retries.positive? && retry_request?(env, e)
155
+ retries -= 1
156
+ rewind_files(request_body)
157
+ @options.retry_block.call(env, @options, retries, e)
158
+ if (sleep_amount = calculate_sleep_amount(retries + 1, env))
159
+ sleep sleep_amount
160
+ retry
161
+ end
162
+ end
163
+
164
+ raise unless e.is_a?(Faraday::RetriableResponse)
165
+
166
+ e.response
167
+ end
60
168
  end
61
169
 
62
- def retry_if
63
- self[:retry_if] ||= DEFAULT_CHECK
170
+ # An exception matcher for the rescue clause can usually be any object
171
+ # that responds to `===`, but for Ruby 1.8 it has to be a Class or Module.
172
+ #
173
+ # @param exceptions [Array]
174
+ # @api private
175
+ # @return [Module] an exception matcher
176
+ def build_exception_matcher(exceptions)
177
+ matcher = Module.new
178
+ (
179
+ class << matcher
180
+ self
181
+ end).class_eval do
182
+ define_method(:===) do |error|
183
+ exceptions.any? do |ex|
184
+ if ex.is_a? Module
185
+ error.is_a? ex
186
+ else
187
+ error.class.to_s == ex.to_s
188
+ end
189
+ end
190
+ end
191
+ end
192
+ matcher
64
193
  end
65
194
 
66
- end
195
+ private
67
196
 
68
- # Public: Initialize middleware
69
- #
70
- # Options:
71
- # max - Maximum number of retries (default: 2)
72
- # interval - Pause in seconds between retries (default: 0)
73
- # interval_randomness - The maximum random interval amount expressed
74
- # as a float between 0 and 1 to use in addition to the
75
- # interval. (default: 0)
76
- # backoff_factor - The amount to multiple each successive retry's
77
- # interval amount by in order to provide backoff
78
- # (default: 1)
79
- # exceptions - The list of exceptions to handle. Exceptions can be
80
- # given as Class, Module, or String. (default:
81
- # [Errno::ETIMEDOUT, Timeout::Error,
82
- # Error::TimeoutError])
83
- # methods - A list of HTTP methods to retry without calling retry_if. Pass
84
- # an empty Array to call retry_if for all exceptions.
85
- # (defaults to the idempotent HTTP methods in IDEMPOTENT_METHODS)
86
- # retry_if - block that will receive the env object and the exception raised
87
- # and should decide if the code should retry still the action or
88
- # not independent of the retry count. This would be useful
89
- # if the exception produced is non-recoverable or if the
90
- # the HTTP method called is not idempotent.
91
- # (defaults to return false)
92
- def initialize(app, options = nil)
93
- super(app)
94
- @options = Options.from(options)
95
- @errmatch = build_exception_matcher(@options.exceptions)
96
- end
197
+ def retry_request?(env, exception)
198
+ @options.methods.include?(env[:method]) ||
199
+ @options.retry_if.call(env, exception)
200
+ end
97
201
 
98
- def sleep_amount(retries)
99
- retry_index = @options.max - retries
100
- current_interval = @options.interval * (@options.backoff_factor ** retry_index)
101
- random_interval = rand * @options.interval_randomness.to_f * @options.interval
102
- current_interval + random_interval
103
- end
202
+ def rewind_files(body)
203
+ return unless body.is_a?(Hash)
104
204
 
105
- def call(env)
106
- retries = @options.max
107
- request_body = env[:body]
108
- begin
109
- env[:body] = request_body # after failure env[:body] is set to the response body
110
- @app.call(env)
111
- rescue @errmatch => exception
112
- if retries > 0 && retry_request?(env, exception)
113
- retries -= 1
114
- sleep sleep_amount(retries + 1)
115
- retry
116
- end
117
- raise
205
+ body.each do |_, value|
206
+ value.rewind if value.is_a?(UploadIO)
207
+ end
118
208
  end
119
- end
120
209
 
121
- # Private: construct an exception matcher object.
122
- #
123
- # An exception matcher for the rescue clause can usually be any object that
124
- # responds to `===`, but for Ruby 1.8 it has to be a Class or Module.
125
- def build_exception_matcher(exceptions)
126
- matcher = Module.new
127
- (class << matcher; self; end).class_eval do
128
- define_method(:===) do |error|
129
- exceptions.any? do |ex|
130
- if ex.is_a? Module
131
- error.is_a? ex
132
- else
133
- error.class.to_s == ex.to_s
134
- end
135
- end
210
+ # MDN spec for Retry-After header:
211
+ # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After
212
+ def calculate_retry_after(env)
213
+ response_headers = env[:response_headers]
214
+ return unless response_headers
215
+
216
+ retry_after_value = env[:response_headers]['Retry-After']
217
+
218
+ # Try to parse date from the header value
219
+ begin
220
+ datetime = DateTime.rfc2822(retry_after_value)
221
+ datetime.to_time - Time.now.utc
222
+ rescue ArgumentError
223
+ retry_after_value.to_f
136
224
  end
137
225
  end
138
- matcher
139
- end
140
226
 
141
- private
227
+ def calculate_retry_interval(retries)
228
+ retry_index = @options.max - retries
229
+ current_interval = @options.interval *
230
+ (@options.backoff_factor**retry_index)
231
+ current_interval = [current_interval, @options.max_interval].min
232
+ random_interval = rand * @options.interval_randomness.to_f *
233
+ @options.interval
142
234
 
143
- def retry_request?(env, exception)
144
- @options.methods.include?(env[:method]) || @options.retry_if.call(env, exception)
235
+ current_interval + random_interval
236
+ end
145
237
  end
146
-
147
238
  end
148
239
  end
@@ -1,15 +1,20 @@
1
+ # frozen_string_literal: true
2
+
1
3
  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
4
+ class Request
5
+ # TokenAuthentication is a middleware that adds a 'Token' header to a
6
+ # Faraday request.
7
+ class TokenAuthentication < load_middleware(:authorization)
8
+ # Public
9
+ def self.header(token, options = nil)
10
+ options ||= {}
11
+ options[:token] = token
12
+ super(:Token, options)
13
+ end
9
14
 
10
- def initialize(app, token, options = nil)
11
- super(app, token, options)
15
+ def initialize(app, token, options = nil)
16
+ super(app, token, options)
17
+ end
12
18
  end
13
19
  end
14
20
  end
15
-
@@ -1,36 +1,54 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Faraday
2
- class Request::UrlEncoded < Faraday::Middleware
3
- CONTENT_TYPE = 'Content-Type'.freeze unless defined? CONTENT_TYPE
4
+ class Request
5
+ # Middleware for supporting urlencoded requests.
6
+ class UrlEncoded < Faraday::Middleware
7
+ CONTENT_TYPE = 'Content-Type' unless defined? CONTENT_TYPE
4
8
 
5
- class << self
6
- attr_accessor :mime_type
7
- end
8
- self.mime_type = 'application/x-www-form-urlencoded'.freeze
9
+ class << self
10
+ attr_accessor :mime_type
11
+ end
12
+ self.mime_type = 'application/x-www-form-urlencoded'
9
13
 
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)
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
14
24
  end
15
- @app.call env
16
- end
17
25
 
18
- def match_content_type(env)
19
- if process_request?(env)
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
+
20
31
  env.request_headers[CONTENT_TYPE] ||= self.class.mime_type
21
32
  yield(env.body) unless env.body.respond_to?(:to_str)
22
33
  end
23
- end
24
34
 
25
- def process_request?(env)
26
- type = request_type(env)
27
- env.body and (type.empty? or type == self.class.mime_type)
28
- end
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
29
43
 
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
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
34
52
  end
35
53
  end
36
54
  end
@@ -1,6 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Faraday
2
- # Used to setup urls, params, headers, and the request body in a sane manner.
4
+ # Used to setup URLs, params, headers, and the request body in a sane manner.
3
5
  #
6
+ # @example
4
7
  # @connection.post do |req|
5
8
  # req.url 'http://localhost', 'a' => '1' # 'http://localhost?a=1'
6
9
  # req.headers['b'] = '2' # Header
@@ -9,25 +12,53 @@ module Faraday
9
12
  # req.body = 'abc'
10
13
  # end
11
14
  #
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
12
29
  class Request < Struct.new(:method, :path, :params, :headers, :body, :options)
30
+ # rubocop:enable Style/StructInheritance
31
+
13
32
  extend MiddlewareRegistry
14
33
 
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']
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']
23
48
 
49
+ # @param request_method [String]
50
+ # @yield [request] for block customization, if block given
51
+ # @yieldparam request [Request]
52
+ # @return [Request]
24
53
  def self.create(request_method)
25
54
  new(request_method).tap do |request|
26
55
  yield(request) if block_given?
27
56
  end
28
57
  end
29
58
 
30
- # Public: Replace params, preserving the existing hash type
59
+ # Replace params, preserving the existing hash type.
60
+ #
61
+ # @param hash [Hash] new params
31
62
  def params=(hash)
32
63
  if params
33
64
  params.replace hash
@@ -36,7 +67,9 @@ module Faraday
36
67
  end
37
68
  end
38
69
 
39
- # Public: Replace request headers, preserving the existing hash type
70
+ # Replace request headers, preserving the existing hash type.
71
+ #
72
+ # @param hash [Hash] new headers
40
73
  def headers=(hash)
41
74
  if headers
42
75
  headers.replace hash
@@ -45,13 +78,20 @@ module Faraday
45
78
  end
46
79
  end
47
80
 
81
+ # Update path and params.
82
+ #
83
+ # @param path [URI, String]
84
+ # @param params [Hash, nil]
85
+ # @return [void]
48
86
  def url(path, params = nil)
49
87
  if path.respond_to? :query
50
- if query = path.query
88
+ if (query = path.query)
51
89
  path = path.dup
52
90
  path.query = nil
53
91
  end
54
92
  else
93
+ anchor_index = path.index('#')
94
+ path = path.slice(0, anchor_index) unless anchor_index.nil?
55
95
  path, query = path.split('?', 2)
56
96
  end
57
97
  self.path = path
@@ -59,34 +99,48 @@ module Faraday
59
99
  self.params.update(params) if params
60
100
  end
61
101
 
102
+ # @param key [Object] key to look up in headers
103
+ # @return [Object] value of the given header name
62
104
  def [](key)
63
105
  headers[key]
64
106
  end
65
107
 
108
+ # @param key [Object] key of header to write
109
+ # @param value [Object] value of header
66
110
  def []=(key, value)
67
111
  headers[key] = value
68
112
  end
69
113
 
70
- # ENV Keys
71
- # :method - a symbolized request method (:get, :post)
72
- # :body - the request body that will eventually be converted to a string.
73
- # :url - URI instance for the current request.
74
- # :status - HTTP response status code
75
- # :request_headers - hash of HTTP Headers to be sent to the server
76
- # :response_headers - Hash of HTTP headers from the server
77
- # :parallel_manager - sent if the connection is in parallel mode
78
- # :request - Hash of options for configuring the request.
79
- # :timeout - open/read timeout Integer in seconds
80
- # :open_timeout - read timeout Integer in seconds
81
- # :proxy - Hash of proxy options
82
- # :uri - Proxy Server URI
83
- # :user - Proxy server username
84
- # :password - Proxy server password
85
- # :ssl - Hash of options for configuring SSL requests.
114
+ # Marshal serialization support.
115
+ #
116
+ # @return [Hash] the hash ready to be serialized in Marshal.
117
+ def marshal_dump
118
+ {
119
+ method: method,
120
+ body: body,
121
+ headers: headers,
122
+ path: path,
123
+ params: params,
124
+ options: options
125
+ }
126
+ end
127
+
128
+ # Marshal serialization support.
129
+ # Restores the instance variables according to the +serialised+.
130
+ # @param serialised [Hash] the serialised object.
131
+ def marshal_load(serialised)
132
+ self.method = serialised[:method]
133
+ self.body = serialised[:body]
134
+ self.headers = serialised[:headers]
135
+ self.path = serialised[:path]
136
+ self.params = serialised[:params]
137
+ self.options = serialised[:options]
138
+ end
139
+
140
+ # @return [Env] the Env for this Request
86
141
  def to_env(connection)
87
142
  Env.new(method, body, connection.build_exclusive_url(path, params),
88
- options, headers, connection.ssl, connection.parallel_manager)
143
+ options, headers, connection.ssl, connection.parallel_manager)
89
144
  end
90
145
  end
91
146
  end
92
-