faraday_middleware 0.9.1 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
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