faraday_middleware 0.10.0 → 1.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.
- checksums.yaml +5 -5
- data/README.md +16 -22
- data/lib/faraday_middleware/backwards_compatibility.rb +16 -12
- data/lib/faraday_middleware/gzip.rb +51 -15
- data/lib/faraday_middleware/instrumentation.rb +8 -2
- data/lib/faraday_middleware/rack_compatible.rb +18 -11
- data/lib/faraday_middleware/redirect_limit_reached.rb +16 -0
- data/lib/faraday_middleware/request/encode_json.rb +12 -9
- data/lib/faraday_middleware/request/method_override.rb +7 -6
- data/lib/faraday_middleware/request/oauth.rb +13 -10
- data/lib/faraday_middleware/request/oauth2.rb +37 -12
- data/lib/faraday_middleware/response/caching.rb +55 -21
- data/lib/faraday_middleware/response/chunked.rb +10 -6
- data/lib/faraday_middleware/response/follow_redirects.rb +57 -26
- data/lib/faraday_middleware/response/mashify.rb +2 -0
- data/lib/faraday_middleware/response/parse_dates.rb +6 -3
- data/lib/faraday_middleware/response/parse_json.rb +10 -10
- data/lib/faraday_middleware/response/parse_marshal.rb +3 -1
- data/lib/faraday_middleware/response/parse_xml.rb +4 -2
- data/lib/faraday_middleware/response/parse_yaml.rb +18 -11
- data/lib/faraday_middleware/response/rashify.rb +3 -1
- data/lib/faraday_middleware/response_middleware.rb +27 -18
- data/lib/faraday_middleware/version.rb +4 -1
- data/lib/faraday_middleware.rb +21 -17
- metadata +8 -32
- data/CHANGELOG.md +0 -10
- data/CONTRIBUTING.md +0 -46
- data/faraday_middleware.gemspec +0 -20
- data/lib/faraday_middleware/addressable_patch.rb +0 -20
@@ -1,12 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'faraday'
|
2
4
|
require 'forwardable'
|
3
|
-
|
4
|
-
require 'faraday_middleware/addressable_patch' if defined? ::Addressable::URI
|
5
|
+
require 'digest/sha1'
|
5
6
|
|
6
7
|
module FaradayMiddleware
|
7
8
|
# Public: Caches GET responses and pulls subsequent ones from the cache.
|
8
9
|
class Caching < Faraday::Middleware
|
9
10
|
attr_reader :cache
|
11
|
+
|
10
12
|
# Internal: List of status codes that can be cached:
|
11
13
|
# * 200 - 'OK'
|
12
14
|
# * 203 - 'Non-Authoritative Information'
|
@@ -15,41 +17,49 @@ module FaradayMiddleware
|
|
15
17
|
# * 302 - 'Found'
|
16
18
|
# * 404 - 'Not Found'
|
17
19
|
# * 410 - 'Gone'
|
18
|
-
CACHEABLE_STATUS_CODES = [200, 203, 300, 301, 302, 404, 410]
|
20
|
+
CACHEABLE_STATUS_CODES = [200, 203, 300, 301, 302, 404, 410].freeze
|
19
21
|
|
20
22
|
extend Forwardable
|
21
23
|
def_delegators :'Faraday::Utils', :parse_query, :build_query
|
22
24
|
|
23
25
|
# Public: initialize the middleware.
|
24
26
|
#
|
25
|
-
# cache - An object that responds to read
|
27
|
+
# cache - An object that responds to read and write (default: nil).
|
26
28
|
# options - An options Hash (default: {}):
|
27
|
-
# :ignore_params - String name or Array names of query
|
28
|
-
#
|
29
|
-
#
|
29
|
+
# :ignore_params - String name or Array names of query
|
30
|
+
# params that should be ignored when forming
|
31
|
+
# the cache key (default: []).
|
32
|
+
# :write_options - Hash of settings that should be passed as the
|
33
|
+
# third options parameter to the cache's #write
|
34
|
+
# method. If not specified, no options parameter
|
35
|
+
# will be passed.
|
36
|
+
# :full_key - Boolean - use full URL as cache key:
|
37
|
+
# (url.host + url.request_uri)
|
38
|
+
# :status_codes - Array of http status code to be cache
|
39
|
+
# (default: CACHEABLE_STATUS_CODE)
|
30
40
|
#
|
31
41
|
# Yields if no cache is given. The block should return a cache object.
|
32
42
|
def initialize(app, cache = nil, options = {})
|
33
43
|
super(app)
|
34
|
-
|
44
|
+
if cache.is_a?(Hash) && block_given?
|
45
|
+
options = cache
|
46
|
+
cache = nil
|
47
|
+
end
|
35
48
|
@cache = cache || yield
|
36
49
|
@options = options
|
37
50
|
end
|
38
51
|
|
39
52
|
def call(env)
|
40
|
-
if :
|
53
|
+
if env[:method] == :get
|
41
54
|
if env[:parallel_manager]
|
42
55
|
# callback mode
|
43
56
|
cache_on_complete(env)
|
44
57
|
else
|
45
58
|
# synchronous mode
|
46
59
|
key = cache_key(env)
|
47
|
-
unless response = cache.read(key)
|
60
|
+
unless (response = cache.read(key)) && response
|
48
61
|
response = @app.call(env)
|
49
|
-
|
50
|
-
if CACHEABLE_STATUS_CODES.include?(response.status)
|
51
|
-
cache.write(key, response)
|
52
|
-
end
|
62
|
+
store_response_in_cache(key, response)
|
53
63
|
end
|
54
64
|
finalize_response(response, env)
|
55
65
|
end
|
@@ -62,29 +72,53 @@ module FaradayMiddleware
|
|
62
72
|
url = env[:url].dup
|
63
73
|
if url.query && params_to_ignore.any?
|
64
74
|
params = parse_query url.query
|
65
|
-
params.reject! {|k,| params_to_ignore.include? k }
|
75
|
+
params.reject! { |k,| params_to_ignore.include? k }
|
66
76
|
url.query = params.any? ? build_query(params) : nil
|
67
77
|
end
|
68
78
|
url.normalize!
|
69
|
-
url.request_uri
|
79
|
+
digest = full_key? ? url.host + url.request_uri : url.request_uri
|
80
|
+
Digest::SHA1.hexdigest(digest)
|
70
81
|
end
|
71
82
|
|
72
83
|
def params_to_ignore
|
73
|
-
@params_to_ignore ||= Array(@options[:ignore_params]).map
|
84
|
+
@params_to_ignore ||= Array(@options[:ignore_params]).map(&:to_s)
|
85
|
+
end
|
86
|
+
|
87
|
+
def full_key?
|
88
|
+
@full_key ||= @options[:full_key]
|
89
|
+
end
|
90
|
+
|
91
|
+
def custom_status_codes
|
92
|
+
@custom_status_codes ||= begin
|
93
|
+
codes = CACHEABLE_STATUS_CODES & Array(@options[:status_codes]).map(&:to_i)
|
94
|
+
codes.any? ? codes : CACHEABLE_STATUS_CODES
|
95
|
+
end
|
74
96
|
end
|
75
97
|
|
76
98
|
def cache_on_complete(env)
|
77
99
|
key = cache_key(env)
|
78
|
-
if cached_response = cache.read(key)
|
100
|
+
if (cached_response = cache.read(key))
|
79
101
|
finalize_response(cached_response, env)
|
80
102
|
else
|
81
|
-
response
|
82
|
-
|
83
|
-
|
103
|
+
# response.status is nil at this point
|
104
|
+
# any checks need to be done inside on_complete block
|
105
|
+
@app.call(env).on_complete do |response_env|
|
106
|
+
store_response_in_cache(key, response_env.response)
|
107
|
+
response_env
|
84
108
|
end
|
85
109
|
end
|
86
110
|
end
|
87
111
|
|
112
|
+
def store_response_in_cache(key, response)
|
113
|
+
return unless custom_status_codes.include?(response.status)
|
114
|
+
|
115
|
+
if @options[:write_options]
|
116
|
+
cache.write(key, response, @options[:write_options])
|
117
|
+
else
|
118
|
+
cache.write(key, response)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
88
122
|
def finalize_response(response, env)
|
89
123
|
response = response.dup if response.frozen?
|
90
124
|
env[:response] = response
|
@@ -1,16 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'faraday_middleware/response_middleware'
|
2
4
|
|
3
5
|
module FaradayMiddleware
|
4
|
-
# Public: Parse a Transfer-Encoding
|
6
|
+
# Public: Parse a Transfer-Encoding. Chunks response to just the original data
|
5
7
|
class Chunked < FaradayMiddleware::ResponseMiddleware
|
6
|
-
TRANSFER_ENCODING = 'transfer-encoding'
|
8
|
+
TRANSFER_ENCODING = 'transfer-encoding'
|
7
9
|
|
8
10
|
define_parser do |raw_body|
|
9
11
|
decoded_body = []
|
10
12
|
until raw_body.empty?
|
11
13
|
chunk_len, raw_body = raw_body.split("\r\n", 2)
|
12
|
-
chunk_len = chunk_len.split(';',2).first.hex
|
13
|
-
break if chunk_len
|
14
|
+
chunk_len = chunk_len.split(';', 2).first.hex
|
15
|
+
break if chunk_len.zero?
|
16
|
+
|
14
17
|
decoded_body << raw_body[0, chunk_len]
|
15
18
|
# The 2 is to strip the extra CRLF at the end of the chunk
|
16
19
|
raw_body = raw_body[chunk_len + 2, raw_body.length - chunk_len - 2]
|
@@ -19,11 +22,12 @@ module FaradayMiddleware
|
|
19
22
|
end
|
20
23
|
|
21
24
|
def parse_response?(env)
|
22
|
-
super
|
25
|
+
super && chunked_encoding?(env[:response_headers])
|
23
26
|
end
|
24
27
|
|
25
28
|
def chunked_encoding?(headers)
|
26
|
-
encoding = headers[TRANSFER_ENCODING]
|
29
|
+
(encoding = headers[TRANSFER_ENCODING]) &&
|
30
|
+
encoding.split(',').include?('chunked')
|
27
31
|
end
|
28
32
|
end
|
29
33
|
end
|
@@ -1,18 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'faraday'
|
2
4
|
require 'set'
|
3
5
|
|
4
6
|
module FaradayMiddleware
|
5
|
-
# Public:
|
6
|
-
class RedirectLimitReached < Faraday::Error::ClientError
|
7
|
-
attr_reader :response
|
8
|
-
|
9
|
-
def initialize(response)
|
10
|
-
super "too many redirects; last one to: #{response['location']}"
|
11
|
-
@response = response
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
# Public: Follow HTTP 301, 302, 303, and 307 redirects.
|
7
|
+
# Public: Follow HTTP 301, 302, 303, 307, and 308 redirects.
|
16
8
|
#
|
17
9
|
# For HTTP 301, 302, and 303, the original GET, POST, PUT, DELETE, or PATCH
|
18
10
|
# request gets converted into a GET. With `:standards_compliant => true`,
|
@@ -32,26 +24,37 @@ module FaradayMiddleware
|
|
32
24
|
# end
|
33
25
|
class FollowRedirects < Faraday::Middleware
|
34
26
|
# HTTP methods for which 30x redirects can be followed
|
35
|
-
ALLOWED_METHODS = Set.new [
|
27
|
+
ALLOWED_METHODS = Set.new %i[head options get post put patch delete]
|
36
28
|
# HTTP redirect status codes that this middleware implements
|
37
|
-
REDIRECT_CODES = Set.new [301, 302, 303, 307]
|
29
|
+
REDIRECT_CODES = Set.new [301, 302, 303, 307, 308]
|
38
30
|
# Keys in env hash which will get cleared between requests
|
39
|
-
ENV_TO_CLEAR = Set.new [
|
31
|
+
ENV_TO_CLEAR = Set.new %i[status response response_headers]
|
40
32
|
|
41
33
|
# Default value for max redirects followed
|
42
34
|
FOLLOW_LIMIT = 3
|
43
35
|
|
44
36
|
# Regex that matches characters that need to be escaped in URLs, sans
|
45
37
|
# the "%" character which we assume already represents an escaped sequence.
|
46
|
-
URI_UNSAFE =
|
38
|
+
URI_UNSAFE = %r{[^\-_.!~*'()a-zA-Z\d;/?:@&=+$,\[\]%]}.freeze
|
39
|
+
|
40
|
+
AUTH_HEADER = 'Authorization'
|
47
41
|
|
48
42
|
# Public: Initialize the middleware.
|
49
43
|
#
|
50
44
|
# options - An options Hash (default: {}):
|
51
|
-
#
|
52
|
-
#
|
45
|
+
# :limit - A Numeric redirect limit (default: 3)
|
46
|
+
# :standards_compliant - A Boolean indicating whether to respect
|
53
47
|
# the HTTP spec when following 301/302
|
54
48
|
# (default: false)
|
49
|
+
# :callback - A callable used on redirects
|
50
|
+
# with the old and new envs
|
51
|
+
# :cookies - An Array of Strings (e.g.
|
52
|
+
# ['cookie1', 'cookie2']) to choose
|
53
|
+
# cookies to be kept, or :all to keep
|
54
|
+
# all cookies (default: []).
|
55
|
+
# :clear_authorization_header - A Boolean indicating whether the request
|
56
|
+
# Authorization header should be cleared on
|
57
|
+
# redirects (default: true)
|
55
58
|
def initialize(app, options = {})
|
56
59
|
super(app)
|
57
60
|
@options = options
|
@@ -67,7 +70,7 @@ module FaradayMiddleware
|
|
67
70
|
private
|
68
71
|
|
69
72
|
def convert_to_get?(response)
|
70
|
-
|
73
|
+
!%i[head options].include?(response.env[:method]) &&
|
71
74
|
@convert_to_get.include?(response.status)
|
72
75
|
end
|
73
76
|
|
@@ -78,7 +81,9 @@ module FaradayMiddleware
|
|
78
81
|
response.on_complete do |response_env|
|
79
82
|
if follow_redirect?(response_env, response)
|
80
83
|
raise RedirectLimitReached, response if follows.zero?
|
81
|
-
|
84
|
+
|
85
|
+
new_request_env = update_env(response_env.dup, request_body, response)
|
86
|
+
callback&.call(response_env, new_request_env)
|
82
87
|
response = perform_with_redirection(new_request_env, follows - 1)
|
83
88
|
end
|
84
89
|
end
|
@@ -86,7 +91,11 @@ module FaradayMiddleware
|
|
86
91
|
end
|
87
92
|
|
88
93
|
def update_env(env, request_body, response)
|
89
|
-
env[:url]
|
94
|
+
redirect_from_url = env[:url].to_s
|
95
|
+
redirect_to_url = safe_escape(response['location'] || '')
|
96
|
+
env[:url] += redirect_to_url
|
97
|
+
|
98
|
+
ENV_TO_CLEAR.each { |key| env.delete key }
|
90
99
|
|
91
100
|
if convert_to_get?(response)
|
92
101
|
env[:method] = :get
|
@@ -95,14 +104,14 @@ module FaradayMiddleware
|
|
95
104
|
env[:body] = request_body
|
96
105
|
end
|
97
106
|
|
98
|
-
|
107
|
+
clear_authorization_header(env, redirect_from_url, redirect_to_url)
|
99
108
|
|
100
109
|
env
|
101
110
|
end
|
102
111
|
|
103
112
|
def follow_redirect?(env, response)
|
104
|
-
ALLOWED_METHODS.include?
|
105
|
-
REDIRECT_CODES.include?
|
113
|
+
ALLOWED_METHODS.include?(env[:method]) &&
|
114
|
+
REDIRECT_CODES.include?(response.status)
|
106
115
|
end
|
107
116
|
|
108
117
|
def follow_limit
|
@@ -113,14 +122,36 @@ module FaradayMiddleware
|
|
113
122
|
@options.fetch(:standards_compliant, false)
|
114
123
|
end
|
115
124
|
|
125
|
+
def callback
|
126
|
+
@options[:callback]
|
127
|
+
end
|
128
|
+
|
116
129
|
# Internal: escapes unsafe characters from an URL which might be a path
|
117
130
|
# component only or a fully qualified URI so that it can be joined onto an
|
118
131
|
# URI:HTTP using the `+` operator. Doesn't escape "%" characters so to not
|
119
132
|
# risk double-escaping.
|
120
133
|
def safe_escape(uri)
|
121
|
-
uri.
|
122
|
-
|
123
|
-
|
134
|
+
uri = uri.split('#')[0] # we want to remove the fragment if present
|
135
|
+
uri.to_s.gsub(URI_UNSAFE) do |match|
|
136
|
+
"%#{match.unpack('H2' * match.bytesize).join('%').upcase}"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def clear_authorization_header(env, from_url, to_url)
|
141
|
+
return env if redirect_to_same_host?(from_url, to_url)
|
142
|
+
return env unless @options.fetch(:clear_authorization_header, true)
|
143
|
+
|
144
|
+
env[:request_headers].delete(AUTH_HEADER)
|
145
|
+
end
|
146
|
+
|
147
|
+
def redirect_to_same_host?(from_url, to_url)
|
148
|
+
return true if to_url.start_with?('/')
|
149
|
+
|
150
|
+
from_uri = URI.parse(from_url)
|
151
|
+
to_uri = URI.parse(to_url)
|
152
|
+
|
153
|
+
[from_uri.scheme, from_uri.host, from_uri.port] ==
|
154
|
+
[to_uri.scheme, to_uri.host, to_uri.port]
|
124
155
|
end
|
125
156
|
end
|
126
157
|
end
|
@@ -1,10 +1,13 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'time'
|
4
|
+
require 'faraday'
|
3
5
|
|
4
6
|
module FaradayMiddleware
|
5
7
|
# Parse dates from response body
|
6
8
|
class ParseDates < ::Faraday::Response::Middleware
|
7
|
-
ISO_DATE_FORMAT = /\A\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?
|
9
|
+
ISO_DATE_FORMAT = /\A\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?
|
10
|
+
(Z|((\+|-)\d{2}:?\d{2}))\Z/xm.freeze
|
8
11
|
|
9
12
|
def initialize(app, options = {})
|
10
13
|
@regexp = options[:match] || ISO_DATE_FORMAT
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'faraday_middleware/response_middleware'
|
2
4
|
|
3
5
|
module FaradayMiddleware
|
@@ -7,8 +9,8 @@ module FaradayMiddleware
|
|
7
9
|
require 'json' unless defined?(::JSON)
|
8
10
|
end
|
9
11
|
|
10
|
-
define_parser do |body|
|
11
|
-
::JSON.parse
|
12
|
+
define_parser do |body, parser_options|
|
13
|
+
::JSON.parse(body, parser_options || {}) unless body.strip.empty?
|
12
14
|
end
|
13
15
|
|
14
16
|
# Public: Override the content-type of the response with "application/json"
|
@@ -18,7 +20,7 @@ module FaradayMiddleware
|
|
18
20
|
# This is to fix responses from certain API providers that insist on serving
|
19
21
|
# JSON with wrong MIME-types such as "text/javascript".
|
20
22
|
class MimeTypeFix < ResponseMiddleware
|
21
|
-
MIME_TYPE = 'application/json'
|
23
|
+
MIME_TYPE = 'application/json'
|
22
24
|
|
23
25
|
def process_response(env)
|
24
26
|
old_type = env[:response_headers][CONTENT_TYPE].to_s
|
@@ -27,19 +29,17 @@ module FaradayMiddleware
|
|
27
29
|
env[:response_headers][CONTENT_TYPE] = new_type
|
28
30
|
end
|
29
31
|
|
30
|
-
BRACKETS = %w-
|
31
|
-
WHITESPACE = [
|
32
|
+
BRACKETS = %w-[ {-.freeze
|
33
|
+
WHITESPACE = [' ', "\n", "\r", "\t"].freeze
|
32
34
|
|
33
35
|
def parse_response?(env)
|
34
|
-
super
|
36
|
+
super && BRACKETS.include?(first_char(env[:body]))
|
35
37
|
end
|
36
38
|
|
37
39
|
def first_char(body)
|
38
40
|
idx = -1
|
39
|
-
|
40
|
-
|
41
|
-
char = char.chr if char
|
42
|
-
end while char and WHITESPACE.include? char
|
41
|
+
char = body[idx += 1]
|
42
|
+
char = body[idx += 1] while char && WHITESPACE.include?(char)
|
43
43
|
char
|
44
44
|
end
|
45
45
|
end
|
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'faraday_middleware/response_middleware'
|
2
4
|
|
3
5
|
module FaradayMiddleware
|
4
6
|
# Public: Restore marshalled Ruby objects in response bodies.
|
5
7
|
class ParseMarshal < ResponseMiddleware
|
6
8
|
define_parser do |body|
|
7
|
-
::Marshal.load
|
9
|
+
::Marshal.load(body) unless body.empty?
|
8
10
|
end
|
9
11
|
end
|
10
12
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'faraday_middleware/response_middleware'
|
2
4
|
|
3
5
|
module FaradayMiddleware
|
@@ -5,8 +7,8 @@ module FaradayMiddleware
|
|
5
7
|
class ParseXml < ResponseMiddleware
|
6
8
|
dependency 'multi_xml'
|
7
9
|
|
8
|
-
define_parser do |body|
|
9
|
-
::MultiXml.parse(body)
|
10
|
+
define_parser do |body, parser_options|
|
11
|
+
::MultiXml.parse(body, parser_options || {})
|
10
12
|
end
|
11
13
|
end
|
12
14
|
end
|
@@ -1,29 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'faraday_middleware/response_middleware'
|
2
4
|
|
3
5
|
module FaradayMiddleware
|
4
6
|
# Public: Parse response bodies as YAML.
|
5
7
|
#
|
6
|
-
# Warning:
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
8
|
+
# Warning: This is not backwards compatible with versions of this middleware
|
9
|
+
# prior to faraday_middleware v0.12 - prior to this version, we used
|
10
|
+
# YAML.load rather than YAMl.safe_load, which exposes serious remote code
|
11
|
+
# execution risks - see https://github.com/ruby/psych/issues/119 for details.
|
12
|
+
# If you're sure you can trust YAML you're passing, you can set up an unsafe
|
13
|
+
# version of this middleware like this:
|
14
|
+
#
|
15
|
+
# class UnsafelyParseYaml < FaradayMiddleware::ResponseMiddleware
|
16
|
+
# dependency do
|
17
|
+
# require 'yaml'
|
18
|
+
# end
|
11
19
|
#
|
12
|
-
# class SafeYaml < FaradayMiddleware::ParseYaml
|
13
20
|
# define_parser do |body|
|
14
|
-
# YAML.
|
21
|
+
# YAML.load body
|
15
22
|
# end
|
16
23
|
# end
|
17
24
|
#
|
18
25
|
# Faraday.new(..) do |config|
|
19
|
-
# config.use
|
26
|
+
# config.use UnsafelyParseYaml
|
20
27
|
# ...
|
21
28
|
# end
|
22
29
|
class ParseYaml < ResponseMiddleware
|
23
|
-
dependency '
|
30
|
+
dependency 'safe_yaml/load'
|
24
31
|
|
25
|
-
define_parser do |body|
|
26
|
-
|
32
|
+
define_parser do |body, parser_options|
|
33
|
+
SafeYAML.load(body, nil, parser_options || {})
|
27
34
|
end
|
28
35
|
end
|
29
36
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'faraday_middleware/response/mashify'
|
2
4
|
|
3
5
|
module FaradayMiddleware
|
@@ -6,7 +8,7 @@ module FaradayMiddleware
|
|
6
8
|
class Rashify < Mashify
|
7
9
|
dependency do
|
8
10
|
require 'rash'
|
9
|
-
self.mash_class = ::Hashie::Rash
|
11
|
+
self.mash_class = ::Hashie::Mash::Rash
|
10
12
|
end
|
11
13
|
end
|
12
14
|
end
|
@@ -1,42 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'faraday'
|
2
4
|
|
5
|
+
# Main FaradayMiddleware module.
|
3
6
|
module FaradayMiddleware
|
4
7
|
# Internal: The base class for middleware that parses responses.
|
5
8
|
class ResponseMiddleware < Faraday::Middleware
|
6
|
-
CONTENT_TYPE = 'Content-Type'
|
9
|
+
CONTENT_TYPE = 'Content-Type'
|
7
10
|
|
8
11
|
class << self
|
9
12
|
attr_accessor :parser
|
10
13
|
end
|
11
14
|
|
12
15
|
# Store a Proc that receives the body and returns the parsed result.
|
13
|
-
def self.define_parser(parser = nil)
|
14
|
-
@parser = parser ||
|
16
|
+
def self.define_parser(parser = nil, &block)
|
17
|
+
@parser = parser ||
|
18
|
+
block ||
|
19
|
+
raise(ArgumentError, 'Define parser with a block')
|
15
20
|
end
|
16
21
|
|
17
22
|
def self.inherited(subclass)
|
18
23
|
super
|
19
|
-
subclass.load_error =
|
20
|
-
subclass.parser =
|
24
|
+
subclass.load_error = load_error if subclass.respond_to? :load_error=
|
25
|
+
subclass.parser = parser
|
21
26
|
end
|
22
27
|
|
23
28
|
def initialize(app = nil, options = {})
|
24
29
|
super(app)
|
25
30
|
@options = options
|
31
|
+
@parser_options = options[:parser_options]
|
26
32
|
@content_types = Array(options[:content_type])
|
27
33
|
end
|
28
34
|
|
29
35
|
def call(environment)
|
30
36
|
@app.call(environment).on_complete do |env|
|
31
|
-
if process_response_type?(response_type(env))
|
32
|
-
process_response(env)
|
33
|
-
end
|
37
|
+
process_response(env) if process_response_type?(response_type(env)) && parse_response?(env)
|
34
38
|
end
|
35
39
|
end
|
36
40
|
|
37
41
|
def process_response(env)
|
38
42
|
env[:raw_body] = env[:body] if preserve_raw?(env)
|
39
43
|
env[:body] = parse(env[:body])
|
44
|
+
rescue Faraday::ParsingError => e
|
45
|
+
raise Faraday::ParsingError.new(e.wrapped_exception, env[:response])
|
40
46
|
end
|
41
47
|
|
42
48
|
# Parse the response body.
|
@@ -45,10 +51,12 @@ module FaradayMiddleware
|
|
45
51
|
def parse(body)
|
46
52
|
if self.class.parser
|
47
53
|
begin
|
48
|
-
self.class.parser.call(body)
|
49
|
-
rescue StandardError, SyntaxError =>
|
50
|
-
raise
|
51
|
-
|
54
|
+
self.class.parser.call(body, @parser_options)
|
55
|
+
rescue StandardError, SyntaxError => e
|
56
|
+
raise e if e.is_a?(SyntaxError) &&
|
57
|
+
e.class.name != 'Psych::SyntaxError'
|
58
|
+
|
59
|
+
raise Faraday::ParsingError, e
|
52
60
|
end
|
53
61
|
else
|
54
62
|
body
|
@@ -62,9 +70,9 @@ module FaradayMiddleware
|
|
62
70
|
end
|
63
71
|
|
64
72
|
def process_response_type?(type)
|
65
|
-
@content_types.empty?
|
73
|
+
@content_types.empty? || @content_types.any? do |pattern|
|
66
74
|
pattern.is_a?(Regexp) ? type =~ pattern : type == pattern
|
67
|
-
|
75
|
+
end
|
68
76
|
end
|
69
77
|
|
70
78
|
def parse_response?(env)
|
@@ -81,17 +89,18 @@ module FaradayMiddleware
|
|
81
89
|
attr_accessor :preserve_raw
|
82
90
|
|
83
91
|
def to_hash
|
84
|
-
super.update(:
|
92
|
+
super.update(preserve_raw: preserve_raw)
|
85
93
|
end
|
86
94
|
|
87
95
|
def each
|
88
96
|
return to_enum(:each) unless block_given?
|
97
|
+
|
89
98
|
super
|
90
99
|
yield :preserve_raw, preserve_raw
|
91
100
|
end
|
92
101
|
|
93
102
|
def fetch(key, *args)
|
94
|
-
if
|
103
|
+
if key == :preserve_raw
|
95
104
|
value = __send__(key)
|
96
105
|
value.nil? ? args.fetch(0) : value
|
97
106
|
else
|
@@ -102,9 +111,9 @@ module FaradayMiddleware
|
|
102
111
|
|
103
112
|
if defined?(Faraday::RequestOptions)
|
104
113
|
begin
|
105
|
-
Faraday::RequestOptions.from(:
|
114
|
+
Faraday::RequestOptions.from(preserve_raw: true)
|
106
115
|
rescue NoMethodError
|
107
|
-
Faraday::RequestOptions.
|
116
|
+
Faraday::RequestOptions.include OptionsExtension
|
108
117
|
end
|
109
118
|
end
|
110
119
|
end
|