faraday_middleware 0.9.1 → 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.
Files changed (45) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +16 -22
  3. data/lib/faraday_middleware/backwards_compatibility.rb +16 -12
  4. data/lib/faraday_middleware/gzip.rb +90 -0
  5. data/lib/faraday_middleware/instrumentation.rb +9 -3
  6. data/lib/faraday_middleware/rack_compatible.rb +18 -11
  7. data/lib/faraday_middleware/redirect_limit_reached.rb +16 -0
  8. data/lib/faraday_middleware/request/encode_json.rb +12 -9
  9. data/lib/faraday_middleware/request/method_override.rb +7 -6
  10. data/lib/faraday_middleware/request/oauth.rb +13 -10
  11. data/lib/faraday_middleware/request/oauth2.rb +37 -12
  12. data/lib/faraday_middleware/response/caching.rb +67 -15
  13. data/lib/faraday_middleware/response/chunked.rb +10 -6
  14. data/lib/faraday_middleware/response/follow_redirects.rb +85 -70
  15. data/lib/faraday_middleware/response/mashify.rb +2 -0
  16. data/lib/faraday_middleware/response/parse_dates.rb +6 -3
  17. data/lib/faraday_middleware/response/parse_json.rb +10 -10
  18. data/lib/faraday_middleware/response/parse_marshal.rb +3 -1
  19. data/lib/faraday_middleware/response/parse_xml.rb +4 -2
  20. data/lib/faraday_middleware/response/parse_yaml.rb +27 -3
  21. data/lib/faraday_middleware/response/rashify.rb +3 -1
  22. data/lib/faraday_middleware/response_middleware.rb +27 -18
  23. data/lib/faraday_middleware/version.rb +4 -1
  24. data/lib/faraday_middleware.rb +22 -16
  25. metadata +10 -65
  26. data/CHANGELOG.md +0 -10
  27. data/CONTRIBUTING.md +0 -46
  28. data/Rakefile +0 -28
  29. data/faraday_middleware.gemspec +0 -23
  30. data/lib/faraday_middleware/addressable_patch.rb +0 -20
  31. data/spec/caching_spec.rb +0 -170
  32. data/spec/chunked_spec.rb +0 -78
  33. data/spec/encode_json_spec.rb +0 -95
  34. data/spec/follow_redirects_spec.rb +0 -221
  35. data/spec/helper.rb +0 -59
  36. data/spec/mashify_spec.rb +0 -70
  37. data/spec/method_override_spec.rb +0 -92
  38. data/spec/oauth2_spec.rb +0 -118
  39. data/spec/oauth_spec.rb +0 -151
  40. data/spec/parse_dates_spec.rb +0 -44
  41. data/spec/parse_json_spec.rb +0 -112
  42. data/spec/parse_marshal_spec.rb +0 -16
  43. data/spec/parse_xml_spec.rb +0 -71
  44. data/spec/parse_yaml_spec.rb +0 -53
  45. data/spec/rashify_spec.rb +0 -47
@@ -1,40 +1,66 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'faraday'
2
4
  require 'forwardable'
3
- # fixes normalizing query strings:
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
10
11
 
12
+ # Internal: List of status codes that can be cached:
13
+ # * 200 - 'OK'
14
+ # * 203 - 'Non-Authoritative Information'
15
+ # * 300 - 'Multiple Choices'
16
+ # * 301 - 'Moved Permanently'
17
+ # * 302 - 'Found'
18
+ # * 404 - 'Not Found'
19
+ # * 410 - 'Gone'
20
+ CACHEABLE_STATUS_CODES = [200, 203, 300, 301, 302, 404, 410].freeze
21
+
11
22
  extend Forwardable
12
23
  def_delegators :'Faraday::Utils', :parse_query, :build_query
13
24
 
14
25
  # Public: initialize the middleware.
15
26
  #
16
- # cache - An object that responds to read, write and fetch (default: nil).
27
+ # cache - An object that responds to read and write (default: nil).
17
28
  # options - An options Hash (default: {}):
18
- # :ignore_params - String name or Array names of query params
19
- # that should be ignored when forming the cache
20
- # key (default: []).
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)
21
40
  #
22
41
  # Yields if no cache is given. The block should return a cache object.
23
42
  def initialize(app, cache = nil, options = {})
24
43
  super(app)
25
- options, cache = cache, nil if cache.is_a? Hash and block_given?
44
+ if cache.is_a?(Hash) && block_given?
45
+ options = cache
46
+ cache = nil
47
+ end
26
48
  @cache = cache || yield
27
49
  @options = options
28
50
  end
29
51
 
30
52
  def call(env)
31
- if :get == env[:method]
53
+ if env[:method] == :get
32
54
  if env[:parallel_manager]
33
55
  # callback mode
34
56
  cache_on_complete(env)
35
57
  else
36
58
  # synchronous mode
37
- response = cache.fetch(cache_key(env)) { @app.call(env) }
59
+ key = cache_key(env)
60
+ unless (response = cache.read(key)) && response
61
+ response = @app.call(env)
62
+ store_response_in_cache(key, response)
63
+ end
38
64
  finalize_response(response, env)
39
65
  end
40
66
  else
@@ -46,24 +72,50 @@ module FaradayMiddleware
46
72
  url = env[:url].dup
47
73
  if url.query && params_to_ignore.any?
48
74
  params = parse_query url.query
49
- params.reject! {|k,| params_to_ignore.include? k }
75
+ params.reject! { |k,| params_to_ignore.include? k }
50
76
  url.query = params.any? ? build_query(params) : nil
51
77
  end
52
78
  url.normalize!
53
- url.request_uri
79
+ digest = full_key? ? url.host + url.request_uri : url.request_uri
80
+ Digest::SHA1.hexdigest(digest)
54
81
  end
55
82
 
56
83
  def params_to_ignore
57
- @params_to_ignore ||= Array(@options[:ignore_params]).map { |p| p.to_s }
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
58
96
  end
59
97
 
60
98
  def cache_on_complete(env)
61
99
  key = cache_key(env)
62
- if cached_response = cache.read(key)
100
+ if (cached_response = cache.read(key))
63
101
  finalize_response(cached_response, env)
64
102
  else
65
- response = @app.call(env)
66
- response.on_complete { cache.write(key, response) }
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
108
+ end
109
+ end
110
+ end
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)
67
119
  end
68
120
  end
69
121
 
@@ -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: Chunked response to just the original data
6
+ # Public: Parse a Transfer-Encoding. Chunks response to just the original data
5
7
  class Chunked < FaradayMiddleware::ResponseMiddleware
6
- TRANSFER_ENCODING = 'transfer-encoding'.freeze
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 == 0
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 and chunked_encoding?(env[:response_headers])
25
+ super && chunked_encoding?(env[:response_headers])
23
26
  end
24
27
 
25
28
  def chunked_encoding?(headers)
26
- encoding = headers[TRANSFER_ENCODING] and encoding.split(',').include?('chunked')
29
+ (encoding = headers[TRANSFER_ENCODING]) &&
30
+ encoding.split(',').include?('chunked')
27
31
  end
28
32
  end
29
33
  end
@@ -1,64 +1,66 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'faraday'
2
4
  require 'set'
3
5
 
4
6
  module FaradayMiddleware
5
- # Public: Exception thrown when the maximum amount of requests is exceeded.
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 for GET, PATCH, POST,
16
- # PUT, and DELETE requests.
7
+ # Public: Follow HTTP 301, 302, 303, 307, and 308 redirects.
17
8
  #
18
- # This middleware does not follow the HTTP specification for HTTP 302, by
19
- # default, in that it follows the improper implementation used by most major
20
- # web browsers which forces the redirected request to become a GET request
21
- # regardless of the original request method.
9
+ # For HTTP 301, 302, and 303, the original GET, POST, PUT, DELETE, or PATCH
10
+ # request gets converted into a GET. With `:standards_compliant => true`,
11
+ # however, the HTTP method after 301/302 remains unchanged. This allows you
12
+ # to opt into HTTP/1.1 compliance and act unlike the major web browsers.
22
13
  #
23
- # For HTTP 301, 302, and 303, the original request is transformed into a
24
- # GET request to the response Location, by default. However, with standards
25
- # compliance enabled, a 302 will instead act in accordance with the HTTP
26
- # specification, which will replay the original request to the received
27
- # Location, just as with a 307.
14
+ # This middleware currently only works with synchronous requests; i.e. it
15
+ # doesn't support parallelism.
28
16
  #
29
- # For HTTP 307, the original request is replayed to the response Location,
30
- # including original HTTP request method (GET, POST, PUT, DELETE, PATCH),
31
- # original headers, and original body.
17
+ # If you wish to persist cookies across redirects, you could use
18
+ # the faraday-cookie_jar gem:
32
19
  #
33
- # This middleware currently only works with synchronous requests; in other
34
- # words, it doesn't support parallelism.
20
+ # Faraday.new(:url => url) do |faraday|
21
+ # faraday.use FaradayMiddleware::FollowRedirects
22
+ # faraday.use :cookie_jar
23
+ # faraday.adapter Faraday.default_adapter
24
+ # end
35
25
  class FollowRedirects < Faraday::Middleware
36
26
  # HTTP methods for which 30x redirects can be followed
37
- ALLOWED_METHODS = Set.new [:head, :options, :get, :post, :put, :patch, :delete]
27
+ ALLOWED_METHODS = Set.new %i[head options get post put patch delete]
38
28
  # HTTP redirect status codes that this middleware implements
39
- REDIRECT_CODES = Set.new [301, 302, 303, 307]
29
+ REDIRECT_CODES = Set.new [301, 302, 303, 307, 308]
40
30
  # Keys in env hash which will get cleared between requests
41
- ENV_TO_CLEAR = Set.new [:status, :response, :response_headers]
31
+ ENV_TO_CLEAR = Set.new %i[status response response_headers]
42
32
 
43
33
  # Default value for max redirects followed
44
34
  FOLLOW_LIMIT = 3
45
35
 
36
+ # Regex that matches characters that need to be escaped in URLs, sans
37
+ # the "%" character which we assume already represents an escaped sequence.
38
+ URI_UNSAFE = %r{[^\-_.!~*'()a-zA-Z\d;/?:@&=+$,\[\]%]}.freeze
39
+
40
+ AUTH_HEADER = 'Authorization'
41
+
46
42
  # Public: Initialize the middleware.
47
43
  #
48
44
  # options - An options Hash (default: {}):
49
- # limit - A Numeric redirect limit (default: 3)
50
- # standards_compliant - A Boolean indicating whether to respect
51
- # the HTTP spec when following 302
52
- # (default: false)
53
- # cookie - Use either an array of strings
54
- # (e.g. ['cookie1', 'cookie2']) to choose kept cookies
55
- # or :all to keep all cookies.
45
+ # :limit - A Numeric redirect limit (default: 3)
46
+ # :standards_compliant - A Boolean indicating whether to respect
47
+ # the HTTP spec when following 301/302
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)
56
58
  def initialize(app, options = {})
57
59
  super(app)
58
60
  @options = options
59
61
 
60
- @replay_request_codes = Set.new [307]
61
- @replay_request_codes << 302 if standards_compliant?
62
+ @convert_to_get = Set.new [303]
63
+ @convert_to_get << 301 << 302 unless standards_compliant?
62
64
  end
63
65
 
64
66
  def call(env)
@@ -67,76 +69,89 @@ module FaradayMiddleware
67
69
 
68
70
  private
69
71
 
70
- def transform_into_get?(response)
71
- return false if [:head, :options].include? response.env[:method]
72
- # Never convert head or options to a get. That would just be silly.
73
-
74
- !@replay_request_codes.include? response.status
72
+ def convert_to_get?(response)
73
+ !%i[head options].include?(response.env[:method]) &&
74
+ @convert_to_get.include?(response.status)
75
75
  end
76
76
 
77
77
  def perform_with_redirection(env, follows)
78
78
  request_body = env[:body]
79
79
  response = @app.call(env)
80
80
 
81
- response.on_complete do |env|
82
- if follow_redirect?(env, response)
81
+ response.on_complete do |response_env|
82
+ if follow_redirect?(response_env, response)
83
83
  raise RedirectLimitReached, response if follows.zero?
84
- env = update_env(env, request_body, response)
85
- response = perform_with_redirection(env, follows - 1)
84
+
85
+ new_request_env = update_env(response_env.dup, request_body, response)
86
+ callback&.call(response_env, new_request_env)
87
+ response = perform_with_redirection(new_request_env, follows - 1)
86
88
  end
87
89
  end
88
90
  response
89
91
  end
90
92
 
91
93
  def update_env(env, request_body, response)
92
- env[:url] += response['location']
93
- if @options[:cookies]
94
- cookies = keep_cookies(env)
95
- env[:request_headers][:cookies] = cookies unless cookies.nil?
96
- end
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 }
97
99
 
98
- if transform_into_get?(response)
100
+ if convert_to_get?(response)
99
101
  env[:method] = :get
100
102
  env[:body] = nil
101
103
  else
102
104
  env[:body] = request_body
103
105
  end
104
106
 
105
- ENV_TO_CLEAR.each {|key| env.delete key }
107
+ clear_authorization_header(env, redirect_from_url, redirect_to_url)
106
108
 
107
109
  env
108
110
  end
109
111
 
110
112
  def follow_redirect?(env, response)
111
- ALLOWED_METHODS.include? env[:method] and
112
- REDIRECT_CODES.include? response.status
113
+ ALLOWED_METHODS.include?(env[:method]) &&
114
+ REDIRECT_CODES.include?(response.status)
113
115
  end
114
116
 
115
117
  def follow_limit
116
118
  @options.fetch(:limit, FOLLOW_LIMIT)
117
119
  end
118
120
 
119
- def keep_cookies(env)
120
- cookies = @options.fetch(:cookies, [])
121
- response_cookies = env[:response_headers][:cookies]
122
- cookies == :all ? response_cookies : selected_request_cookies(response_cookies)
121
+ def standards_compliant?
122
+ @options.fetch(:standards_compliant, false)
123
123
  end
124
124
 
125
- def selected_request_cookies(cookies)
126
- selected_cookies(cookies)[0...-1]
125
+ def callback
126
+ @options[:callback]
127
127
  end
128
128
 
129
- def selected_cookies(cookies)
130
- "".tap do |cookie_string|
131
- @options[:cookies].each do |cookie|
132
- string = /#{cookie}=?[^;]*/.match(cookies)[0] + ';'
133
- cookie_string << string
134
- end
129
+ # Internal: escapes unsafe characters from an URL which might be a path
130
+ # component only or a fully qualified URI so that it can be joined onto an
131
+ # URI:HTTP using the `+` operator. Doesn't escape "%" characters so to not
132
+ # risk double-escaping.
133
+ def safe_escape(uri)
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}"
135
137
  end
136
138
  end
137
139
 
138
- def standards_compliant?
139
- @options.fetch(:standards_compliant, false)
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]
140
155
  end
141
156
  end
142
157
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'faraday'
2
4
 
3
5
  module FaradayMiddleware
@@ -1,10 +1,13 @@
1
- require "time"
2
- require "faraday"
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+)?Z\Z/m
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 body unless body.strip.empty?
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'.freeze
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 = [ " ", "\n", "\r", "\t" ]
32
+ BRACKETS = %w-[ {-.freeze
33
+ WHITESPACE = [' ', "\n", "\r", "\t"].freeze
32
34
 
33
35
  def parse_response?(env)
34
- super and BRACKETS.include? first_char(env[:body])
36
+ super && BRACKETS.include?(first_char(env[:body]))
35
37
  end
36
38
 
37
39
  def first_char(body)
38
40
  idx = -1
39
- begin
40
- char = body[idx += 1]
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 body unless body.empty?
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,12 +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.
7
+ #
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
19
+ #
20
+ # define_parser do |body|
21
+ # YAML.load body
22
+ # end
23
+ # end
24
+ #
25
+ # Faraday.new(..) do |config|
26
+ # config.use UnsafelyParseYaml
27
+ # ...
28
+ # end
5
29
  class ParseYaml < ResponseMiddleware
6
- dependency 'yaml'
30
+ dependency 'safe_yaml/load'
7
31
 
8
- define_parser do |body|
9
- ::YAML.load body
32
+ define_parser do |body, parser_options|
33
+ SafeYAML.load(body, nil, parser_options || {})
10
34
  end
11
35
  end
12
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