faraday 1.4.1 → 2.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +197 -3
- data/LICENSE.md +1 -1
- data/README.md +34 -20
- data/Rakefile +3 -1
- data/examples/client_spec.rb +67 -13
- data/examples/client_test.rb +80 -15
- data/lib/faraday/adapter/test.rb +117 -52
- data/lib/faraday/adapter.rb +5 -14
- data/lib/faraday/connection.rb +70 -130
- data/lib/faraday/encoders/nested_params_encoder.rb +14 -7
- data/lib/faraday/error.rb +20 -11
- data/lib/faraday/logging/formatter.rb +28 -15
- data/lib/faraday/middleware.rb +3 -1
- data/lib/faraday/middleware_registry.rb +17 -63
- data/lib/faraday/options/connection_options.rb +7 -6
- data/lib/faraday/options/env.rb +85 -62
- data/lib/faraday/options/proxy_options.rb +11 -3
- data/lib/faraday/options/request_options.rb +7 -6
- data/lib/faraday/options/ssl_options.rb +56 -45
- data/lib/faraday/options.rb +7 -6
- data/lib/faraday/rack_builder.rb +23 -21
- data/lib/faraday/request/authorization.rb +37 -38
- data/lib/faraday/request/instrumentation.rb +5 -1
- data/lib/faraday/request/json.rb +70 -0
- data/lib/faraday/request/url_encoded.rb +5 -1
- data/lib/faraday/request.rb +20 -37
- data/lib/faraday/response/json.rb +73 -0
- data/lib/faraday/response/logger.rb +8 -4
- data/lib/faraday/response/raise_error.rb +33 -6
- data/lib/faraday/response.rb +10 -20
- data/lib/faraday/utils/headers.rb +7 -2
- data/lib/faraday/utils.rb +11 -7
- data/lib/faraday/version.rb +1 -1
- data/lib/faraday.rb +10 -31
- data/spec/faraday/adapter/test_spec.rb +182 -0
- data/spec/faraday/connection_spec.rb +177 -90
- data/spec/faraday/error_spec.rb +31 -6
- data/spec/faraday/middleware_registry_spec.rb +31 -0
- data/spec/faraday/middleware_spec.rb +18 -0
- data/spec/faraday/options/env_spec.rb +8 -2
- data/spec/faraday/options/options_spec.rb +1 -1
- data/spec/faraday/options/proxy_options_spec.rb +15 -0
- data/spec/faraday/params_encoders/nested_spec.rb +8 -0
- data/spec/faraday/rack_builder_spec.rb +26 -54
- data/spec/faraday/request/authorization_spec.rb +54 -24
- data/spec/faraday/request/instrumentation_spec.rb +5 -7
- data/spec/faraday/request/json_spec.rb +199 -0
- data/spec/faraday/request/url_encoded_spec.rb +12 -2
- data/spec/faraday/request_spec.rb +5 -15
- data/spec/faraday/response/json_spec.rb +189 -0
- data/spec/faraday/response/logger_spec.rb +38 -0
- data/spec/faraday/response/raise_error_spec.rb +47 -5
- data/spec/faraday/response_spec.rb +3 -1
- data/spec/faraday/utils/headers_spec.rb +22 -4
- data/spec/faraday/utils_spec.rb +63 -1
- data/spec/faraday_spec.rb +8 -4
- data/spec/spec_helper.rb +6 -5
- data/spec/support/fake_safe_buffer.rb +1 -1
- data/spec/support/helper_methods.rb +0 -37
- data/spec/support/shared_examples/adapter.rb +2 -2
- data/spec/support/shared_examples/request_method.rb +22 -21
- metadata +14 -94
- data/lib/faraday/adapter/em_http.rb +0 -289
- data/lib/faraday/adapter/em_http_ssl_patch.rb +0 -62
- data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +0 -69
- data/lib/faraday/adapter/em_synchrony.rb +0 -153
- data/lib/faraday/adapter/httpclient.rb +0 -152
- data/lib/faraday/adapter/patron.rb +0 -132
- data/lib/faraday/adapter/rack.rb +0 -75
- data/lib/faraday/adapter/typhoeus.rb +0 -15
- data/lib/faraday/autoload.rb +0 -92
- data/lib/faraday/dependency_loader.rb +0 -37
- data/lib/faraday/file_part.rb +0 -128
- data/lib/faraday/param_part.rb +0 -53
- data/lib/faraday/request/basic_authentication.rb +0 -20
- data/lib/faraday/request/multipart.rb +0 -106
- data/lib/faraday/request/retry.rb +0 -239
- data/lib/faraday/request/token_authentication.rb +0 -20
- data/spec/faraday/adapter/em_http_spec.rb +0 -47
- data/spec/faraday/adapter/em_synchrony_spec.rb +0 -16
- data/spec/faraday/adapter/excon_spec.rb +0 -49
- data/spec/faraday/adapter/httpclient_spec.rb +0 -73
- data/spec/faraday/adapter/net_http_spec.rb +0 -64
- data/spec/faraday/adapter/patron_spec.rb +0 -18
- data/spec/faraday/adapter/rack_spec.rb +0 -8
- data/spec/faraday/adapter/typhoeus_spec.rb +0 -7
- data/spec/faraday/composite_read_io_spec.rb +0 -80
- data/spec/faraday/request/multipart_spec.rb +0 -302
- data/spec/faraday/request/retry_spec.rb +0 -242
- data/spec/faraday/response/middleware_spec.rb +0 -68
- data/spec/support/webmock_rack_app.rb +0 -68
@@ -4,52 +4,51 @@ module Faraday
|
|
4
4
|
class Request
|
5
5
|
# Request middleware for the Authorization HTTP header
|
6
6
|
class Authorization < Faraday::Middleware
|
7
|
-
|
8
|
-
KEY = 'Authorization'
|
9
|
-
end
|
10
|
-
|
11
|
-
# @param type [String, Symbol]
|
12
|
-
# @param token [String, Symbol, Hash]
|
13
|
-
# @return [String] a header value
|
14
|
-
def self.header(type, token)
|
15
|
-
case token
|
16
|
-
when String, Symbol
|
17
|
-
"#{type} #{token}"
|
18
|
-
when Hash
|
19
|
-
build_hash(type.to_s, token)
|
20
|
-
else
|
21
|
-
raise ArgumentError,
|
22
|
-
"Can't build an Authorization #{type}" \
|
23
|
-
"header from #{token.inspect}"
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
# @param type [String]
|
28
|
-
# @param hash [Hash]
|
29
|
-
# @return [String] type followed by comma-separated key=value pairs
|
30
|
-
# @api private
|
31
|
-
def self.build_hash(type, hash)
|
32
|
-
comma = ', '
|
33
|
-
values = []
|
34
|
-
hash.each do |key, value|
|
35
|
-
values << "#{key}=#{value.to_s.inspect}"
|
36
|
-
end
|
37
|
-
"#{type} #{values * comma}"
|
38
|
-
end
|
7
|
+
KEY = 'Authorization'
|
39
8
|
|
40
9
|
# @param app [#call]
|
41
10
|
# @param type [String, Symbol] Type of Authorization
|
42
|
-
# @param
|
43
|
-
|
44
|
-
|
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)
|
17
|
+
@type = type
|
18
|
+
@params = params
|
45
19
|
super(app)
|
46
20
|
end
|
47
21
|
|
48
22
|
# @param env [Faraday::Env]
|
49
|
-
def
|
50
|
-
|
51
|
-
|
23
|
+
def on_request(env)
|
24
|
+
return if env.request_headers[KEY]
|
25
|
+
|
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
|
52
49
|
end
|
53
50
|
end
|
54
51
|
end
|
55
52
|
end
|
53
|
+
|
54
|
+
Faraday::Request.register_middleware(authorization: Faraday::Request::Authorization)
|
@@ -5,12 +5,14 @@ module Faraday
|
|
5
5
|
# Middleware for instrumenting Requests.
|
6
6
|
class Instrumentation < Faraday::Middleware
|
7
7
|
# Options class used in Request::Instrumentation class.
|
8
|
-
|
8
|
+
Options = Faraday::Options.new(:name, :instrumenter) do
|
9
|
+
remove_method :name
|
9
10
|
# @return [String]
|
10
11
|
def name
|
11
12
|
self[:name] ||= 'request.faraday'
|
12
13
|
end
|
13
14
|
|
15
|
+
remove_method :instrumenter
|
14
16
|
# @return [Class]
|
15
17
|
def instrumenter
|
16
18
|
self[:instrumenter] ||= ActiveSupport::Notifications
|
@@ -52,3 +54,5 @@ module Faraday
|
|
52
54
|
end
|
53
55
|
end
|
54
56
|
end
|
57
|
+
|
58
|
+
Faraday::Request.register_middleware(instrumentation: Faraday::Request::Instrumentation)
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module Faraday
|
6
|
+
class Request
|
7
|
+
# Request middleware that encodes the body as JSON.
|
8
|
+
#
|
9
|
+
# Processes only requests with matching Content-type or those without a type.
|
10
|
+
# If a request doesn't have a type but has a body, it sets the Content-type
|
11
|
+
# to JSON MIME-type.
|
12
|
+
#
|
13
|
+
# Doesn't try to encode bodies that already are in string form.
|
14
|
+
class Json < Middleware
|
15
|
+
MIME_TYPE = 'application/json'
|
16
|
+
MIME_TYPE_REGEX = %r{^application/(vnd\..+\+)?json$}
|
17
|
+
|
18
|
+
def on_request(env)
|
19
|
+
match_content_type(env) do |data|
|
20
|
+
env[:body] = encode(data)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def encode(data)
|
27
|
+
if options[:encoder].is_a?(Array) && options[:encoder].size >= 2
|
28
|
+
options[:encoder][0].public_send(options[:encoder][1], data)
|
29
|
+
elsif options[:encoder].respond_to?(:dump)
|
30
|
+
options[:encoder].dump(data)
|
31
|
+
else
|
32
|
+
::JSON.generate(data)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def match_content_type(env)
|
37
|
+
return unless process_request?(env)
|
38
|
+
|
39
|
+
env[:request_headers][CONTENT_TYPE] ||= MIME_TYPE
|
40
|
+
yield env[:body] unless env[:body].respond_to?(:to_str)
|
41
|
+
end
|
42
|
+
|
43
|
+
def process_request?(env)
|
44
|
+
type = request_type(env)
|
45
|
+
body?(env) && (type.empty? || type.match?(MIME_TYPE_REGEX))
|
46
|
+
end
|
47
|
+
|
48
|
+
def body?(env)
|
49
|
+
body = env[:body]
|
50
|
+
case body
|
51
|
+
when true, false
|
52
|
+
true
|
53
|
+
when nil
|
54
|
+
# NOTE: nil can be converted to `"null"`, but this middleware doesn't process `nil` for the compatibility.
|
55
|
+
false
|
56
|
+
else
|
57
|
+
!(body.respond_to?(:to_str) && body.empty?)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def request_type(env)
|
62
|
+
type = env[:request_headers][CONTENT_TYPE].to_s
|
63
|
+
type = type.split(';', 2).first if type.index(';')
|
64
|
+
type
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
Faraday::Request.register_middleware(json: Faraday::Request::Json)
|
@@ -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
|
-
|
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)
|
data/lib/faraday/request.rb
CHANGED
@@ -21,32 +21,16 @@ module Faraday
|
|
21
21
|
# @!attribute headers
|
22
22
|
# @return [Faraday::Utils::Headers] headers
|
23
23
|
# @!attribute body
|
24
|
-
# @return [
|
24
|
+
# @return [String] body
|
25
25
|
# @!attribute options
|
26
26
|
# @return [RequestOptions] options
|
27
|
-
|
28
|
-
# rubocop:disable Style/StructInheritance
|
29
|
-
class Request < Struct.new(
|
30
|
-
:http_method, :path, :params, :headers, :body, :options
|
31
|
-
)
|
32
|
-
# rubocop:enable Style/StructInheritance
|
33
|
-
|
27
|
+
Request = Struct.new(:http_method, :path, :params, :headers, :body, :options) do
|
34
28
|
extend MiddlewareRegistry
|
35
29
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
authorization: [:Authorization, 'authorization'],
|
41
|
-
basic_auth: [
|
42
|
-
:BasicAuthentication,
|
43
|
-
'basic_authentication'
|
44
|
-
],
|
45
|
-
token_auth: [
|
46
|
-
:TokenAuthentication,
|
47
|
-
'token_authentication'
|
48
|
-
],
|
49
|
-
instrumentation: [:Instrumentation, 'instrumentation']
|
30
|
+
alias_method :member_get, :[]
|
31
|
+
private :member_get
|
32
|
+
alias_method :member_set, :[]=
|
33
|
+
private :member_set
|
50
34
|
|
51
35
|
# @param request_method [String]
|
52
36
|
# @yield [request] for block customization, if block given
|
@@ -58,14 +42,7 @@ module Faraday
|
|
58
42
|
end
|
59
43
|
end
|
60
44
|
|
61
|
-
|
62
|
-
warn <<~TEXT
|
63
|
-
WARNING: `Faraday::Request##{__method__}` is deprecated; use `#http_method` instead. It will be removed in or after version 2.0.
|
64
|
-
`Faraday::Request##{__method__}` called from #{caller_locations(1..1).first}
|
65
|
-
TEXT
|
66
|
-
http_method
|
67
|
-
end
|
68
|
-
|
45
|
+
remove_method :params=
|
69
46
|
# Replace params, preserving the existing hash type.
|
70
47
|
#
|
71
48
|
# @param hash [Hash] new params
|
@@ -73,10 +50,11 @@ module Faraday
|
|
73
50
|
if params
|
74
51
|
params.replace hash
|
75
52
|
else
|
76
|
-
|
53
|
+
member_set(:params, hash)
|
77
54
|
end
|
78
55
|
end
|
79
56
|
|
57
|
+
remove_method :headers=
|
80
58
|
# Replace request headers, preserving the existing hash type.
|
81
59
|
#
|
82
60
|
# @param hash [Hash] new headers
|
@@ -84,7 +62,7 @@ module Faraday
|
|
84
62
|
if headers
|
85
63
|
headers.replace hash
|
86
64
|
else
|
87
|
-
|
65
|
+
member_set(:headers, hash)
|
88
66
|
end
|
89
67
|
end
|
90
68
|
|
@@ -140,11 +118,11 @@ module Faraday
|
|
140
118
|
# @param serialised [Hash] the serialised object.
|
141
119
|
def marshal_load(serialised)
|
142
120
|
self.http_method = serialised[:http_method]
|
143
|
-
self.body
|
144
|
-
self.headers
|
145
|
-
self.path
|
146
|
-
self.params
|
147
|
-
self.options
|
121
|
+
self.body = serialised[:body]
|
122
|
+
self.headers = serialised[:headers]
|
123
|
+
self.path = serialised[:path]
|
124
|
+
self.params = serialised[:params]
|
125
|
+
self.options = serialised[:options]
|
148
126
|
end
|
149
127
|
|
150
128
|
# @return [Env] the Env for this Request
|
@@ -154,3 +132,8 @@ module Faraday
|
|
154
132
|
end
|
155
133
|
end
|
156
134
|
end
|
135
|
+
|
136
|
+
require 'faraday/request/authorization'
|
137
|
+
require 'faraday/request/instrumentation'
|
138
|
+
require 'faraday/request/json'
|
139
|
+
require 'faraday/request/url_encoded'
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module Faraday
|
6
|
+
class Response
|
7
|
+
# Parse response bodies as JSON.
|
8
|
+
class Json < Middleware
|
9
|
+
def initialize(app = nil, parser_options: nil, content_type: /\bjson$/, preserve_raw: false)
|
10
|
+
super(app)
|
11
|
+
@parser_options = parser_options
|
12
|
+
@content_types = Array(content_type)
|
13
|
+
@preserve_raw = preserve_raw
|
14
|
+
|
15
|
+
process_parser_options
|
16
|
+
end
|
17
|
+
|
18
|
+
def on_complete(env)
|
19
|
+
process_response(env) if parse_response?(env)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def process_response(env)
|
25
|
+
env[:raw_body] = env[:body] if @preserve_raw
|
26
|
+
env[:body] = parse(env[:body])
|
27
|
+
rescue StandardError, SyntaxError => e
|
28
|
+
raise Faraday::ParsingError.new(e, env[:response])
|
29
|
+
end
|
30
|
+
|
31
|
+
def parse(body)
|
32
|
+
return if body.strip.empty?
|
33
|
+
|
34
|
+
decoder, method_name = @decoder_options
|
35
|
+
|
36
|
+
decoder.public_send(method_name, body, @parser_options || {})
|
37
|
+
end
|
38
|
+
|
39
|
+
def parse_response?(env)
|
40
|
+
process_response_type?(env) &&
|
41
|
+
env[:body].respond_to?(:to_str)
|
42
|
+
end
|
43
|
+
|
44
|
+
def process_response_type?(env)
|
45
|
+
type = response_type(env)
|
46
|
+
@content_types.empty? || @content_types.any? do |pattern|
|
47
|
+
pattern.is_a?(Regexp) ? type.match?(pattern) : type == pattern
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def response_type(env)
|
52
|
+
type = env[:response_headers][CONTENT_TYPE].to_s
|
53
|
+
type = type.split(';', 2).first if type.index(';')
|
54
|
+
type
|
55
|
+
end
|
56
|
+
|
57
|
+
def process_parser_options
|
58
|
+
@decoder_options = @parser_options&.delete(:decoder)
|
59
|
+
|
60
|
+
@decoder_options =
|
61
|
+
if @decoder_options.is_a?(Array) && @decoder_options.size >= 2
|
62
|
+
@decoder_options.slice(0, 2)
|
63
|
+
elsif @decoder_options.respond_to?(:load)
|
64
|
+
[@decoder_options, :load]
|
65
|
+
else
|
66
|
+
[::JSON, :parse]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
Faraday::Response.register_middleware(json: Faraday::Response::Json)
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'forwardable'
|
4
|
+
require 'logger'
|
4
5
|
require 'faraday/logging/formatter'
|
5
6
|
|
6
7
|
module Faraday
|
@@ -11,10 +12,7 @@ module Faraday
|
|
11
12
|
class Logger < Middleware
|
12
13
|
def initialize(app, logger = nil, options = {})
|
13
14
|
super(app)
|
14
|
-
logger ||=
|
15
|
-
require 'logger'
|
16
|
-
::Logger.new($stdout)
|
17
|
-
end
|
15
|
+
logger ||= ::Logger.new($stdout)
|
18
16
|
formatter_class = options.delete(:formatter) || Logging::Formatter
|
19
17
|
@formatter = formatter_class.new(logger: logger, options: options)
|
20
18
|
yield @formatter if block_given?
|
@@ -28,6 +26,12 @@ module Faraday
|
|
28
26
|
def on_complete(env)
|
29
27
|
@formatter.response(env)
|
30
28
|
end
|
29
|
+
|
30
|
+
def on_error(exc)
|
31
|
+
@formatter.exception(exc) if @formatter.respond_to?(:exception)
|
32
|
+
end
|
31
33
|
end
|
32
34
|
end
|
33
35
|
end
|
36
|
+
|
37
|
+
Faraday::Response.register_middleware(logger: Faraday::Response::Logger)
|
@@ -6,8 +6,8 @@ module Faraday
|
|
6
6
|
# client or server error responses.
|
7
7
|
class RaiseError < Middleware
|
8
8
|
# rubocop:disable Naming/ConstantName
|
9
|
-
ClientErrorStatuses = (400...500)
|
10
|
-
ServerErrorStatuses = (500...600)
|
9
|
+
ClientErrorStatuses = (400...500)
|
10
|
+
ServerErrorStatuses = (500...600)
|
11
11
|
# rubocop:enable Naming/ConstantName
|
12
12
|
|
13
13
|
def on_complete(env)
|
@@ -24,10 +24,14 @@ module Faraday
|
|
24
24
|
# mimic the behavior that we get with proxy requests with HTTPS
|
25
25
|
msg = %(407 "Proxy Authentication Required")
|
26
26
|
raise Faraday::ProxyAuthError.new(msg, response_values(env))
|
27
|
+
when 408
|
28
|
+
raise Faraday::RequestTimeoutError, response_values(env)
|
27
29
|
when 409
|
28
30
|
raise Faraday::ConflictError, response_values(env)
|
29
31
|
when 422
|
30
32
|
raise Faraday::UnprocessableEntityError, response_values(env)
|
33
|
+
when 429
|
34
|
+
raise Faraday::TooManyRequestsError, response_values(env)
|
31
35
|
when ClientErrorStatuses
|
32
36
|
raise Faraday::ClientError, response_values(env)
|
33
37
|
when ServerErrorStatuses
|
@@ -37,20 +41,43 @@ module Faraday
|
|
37
41
|
end
|
38
42
|
end
|
39
43
|
|
44
|
+
# Returns a hash of response data with the following keys:
|
45
|
+
# - status
|
46
|
+
# - headers
|
47
|
+
# - body
|
48
|
+
# - request
|
49
|
+
#
|
50
|
+
# The `request` key is omitted when the middleware is explicitly
|
51
|
+
# configured with the option `include_request: false`.
|
40
52
|
def response_values(env)
|
41
|
-
{
|
53
|
+
response = {
|
42
54
|
status: env.status,
|
43
55
|
headers: env.response_headers,
|
44
|
-
body: env.body
|
56
|
+
body: env.body
|
57
|
+
}
|
58
|
+
|
59
|
+
# Include the request data by default. If the middleware was explicitly
|
60
|
+
# configured to _not_ include request data, then omit it.
|
61
|
+
return response unless options.fetch(:include_request, true)
|
62
|
+
|
63
|
+
response.merge(
|
45
64
|
request: {
|
46
65
|
method: env.method,
|
66
|
+
url: env.url,
|
47
67
|
url_path: env.url.path,
|
48
|
-
params: env
|
68
|
+
params: query_params(env),
|
49
69
|
headers: env.request_headers,
|
50
70
|
body: env.request_body
|
51
71
|
}
|
52
|
-
|
72
|
+
)
|
73
|
+
end
|
74
|
+
|
75
|
+
def query_params(env)
|
76
|
+
env.request.params_encoder ||= Faraday::Utils.default_params_encoder
|
77
|
+
env.params_encoder.decode(env.url.query)
|
53
78
|
end
|
54
79
|
end
|
55
80
|
end
|
56
81
|
end
|
82
|
+
|
83
|
+
Faraday::Response.register_middleware(raise_error: Faraday::Response::RaiseError)
|
data/lib/faraday/response.rb
CHANGED
@@ -5,25 +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
|
-
|
27
11
|
def initialize(env = nil)
|
28
12
|
@env = Env.from(env) if env
|
29
13
|
@on_complete_callbacks = []
|
@@ -42,6 +26,7 @@ module Faraday
|
|
42
26
|
def headers
|
43
27
|
finished? ? env.response_headers : {}
|
44
28
|
end
|
29
|
+
|
45
30
|
def_delegator :headers, :[]
|
46
31
|
|
47
32
|
def body
|
@@ -53,10 +38,10 @@ module Faraday
|
|
53
38
|
end
|
54
39
|
|
55
40
|
def on_complete(&block)
|
56
|
-
if
|
57
|
-
@on_complete_callbacks << block
|
58
|
-
else
|
41
|
+
if finished?
|
59
42
|
yield(env)
|
43
|
+
else
|
44
|
+
@on_complete_callbacks << block
|
60
45
|
end
|
61
46
|
self
|
62
47
|
end
|
@@ -76,7 +61,8 @@ module Faraday
|
|
76
61
|
def to_hash
|
77
62
|
{
|
78
63
|
status: env.status, body: env.body,
|
79
|
-
response_headers: env.response_headers
|
64
|
+
response_headers: env.response_headers,
|
65
|
+
url: env.url
|
80
66
|
}
|
81
67
|
end
|
82
68
|
|
@@ -99,3 +85,7 @@ module Faraday
|
|
99
85
|
end
|
100
86
|
end
|
101
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(
|
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
|
-
|
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
|
data/lib/faraday/utils.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'uri'
|
3
4
|
require 'faraday/utils/headers'
|
4
5
|
require 'faraday/utils/params_hash'
|
5
6
|
|
@@ -24,7 +25,7 @@ module Faraday
|
|
24
25
|
attr_writer :default_space_encoding
|
25
26
|
end
|
26
27
|
|
27
|
-
ESCAPE_RE = /[^a-zA-Z0-9 .~_-]
|
28
|
+
ESCAPE_RE = /[^a-zA-Z0-9 .~_-]/
|
28
29
|
|
29
30
|
def escape(str)
|
30
31
|
str.to_s.gsub(ESCAPE_RE) do |match|
|
@@ -36,7 +37,7 @@ module Faraday
|
|
36
37
|
CGI.unescape str.to_s
|
37
38
|
end
|
38
39
|
|
39
|
-
DEFAULT_SEP = /[&;] */n
|
40
|
+
DEFAULT_SEP = /[&;] */n
|
40
41
|
|
41
42
|
# Adapted from Rack
|
42
43
|
def parse_query(query)
|
@@ -51,6 +52,12 @@ module Faraday
|
|
51
52
|
@default_params_encoder ||= NestedParamsEncoder
|
52
53
|
end
|
53
54
|
|
55
|
+
def basic_header_from(login, pass)
|
56
|
+
value = ["#{login}:#{pass}"].pack('m') # Base64 encoding
|
57
|
+
value.delete!("\n")
|
58
|
+
"Basic #{value}"
|
59
|
+
end
|
60
|
+
|
54
61
|
class << self
|
55
62
|
attr_writer :default_params_encoder
|
56
63
|
end
|
@@ -71,10 +78,7 @@ module Faraday
|
|
71
78
|
end
|
72
79
|
|
73
80
|
def default_uri_parser
|
74
|
-
@default_uri_parser ||=
|
75
|
-
require 'uri'
|
76
|
-
Kernel.method(:URI)
|
77
|
-
end
|
81
|
+
@default_uri_parser ||= Kernel.method(:URI)
|
78
82
|
end
|
79
83
|
|
80
84
|
def default_uri_parser=(parser)
|
@@ -96,7 +100,7 @@ module Faraday
|
|
96
100
|
# Recursive hash update
|
97
101
|
def deep_merge!(target, hash)
|
98
102
|
hash.each do |key, value|
|
99
|
-
target[key] = if value.is_a?(Hash) && target[key].is_a?(Hash)
|
103
|
+
target[key] = if value.is_a?(Hash) && (target[key].is_a?(Hash) || target[key].is_a?(Options))
|
100
104
|
deep_merge(target[key], value)
|
101
105
|
else
|
102
106
|
value
|
data/lib/faraday/version.rb
CHANGED