faraday 1.10.2 → 2.7.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +197 -3
  3. data/LICENSE.md +1 -1
  4. data/README.md +18 -16
  5. data/examples/client_spec.rb +41 -19
  6. data/examples/client_test.rb +48 -22
  7. data/lib/faraday/adapter/test.rb +59 -10
  8. data/lib/faraday/adapter.rb +5 -9
  9. data/lib/faraday/connection.rb +47 -129
  10. data/lib/faraday/encoders/nested_params_encoder.rb +13 -6
  11. data/lib/faraday/error.rb +3 -2
  12. data/lib/faraday/logging/formatter.rb +19 -2
  13. data/lib/faraday/middleware.rb +3 -1
  14. data/lib/faraday/middleware_registry.rb +17 -63
  15. data/lib/faraday/options/env.rb +31 -7
  16. data/lib/faraday/options/ssl_options.rb +11 -1
  17. data/lib/faraday/options.rb +3 -3
  18. data/lib/faraday/rack_builder.rb +23 -20
  19. data/lib/faraday/request/authorization.rb +33 -41
  20. data/lib/faraday/request/instrumentation.rb +2 -0
  21. data/lib/faraday/request/url_encoded.rb +5 -1
  22. data/lib/faraday/request.rb +7 -25
  23. data/lib/faraday/response/json.rb +4 -4
  24. data/lib/faraday/response/logger.rb +6 -0
  25. data/lib/faraday/response/raise_error.rb +9 -1
  26. data/lib/faraday/response.rb +9 -21
  27. data/lib/faraday/utils/headers.rb +7 -2
  28. data/lib/faraday/utils.rb +10 -5
  29. data/lib/faraday/version.rb +1 -1
  30. data/lib/faraday.rb +8 -44
  31. data/spec/faraday/adapter/test_spec.rb +65 -0
  32. data/spec/faraday/connection_spec.rb +163 -91
  33. data/spec/faraday/middleware_registry_spec.rb +31 -0
  34. data/spec/faraday/middleware_spec.rb +18 -0
  35. data/spec/faraday/options/env_spec.rb +8 -2
  36. data/spec/faraday/params_encoders/nested_spec.rb +8 -0
  37. data/spec/faraday/rack_builder_spec.rb +26 -54
  38. data/spec/faraday/request/authorization_spec.rb +50 -28
  39. data/spec/faraday/request/instrumentation_spec.rb +5 -7
  40. data/spec/faraday/request/url_encoded_spec.rb +12 -2
  41. data/spec/faraday/request_spec.rb +5 -15
  42. data/spec/faraday/response/json_spec.rb +4 -6
  43. data/spec/faraday/response/logger_spec.rb +28 -0
  44. data/spec/faraday/response/raise_error_spec.rb +7 -4
  45. data/spec/faraday/response_spec.rb +3 -1
  46. data/spec/faraday/utils/headers_spec.rb +22 -4
  47. data/spec/faraday/utils_spec.rb +63 -1
  48. data/spec/spec_helper.rb +0 -2
  49. data/spec/support/fake_safe_buffer.rb +1 -1
  50. data/spec/support/helper_methods.rb +0 -37
  51. data/spec/support/shared_examples/adapter.rb +2 -2
  52. data/spec/support/shared_examples/request_method.rb +22 -21
  53. metadata +14 -151
  54. data/lib/faraday/adapter/typhoeus.rb +0 -15
  55. data/lib/faraday/autoload.rb +0 -87
  56. data/lib/faraday/dependency_loader.rb +0 -37
  57. data/lib/faraday/deprecate.rb +0 -110
  58. data/lib/faraday/request/basic_authentication.rb +0 -20
  59. data/lib/faraday/request/token_authentication.rb +0 -20
  60. data/spec/faraday/adapter/em_http_spec.rb +0 -49
  61. data/spec/faraday/adapter/em_synchrony_spec.rb +0 -18
  62. data/spec/faraday/adapter/excon_spec.rb +0 -49
  63. data/spec/faraday/adapter/httpclient_spec.rb +0 -73
  64. data/spec/faraday/adapter/net_http_spec.rb +0 -64
  65. data/spec/faraday/adapter/patron_spec.rb +0 -18
  66. data/spec/faraday/adapter/rack_spec.rb +0 -8
  67. data/spec/faraday/adapter/typhoeus_spec.rb +0 -7
  68. data/spec/faraday/composite_read_io_spec.rb +0 -80
  69. data/spec/faraday/deprecate_spec.rb +0 -147
  70. data/spec/faraday/response/middleware_spec.rb +0 -68
  71. data/spec/support/webmock_rack_app.rb +0 -68
@@ -6,59 +6,26 @@ module Faraday
6
6
  # Adds the ability for other modules to register and lookup
7
7
  # middleware classes.
8
8
  module MiddlewareRegistry
9
+ def registered_middleware
10
+ @registered_middleware ||= {}
11
+ end
12
+
9
13
  # Register middleware class(es) on the current module.
10
14
  #
11
- # @param autoload_path [String] Middleware autoload path
12
- # @param mapping [Hash{
13
- # Symbol => Module,
14
- # Symbol => Array<Module, Symbol, String>,
15
- # }] Middleware mapping from a lookup symbol to a reference to the
16
- # middleware.
17
- # Classes can be expressed as:
18
- # - a fully qualified constant
19
- # - a Symbol
20
- # - a Proc that will be lazily called to return the former
21
- # - an array is given, its first element is the constant or symbol,
22
- # and its second is a file to `require`.
15
+ # @param mappings [Hash] Middleware mappings from a lookup symbol to a middleware class.
23
16
  # @return [void]
24
17
  #
25
18
  # @example Lookup by a constant
26
19
  #
27
20
  # module Faraday
28
- # class Whatever
21
+ # class Whatever < Middleware
29
22
  # # Middleware looked up by :foo returns Faraday::Whatever::Foo.
30
- # register_middleware foo: Foo
31
- # end
32
- # end
33
- #
34
- # @example Lookup by a symbol
35
- #
36
- # module Faraday
37
- # class Whatever
38
- # # Middleware looked up by :bar returns
39
- # # Faraday::Whatever.const_get(:Bar)
40
- # register_middleware bar: :Bar
41
- # end
42
- # end
43
- #
44
- # @example Lookup by a symbol and string in an array
45
- #
46
- # module Faraday
47
- # class Whatever
48
- # # Middleware looked up by :baz requires 'baz' and returns
49
- # # Faraday::Whatever.const_get(:Baz)
50
- # register_middleware baz: [:Baz, 'baz']
23
+ # register_middleware(foo: Whatever)
51
24
  # end
52
25
  # end
53
- #
54
- def register_middleware(autoload_path = nil, mapping = nil)
55
- if mapping.nil?
56
- mapping = autoload_path
57
- autoload_path = nil
58
- end
26
+ def register_middleware(**mappings)
59
27
  middleware_mutex do
60
- @middleware_autoload_path = autoload_path if autoload_path
61
- (@registered_middleware ||= {}).update(mapping)
28
+ registered_middleware.update(mappings)
62
29
  end
63
30
  end
64
31
 
@@ -66,7 +33,7 @@ module Faraday
66
33
  #
67
34
  # @param key [Symbol] key for the registered middleware.
68
35
  def unregister_middleware(key)
69
- @registered_middleware.delete(key)
36
+ registered_middleware.delete(key)
70
37
  end
71
38
 
72
39
  # Lookup middleware class with a registered Symbol shortcut.
@@ -78,30 +45,27 @@ module Faraday
78
45
  # @example
79
46
  #
80
47
  # module Faraday
81
- # class Whatever
82
- # register_middleware foo: Foo
48
+ # class Whatever < Middleware
49
+ # register_middleware(foo: Whatever)
83
50
  # end
84
51
  # end
85
52
  #
86
- # Faraday::Whatever.lookup_middleware(:foo)
87
- # # => Faraday::Whatever::Foo
88
- #
53
+ # Faraday::Middleware.lookup_middleware(:foo)
54
+ # # => Faraday::Whatever
89
55
  def lookup_middleware(key)
90
56
  load_middleware(key) ||
91
57
  raise(Faraday::Error, "#{key.inspect} is not registered on #{self}")
92
58
  end
93
59
 
60
+ private
61
+
94
62
  def middleware_mutex(&block)
95
63
  @middleware_mutex ||= Monitor.new
96
64
  @middleware_mutex.synchronize(&block)
97
65
  end
98
66
 
99
- def fetch_middleware(key)
100
- defined?(@registered_middleware) && @registered_middleware[key]
101
- end
102
-
103
67
  def load_middleware(key)
104
- value = fetch_middleware(key)
68
+ value = registered_middleware[key]
105
69
  case value
106
70
  when Module
107
71
  value
@@ -113,16 +77,6 @@ module Faraday
113
77
  middleware_mutex do
114
78
  @registered_middleware[key] = value.call
115
79
  end
116
- when Array
117
- middleware_mutex do
118
- const, path = value
119
- if (root = @middleware_autoload_path)
120
- path = "#{root}/#{path}"
121
- end
122
- require(path)
123
- @registered_middleware[key] = const
124
- end
125
- load_middleware(key)
126
80
  end
127
81
  end
128
82
  end
@@ -15,13 +15,19 @@ module Faraday
15
15
  # @return [Hash] options for configuring the request.
16
16
  # Options for configuring the request.
17
17
  #
18
- # - `:timeout` open/read timeout Integer in seconds
19
- # - `:open_timeout` - read timeout Integer in seconds
20
- # - `:on_data` - Proc for streaming
21
- # - `:proxy` - Hash of proxy options
22
- # - `:uri` - Proxy Server URI
23
- # - `:user` - Proxy server username
24
- # - `:password` - Proxy server password
18
+ # - `:timeout` - time limit for the entire request (Integer in
19
+ # seconds)
20
+ # - `:open_timeout` - time limit for just the connection phase (e.g.
21
+ # handshake) (Integer in seconds)
22
+ # - `:read_timeout` - time limit for the first response byte received from
23
+ # the server (Integer in seconds)
24
+ # - `:write_timeout` - time limit for the client to send the request to the
25
+ # server (Integer in seconds)
26
+ # - `:on_data` - Proc for streaming
27
+ # - `:proxy` - Hash of proxy options
28
+ # - `:uri` - Proxy server URI
29
+ # - `:user` - Proxy server username
30
+ # - `:password` - Proxy server password
25
31
  #
26
32
  # @!attribute request_headers
27
33
  # @return [Hash] HTTP Headers to be sent to the server.
@@ -157,6 +163,24 @@ module Faraday
157
163
  %(#<#{self.class}#{attrs.join(' ')}>)
158
164
  end
159
165
 
166
+ def stream_response?
167
+ request.stream_response?
168
+ end
169
+
170
+ def stream_response(&block)
171
+ size = 0
172
+ yielded = false
173
+ block_result = block.call do |chunk| # rubocop:disable Performance/RedundantBlockCall
174
+ if chunk.bytesize.positive? || size.positive?
175
+ yielded = true
176
+ size += chunk.bytesize
177
+ request.on_data.call(chunk, size, self)
178
+ end
179
+ end
180
+ request.on_data.call(+'', 0, self) unless yielded
181
+ block_result
182
+ end
183
+
160
184
  # @private
161
185
  def custom_members
162
186
  @custom_members ||= {}
@@ -6,6 +6,10 @@ module Faraday
6
6
  # @!attribute verify
7
7
  # @return [Boolean] whether to verify SSL certificates or not
8
8
  #
9
+ # @!attribute verify_hostname
10
+ # @return [Boolean] whether to enable hostname verification on server certificates
11
+ # during the handshake or not (see https://github.com/ruby/openssl/pull/60)
12
+ #
9
13
  # @!attribute ca_file
10
14
  # @return [String] CA file
11
15
  #
@@ -41,7 +45,8 @@ module Faraday
41
45
  #
42
46
  # @!attribute max_version
43
47
  # @return [String, Symbol] maximum SSL version (see https://ruby-doc.org/stdlib-2.5.1/libdoc/openssl/rdoc/OpenSSL/SSL/SSLContext.html#method-i-max_version-3D)
44
- class SSLOptions < Options.new(:verify, :ca_file, :ca_path, :verify_mode,
48
+ class SSLOptions < Options.new(:verify, :verify_hostname,
49
+ :ca_file, :ca_path, :verify_mode,
45
50
  :cert_store, :client_cert, :client_key,
46
51
  :certificate, :private_key, :verify_depth,
47
52
  :version, :min_version, :max_version)
@@ -55,5 +60,10 @@ module Faraday
55
60
  def disable?
56
61
  !verify?
57
62
  end
63
+
64
+ # @return [Boolean] true if should verify_hostname
65
+ def verify_hostname?
66
+ verify_hostname != false
67
+ end
58
68
  end
59
69
  end
@@ -104,7 +104,7 @@ module Faraday
104
104
 
105
105
  # Public
106
106
  def each_key(&block)
107
- return to_enum(:each_key) unless block_given?
107
+ return to_enum(:each_key) unless block
108
108
 
109
109
  keys.each(&block)
110
110
  end
@@ -118,7 +118,7 @@ module Faraday
118
118
 
119
119
  # Public
120
120
  def each_value(&block)
121
- return to_enum(:each_value) unless block_given?
121
+ return to_enum(:each_value) unless block
122
122
 
123
123
  values.each(&block)
124
124
  end
@@ -168,7 +168,7 @@ module Faraday
168
168
  end
169
169
 
170
170
  def self.memoized(key, &block)
171
- unless block_given?
171
+ unless block
172
172
  raise ArgumentError, '#memoized must be called with a block'
173
173
  end
174
174
 
@@ -8,7 +8,7 @@ module Faraday
8
8
  # middleware stack (heavily inspired by Rack).
9
9
  #
10
10
  # @example
11
- # Faraday::Connection.new(url: 'http://sushi.com') do |builder|
11
+ # Faraday::Connection.new(url: 'http://httpbingo.org') do |builder|
12
12
  # builder.request :url_encoded # Faraday::Request::UrlEncoded
13
13
  # builder.adapter :net_http # Faraday::Adapter::NetHttp
14
14
  # end
@@ -58,23 +58,22 @@ module Faraday
58
58
  end
59
59
  end
60
60
 
61
- def initialize(handlers = [], adapter = nil, &block)
62
- @adapter = adapter
63
- @handlers = handlers
64
- if block_given?
65
- build(&block)
66
- elsif @handlers.empty?
67
- # default stack, if nothing else is configured
68
- request :url_encoded
69
- self.adapter Faraday.default_adapter
70
- end
61
+ def initialize(&block)
62
+ @adapter = nil
63
+ @handlers = []
64
+ build(&block)
65
+ end
66
+
67
+ def initialize_dup(original)
68
+ super
69
+ @adapter = original.adapter
70
+ @handlers = original.handlers.dup
71
71
  end
72
72
 
73
- def build(options = {})
73
+ def build
74
74
  raise_if_locked
75
- @handlers.clear unless options[:keep]
76
- yield(self) if block_given?
77
- adapter(Faraday.default_adapter) unless @adapter
75
+ block_given? ? yield(self) : request(:url_encoded)
76
+ adapter(Faraday.default_adapter, **Faraday.default_adapter_options) unless @adapter
78
77
  end
79
78
 
80
79
  def [](idx)
@@ -109,7 +108,7 @@ module Faraday
109
108
  end
110
109
 
111
110
  ruby2_keywords def adapter(klass = NO_ARGUMENT, *args, &block)
112
- return @adapter if klass == NO_ARGUMENT
111
+ return @adapter if klass == NO_ARGUMENT || klass.nil?
113
112
 
114
113
  klass = Faraday::Adapter.lookup_middleware(klass) if klass.is_a?(Symbol)
115
114
  @adapter = self.class::Handler.new(klass, *args, &block)
@@ -164,6 +163,7 @@ module Faraday
164
163
  def app
165
164
  @app ||= begin
166
165
  lock!
166
+ ensure_adapter!
167
167
  to_app
168
168
  end
169
169
  end
@@ -182,10 +182,6 @@ module Faraday
182
182
  @adapter == other.adapter
183
183
  end
184
184
 
185
- def dup
186
- self.class.new(@handlers.dup, @adapter.dup)
187
- end
188
-
189
185
  # ENV Keys
190
186
  # :http_method - a symbolized request HTTP method (:get, :post)
191
187
  # :body - the request body that will eventually be converted to a string.
@@ -216,6 +212,9 @@ module Faraday
216
212
  private
217
213
 
218
214
  LOCK_ERR = "can't modify middleware stack after making a request"
215
+ MISSING_ADAPTER_ERROR = "An attempt to run a request with a Faraday::Connection without adapter has been made.\n" \
216
+ "Please set Faraday.default_adapter or provide one when initializing the connection.\n" \
217
+ 'For more info, check https://lostisland.github.io/faraday/usage/.'
219
218
 
220
219
  def raise_if_locked
221
220
  raise StackLocked, LOCK_ERR if locked?
@@ -227,6 +226,10 @@ module Faraday
227
226
  raise 'Adapter should be set using the `adapter` method, not `use`'
228
227
  end
229
228
 
229
+ def ensure_adapter!
230
+ raise MISSING_ADAPTER_ERROR unless @adapter
231
+ end
232
+
230
233
  def adapter_set?
231
234
  !@adapter.nil?
232
235
  end
@@ -1,53 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'base64'
4
-
5
3
  module Faraday
6
4
  class Request
7
5
  # Request middleware for the Authorization HTTP header
8
6
  class Authorization < Faraday::Middleware
9
- unless defined?(::Faraday::Request::Authorization::KEY)
10
- KEY = 'Authorization'
11
- end
12
-
13
- # @param type [String, Symbol]
14
- # @param token [String, Symbol, Hash]
15
- # @return [String] a header value
16
- def self.header(type, token)
17
- case token
18
- when String, Symbol, Proc
19
- token = token.call if token.is_a?(Proc)
20
- "#{type} #{token}"
21
- when Hash
22
- build_hash(type.to_s, token)
23
- else
24
- raise ArgumentError,
25
- "Can't build an Authorization #{type}" \
26
- "header from #{token.inspect}"
27
- end
28
- end
29
-
30
- # @param type [String]
31
- # @param hash [Hash]
32
- # @return [String] type followed by comma-separated key=value pairs
33
- # @api private
34
- def self.build_hash(type, hash)
35
- comma = ', '
36
- values = []
37
- hash.each do |key, value|
38
- value = value.call if value.is_a?(Proc)
39
- values << "#{key}=#{value.to_s.inspect}"
40
- end
41
- "#{type} #{values * comma}"
42
- end
7
+ KEY = 'Authorization'
43
8
 
44
9
  # @param app [#call]
45
10
  # @param type [String, Symbol] Type of Authorization
46
- # @param param [String, Symbol, Hash, Proc] parameter to build the Authorization header.
47
- # This value can be a proc, in which case it will be invoked on each request.
48
- def initialize(app, type, param)
11
+ # @param params [Array<String, Proc, #call>] parameters to build the Authorization header.
12
+ # If the type is `:basic`, then these can be a login and password pair.
13
+ # Otherwise, a single value is expected that will be appended after the type.
14
+ # This value can be a proc or an object responding to `.call`, in which case
15
+ # it will be invoked on each request.
16
+ def initialize(app, type, *params)
49
17
  @type = type
50
- @param = param
18
+ @params = params
51
19
  super(app)
52
20
  end
53
21
 
@@ -55,8 +23,32 @@ module Faraday
55
23
  def on_request(env)
56
24
  return if env.request_headers[KEY]
57
25
 
58
- env.request_headers[KEY] = self.class.header(@type, @param)
26
+ env.request_headers[KEY] = header_from(@type, env, *@params)
27
+ end
28
+
29
+ private
30
+
31
+ # @param type [String, Symbol]
32
+ # @param env [Faraday::Env]
33
+ # @param params [Array]
34
+ # @return [String] a header value
35
+ def header_from(type, env, *params)
36
+ if type.to_s.casecmp('basic').zero? && params.size == 2
37
+ Utils.basic_header_from(*params)
38
+ elsif params.size != 1
39
+ raise ArgumentError, "Unexpected params received (got #{params.size} instead of 1)"
40
+ else
41
+ value = params.first
42
+ if (value.is_a?(Proc) && value.arity == 1) || (value.respond_to?(:call) && value.method(:call).arity == 1)
43
+ value = value.call(env)
44
+ elsif value.is_a?(Proc) || value.respond_to?(:call)
45
+ value = value.call
46
+ end
47
+ "#{type} #{value}"
48
+ end
59
49
  end
60
50
  end
61
51
  end
62
52
  end
53
+
54
+ Faraday::Request.register_middleware(authorization: Faraday::Request::Authorization)
@@ -52,3 +52,5 @@ module Faraday
52
52
  end
53
53
  end
54
54
  end
55
+
56
+ Faraday::Request.register_middleware(instrumentation: Faraday::Request::Instrumentation)
@@ -31,7 +31,9 @@ module Faraday
31
31
  return unless process_request?(env)
32
32
 
33
33
  env.request_headers[CONTENT_TYPE] ||= self.class.mime_type
34
- yield(env.body) unless env.body.respond_to?(:to_str)
34
+ return if env.body.respond_to?(:to_str) || env.body.respond_to?(:read)
35
+
36
+ yield(env.body)
35
37
  end
36
38
 
37
39
  # @param env [Faraday::Env]
@@ -54,3 +56,5 @@ module Faraday
54
56
  end
55
57
  end
56
58
  end
59
+
60
+ Faraday::Request.register_middleware(url_encoded: Faraday::Request::UrlEncoded)
@@ -21,32 +21,16 @@ module Faraday
21
21
  # @!attribute headers
22
22
  # @return [Faraday::Utils::Headers] headers
23
23
  # @!attribute body
24
- # @return [Hash] body
24
+ # @return [String] body
25
25
  # @!attribute options
26
26
  # @return [RequestOptions] options
27
27
  #
28
28
  # rubocop:disable Style/StructInheritance
29
- class Request < Struct.new(
30
- :http_method, :path, :params, :headers, :body, :options
31
- )
29
+ class Request < Struct.new(:http_method, :path, :params, :headers, :body, :options)
32
30
  # rubocop:enable Style/StructInheritance
33
31
 
34
32
  extend MiddlewareRegistry
35
33
 
36
- register_middleware File.expand_path('request', __dir__),
37
- url_encoded: [:UrlEncoded, 'url_encoded'],
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'],
48
- json: [:Json, 'json']
49
-
50
34
  # @param request_method [String]
51
35
  # @yield [request] for block customization, if block given
52
36
  # @yieldparam request [Request]
@@ -57,13 +41,6 @@ module Faraday
57
41
  end
58
42
  end
59
43
 
60
- def method
61
- http_method
62
- end
63
-
64
- extend Faraday::Deprecate
65
- deprecate :method, :http_method, '2.0'
66
-
67
44
  # Replace params, preserving the existing hash type.
68
45
  #
69
46
  # @param hash [Hash] new params
@@ -152,3 +129,8 @@ module Faraday
152
129
  end
153
130
  end
154
131
  end
132
+
133
+ require 'faraday/request/authorization'
134
+ require 'faraday/request/instrumentation'
135
+ require 'faraday/request/json'
136
+ require 'faraday/request/url_encoded'
@@ -6,11 +6,11 @@ module Faraday
6
6
  class Response
7
7
  # Parse response bodies as JSON.
8
8
  class Json < Middleware
9
- def initialize(app = nil, options = {})
9
+ def initialize(app = nil, parser_options: nil, content_type: /\bjson$/, preserve_raw: false)
10
10
  super(app)
11
- @parser_options = options[:parser_options]
12
- @content_types = Array(options[:content_type] || /\bjson$/)
13
- @preserve_raw = options[:preserve_raw]
11
+ @parser_options = parser_options
12
+ @content_types = Array(content_type)
13
+ @preserve_raw = preserve_raw
14
14
  end
15
15
 
16
16
  def on_complete(env)
@@ -26,6 +26,12 @@ module Faraday
26
26
  def on_complete(env)
27
27
  @formatter.response(env)
28
28
  end
29
+
30
+ def on_error(exc)
31
+ @formatter.exception(exc) if @formatter.respond_to?(:exception)
32
+ end
29
33
  end
30
34
  end
31
35
  end
36
+
37
+ Faraday::Response.register_middleware(logger: Faraday::Response::Logger)
@@ -44,13 +44,21 @@ module Faraday
44
44
  body: env.body,
45
45
  request: {
46
46
  method: env.method,
47
+ url: env.url,
47
48
  url_path: env.url.path,
48
- params: env.params,
49
+ params: query_params(env),
49
50
  headers: env.request_headers,
50
51
  body: env.request_body
51
52
  }
52
53
  }
53
54
  end
55
+
56
+ def query_params(env)
57
+ env.request.params_encoder ||= Faraday::Utils.default_params_encoder
58
+ env.params_encoder.decode(env.url.query)
59
+ end
54
60
  end
55
61
  end
56
62
  end
63
+
64
+ Faraday::Response.register_middleware(raise_error: Faraday::Response::RaiseError)
@@ -5,26 +5,9 @@ require 'forwardable'
5
5
  module Faraday
6
6
  # Response represents an HTTP response from making an HTTP request.
7
7
  class Response
8
- # Used for simple response middleware.
9
- class Middleware < Faraday::Middleware
10
- # Override this to modify the environment after the response has finished.
11
- # Calls the `parse` method if defined
12
- # `parse` method can be defined as private, public and protected
13
- def on_complete(env)
14
- return unless respond_to?(:parse, true) && env.parse_body?
15
-
16
- env.body = parse(env.body)
17
- end
18
- end
19
-
20
8
  extend Forwardable
21
9
  extend MiddlewareRegistry
22
10
 
23
- register_middleware File.expand_path('response', __dir__),
24
- raise_error: [:RaiseError, 'raise_error'],
25
- logger: [:Logger, 'logger'],
26
- json: [:Json, 'json']
27
-
28
11
  def initialize(env = nil)
29
12
  @env = Env.from(env) if env
30
13
  @on_complete_callbacks = []
@@ -55,10 +38,10 @@ module Faraday
55
38
  end
56
39
 
57
40
  def on_complete(&block)
58
- if !finished?
59
- @on_complete_callbacks << block
60
- else
41
+ if finished?
61
42
  yield(env)
43
+ else
44
+ @on_complete_callbacks << block
62
45
  end
63
46
  self
64
47
  end
@@ -78,7 +61,8 @@ module Faraday
78
61
  def to_hash
79
62
  {
80
63
  status: env.status, body: env.body,
81
- response_headers: env.response_headers
64
+ response_headers: env.response_headers,
65
+ url: env.url
82
66
  }
83
67
  end
84
68
 
@@ -101,3 +85,7 @@ module Faraday
101
85
  end
102
86
  end
103
87
  end
88
+
89
+ require 'faraday/response/json'
90
+ require 'faraday/response/logger'
91
+ require 'faraday/response/raise_error'
@@ -111,7 +111,7 @@ module Faraday
111
111
  def parse(header_string)
112
112
  return unless header_string && !header_string.empty?
113
113
 
114
- headers = header_string.split(/\r\n/)
114
+ headers = header_string.split("\r\n")
115
115
 
116
116
  # Find the last set of response headers.
117
117
  start_index = headers.rindex { |x| x.start_with?('HTTP/') } || 0
@@ -132,7 +132,12 @@ module Faraday
132
132
 
133
133
  # Join multiple values with a comma.
134
134
  def add_parsed(key, value)
135
- self[key] ? self[key] << ', ' << value : self[key] = value
135
+ if key?(key)
136
+ self[key] = self[key].to_s
137
+ self[key] << ', ' << value
138
+ else
139
+ self[key] = value
140
+ end
136
141
  end
137
142
  end
138
143
  end