actionpack 6.0.2.1 → 6.0.3.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionpack might be problematic. Click here for more details.

Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +31 -0
  3. data/README.rdoc +1 -1
  4. data/lib/abstract_controller/base.rb +0 -1
  5. data/lib/abstract_controller/caching.rb +1 -1
  6. data/lib/abstract_controller/collector.rb +0 -1
  7. data/lib/abstract_controller/helpers.rb +5 -4
  8. data/lib/abstract_controller/translation.rb +4 -5
  9. data/lib/action_controller/caching.rb +0 -1
  10. data/lib/action_controller/metal.rb +7 -5
  11. data/lib/action_controller/metal/content_security_policy.rb +0 -1
  12. data/lib/action_controller/metal/instrumentation.rb +0 -1
  13. data/lib/action_controller/metal/live.rb +0 -4
  14. data/lib/action_controller/metal/params_wrapper.rb +0 -1
  15. data/lib/action_controller/metal/rendering.rb +0 -1
  16. data/lib/action_controller/metal/request_forgery_protection.rb +27 -9
  17. data/lib/action_controller/metal/streaming.rb +0 -1
  18. data/lib/action_controller/metal/strong_parameters.rb +4 -0
  19. data/lib/action_controller/test_case.rb +7 -5
  20. data/lib/action_dispatch.rb +3 -0
  21. data/lib/action_dispatch/http/cache.rb +0 -1
  22. data/lib/action_dispatch/http/content_security_policy.rb +0 -2
  23. data/lib/action_dispatch/http/filter_parameters.rb +0 -1
  24. data/lib/action_dispatch/http/filter_redirect.rb +0 -1
  25. data/lib/action_dispatch/http/headers.rb +0 -1
  26. data/lib/action_dispatch/http/mime_negotiation.rb +0 -1
  27. data/lib/action_dispatch/http/mime_type.rb +1 -3
  28. data/lib/action_dispatch/http/parameters.rb +1 -2
  29. data/lib/action_dispatch/http/request.rb +9 -1
  30. data/lib/action_dispatch/http/response.rb +0 -1
  31. data/lib/action_dispatch/http/url.rb +0 -1
  32. data/lib/action_dispatch/journey/formatter.rb +0 -1
  33. data/lib/action_dispatch/journey/gtg/builder.rb +0 -1
  34. data/lib/action_dispatch/journey/gtg/transition_table.rb +0 -1
  35. data/lib/action_dispatch/journey/nfa/transition_table.rb +0 -1
  36. data/lib/action_dispatch/journey/path/pattern.rb +0 -1
  37. data/lib/action_dispatch/journey/router.rb +0 -1
  38. data/lib/action_dispatch/journey/routes.rb +0 -1
  39. data/lib/action_dispatch/journey/scanner.rb +0 -1
  40. data/lib/action_dispatch/journey/visitors.rb +0 -3
  41. data/lib/action_dispatch/middleware/actionable_exceptions.rb +1 -1
  42. data/lib/action_dispatch/middleware/cookies.rb +6 -6
  43. data/lib/action_dispatch/middleware/debug_exceptions.rb +7 -3
  44. data/lib/action_dispatch/middleware/debug_view.rb +3 -5
  45. data/lib/action_dispatch/middleware/exception_wrapper.rb +0 -1
  46. data/lib/action_dispatch/middleware/host_authorization.rb +0 -2
  47. data/lib/action_dispatch/middleware/public_exceptions.rb +0 -1
  48. data/lib/action_dispatch/middleware/remote_ip.rb +0 -1
  49. data/lib/action_dispatch/middleware/session/abstract_store.rb +0 -1
  50. data/lib/action_dispatch/middleware/session/cookie_store.rb +0 -1
  51. data/lib/action_dispatch/middleware/show_exceptions.rb +0 -1
  52. data/lib/action_dispatch/middleware/stack.rb +5 -1
  53. data/lib/action_dispatch/middleware/static.rb +1 -1
  54. data/lib/action_dispatch/request/session.rb +0 -1
  55. data/lib/action_dispatch/routing/inspector.rb +0 -2
  56. data/lib/action_dispatch/routing/mapper.rb +2 -3
  57. data/lib/action_dispatch/routing/polymorphic_routes.rb +0 -2
  58. data/lib/action_dispatch/routing/route_set.rb +1 -4
  59. data/lib/action_dispatch/routing/url_for.rb +0 -2
  60. data/lib/action_dispatch/system_test_case.rb +2 -3
  61. data/lib/action_dispatch/system_testing/driver.rb +2 -2
  62. data/lib/action_dispatch/testing/assertion_response.rb +0 -1
  63. data/lib/action_dispatch/testing/integration.rb +22 -7
  64. data/lib/action_pack/gem_version.rb +2 -2
  65. metadata +16 -16
@@ -154,7 +154,6 @@ module ActionDispatch
154
154
  end
155
155
 
156
156
  private
157
-
158
157
  BROWSER_LIKE_ACCEPTS = /,\s*\*\/\*|\*\/\*\s*,/
159
158
 
160
159
  def valid_accept_header # :doc:
@@ -225,7 +225,7 @@ module Mime
225
225
  MIME_NAME = "[a-zA-Z0-9][a-zA-Z0-9#{Regexp.escape('!#$&-^_.+')}]{0,126}"
226
226
  MIME_PARAMETER_KEY = "[a-zA-Z0-9][a-zA-Z0-9#{Regexp.escape('!#$&-^_.+')}]{0,126}"
227
227
  MIME_PARAMETER_VALUE = "#{Regexp.escape('"')}?[a-zA-Z0-9][a-zA-Z0-9#{Regexp.escape('!#$&-^_.+')}]{0,126}#{Regexp.escape('"')}?"
228
- MIME_PARAMETER = "\s*\;\s+#{MIME_PARAMETER_KEY}(?:\=#{MIME_PARAMETER_VALUE})?"
228
+ MIME_PARAMETER = "\s*\;\s*#{MIME_PARAMETER_KEY}(?:\=#{MIME_PARAMETER_VALUE})?"
229
229
  MIME_REGEXP = /\A(?:\*\/\*|#{MIME_NAME}\/(?:\*|#{MIME_NAME})(?:\s*#{MIME_PARAMETER}\s*)*)\z/
230
230
 
231
231
  class InvalidMimeType < StandardError; end
@@ -290,11 +290,9 @@ module Mime
290
290
  def all?; false; end
291
291
 
292
292
  protected
293
-
294
293
  attr_reader :string, :synonyms
295
294
 
296
295
  private
297
-
298
296
  def to_ary; end
299
297
  def to_a; end
300
298
 
@@ -85,7 +85,6 @@ module ActionDispatch
85
85
  end
86
86
 
87
87
  private
88
-
89
88
  def set_binary_encoding(params, controller, action)
90
89
  return params unless controller && controller.valid_encoding?
91
90
 
@@ -99,7 +98,7 @@ module ActionDispatch
99
98
 
100
99
  def binary_params_for?(controller, action)
101
100
  controller_class_for(controller).binary_params_for?(action)
102
- rescue NameError
101
+ rescue MissingController
103
102
  false
104
103
  end
105
104
 
@@ -85,7 +85,15 @@ module ActionDispatch
85
85
  if name
86
86
  controller_param = name.underscore
87
87
  const_name = "#{controller_param.camelize}Controller"
88
- ActiveSupport::Dependencies.constantize(const_name)
88
+ begin
89
+ ActiveSupport::Dependencies.constantize(const_name)
90
+ rescue NameError => error
91
+ if error.missing_name == const_name || const_name.start_with?("#{error.missing_name}::")
92
+ raise MissingController.new(error.message, error.name)
93
+ else
94
+ raise
95
+ end
96
+ end
89
97
  else
90
98
  PASS_NOT_FOUND
91
99
  end
@@ -143,7 +143,6 @@ module ActionDispatch # :nodoc:
143
143
  end
144
144
 
145
145
  private
146
-
147
146
  def each_chunk(&block)
148
147
  @buf.each(&block)
149
148
  end
@@ -78,7 +78,6 @@ module ActionDispatch
78
78
  end
79
79
 
80
80
  private
81
-
82
81
  def add_params(path, params)
83
82
  params = { params: params } unless params.is_a?(Hash)
84
83
  params.reject! { |_, v| v.to_param.nil? }
@@ -62,7 +62,6 @@ module ActionDispatch
62
62
  end
63
63
 
64
64
  private
65
-
66
65
  def extract_parameterized_parts(route, options, recall, parameterize = nil)
67
66
  parameterized_parts = recall.merge(options)
68
67
 
@@ -128,7 +128,6 @@ module ActionDispatch
128
128
  end
129
129
 
130
130
  private
131
-
132
131
  def followpos_table
133
132
  @followpos ||= build_followpos
134
133
  end
@@ -141,7 +141,6 @@ module ActionDispatch
141
141
  end
142
142
 
143
143
  private
144
-
145
144
  def states_hash_for(sym)
146
145
  case sym
147
146
  when String
@@ -94,7 +94,6 @@ module ActionDispatch
94
94
  end
95
95
 
96
96
  private
97
-
98
97
  def inverted
99
98
  return @inverted if @inverted
100
99
 
@@ -174,7 +174,6 @@ module ActionDispatch
174
174
  end
175
175
 
176
176
  private
177
-
178
177
  def regexp_visitor
179
178
  @anchored ? AnchoredRegexp : UnanchoredRegexp
180
179
  end
@@ -81,7 +81,6 @@ module ActionDispatch
81
81
  end
82
82
 
83
83
  private
84
-
85
84
  def partitioned_routes
86
85
  routes.partition { |r|
87
86
  r.path.anchored && r.ast.grep(Nodes::Symbol).all? { |n| n.default_regexp? }
@@ -71,7 +71,6 @@ module ActionDispatch
71
71
  end
72
72
 
73
73
  private
74
-
75
74
  def clear_cache!
76
75
  @ast = nil
77
76
  @simulator = nil
@@ -33,7 +33,6 @@ module ActionDispatch
33
33
  end
34
34
 
35
35
  private
36
-
37
36
  # takes advantage of String @- deduping capabilities in Ruby 2.5 upwards
38
37
  # see: https://bugs.ruby-lang.org/issues/13077
39
38
  def dedup_scan(regex)
@@ -59,7 +59,6 @@ module ActionDispatch
59
59
  end
60
60
 
61
61
  private
62
-
63
62
  def visit(node)
64
63
  send(DISPATCH_CACHE[node.type], node)
65
64
  end
@@ -168,7 +167,6 @@ module ActionDispatch
168
167
 
169
168
  class String < FunctionalVisitor # :nodoc:
170
169
  private
171
-
172
170
  def binary(node, seed)
173
171
  visit(node.right, visit(node.left, seed))
174
172
  end
@@ -214,7 +212,6 @@ module ActionDispatch
214
212
  end
215
213
 
216
214
  private
217
-
218
215
  def binary(node, seed)
219
216
  seed.last.concat node.children.map { |c|
220
217
  "#{node.object_id} -> #{c.object_id};"
@@ -23,7 +23,7 @@ module ActionDispatch
23
23
 
24
24
  private
25
25
  def actionable_request?(request)
26
- request.show_exceptions? && request.post? && request.path == endpoint
26
+ request.get_header("action_dispatch.show_detailed_exceptions") && request.post? && request.path == endpoint
27
27
  end
28
28
 
29
29
  def redirect_to(location)
@@ -252,7 +252,6 @@ module ActionDispatch
252
252
  end
253
253
 
254
254
  private
255
-
256
255
  def upgrade_legacy_hmac_aes_cbc_cookies?
257
256
  request.secret_key_base.present? &&
258
257
  request.encrypted_signed_cookie_salt.present? &&
@@ -428,7 +427,6 @@ module ActionDispatch
428
427
  mattr_accessor :always_write_cookie, default: false
429
428
 
430
429
  private
431
-
432
430
  def escape(string)
433
431
  ::Rack::Utils.escape(string)
434
432
  end
@@ -573,7 +571,8 @@ module ActionDispatch
573
571
  secret = request.key_generator.generate_key(request.signed_cookie_salt)
574
572
  @verifier = ActiveSupport::MessageVerifier.new(secret, digest: signed_cookie_digest, serializer: SERIALIZER)
575
573
 
576
- request.cookies_rotations.signed.each do |*secrets, **options|
574
+ request.cookies_rotations.signed.each do |(*secrets)|
575
+ options = secrets.extract_options!
577
576
  @verifier.rotate(*secrets, serializer: SERIALIZER, **options)
578
577
  end
579
578
  end
@@ -586,7 +585,7 @@ module ActionDispatch
586
585
  end
587
586
 
588
587
  def commit(name, options)
589
- options[:value] = @verifier.generate(serialize(options[:value]), cookie_metadata(name, options))
588
+ options[:value] = @verifier.generate(serialize(options[:value]), **cookie_metadata(name, options))
590
589
 
591
590
  raise CookieOverflow if options[:value].bytesize > MAX_COOKIE_SIZE
592
591
  end
@@ -609,7 +608,8 @@ module ActionDispatch
609
608
  @encryptor = ActiveSupport::MessageEncryptor.new(secret, sign_secret, cipher: "aes-256-cbc", serializer: SERIALIZER)
610
609
  end
611
610
 
612
- request.cookies_rotations.encrypted.each do |*secrets, **options|
611
+ request.cookies_rotations.encrypted.each do |(*secrets)|
612
+ options = secrets.extract_options!
613
613
  @encryptor.rotate(*secrets, serializer: SERIALIZER, **options)
614
614
  end
615
615
 
@@ -632,7 +632,7 @@ module ActionDispatch
632
632
  end
633
633
 
634
634
  def commit(name, options)
635
- options[:value] = @encryptor.encrypt_and_sign(serialize(options[:value]), cookie_metadata(name, options))
635
+ options[:value] = @encryptor.encrypt_and_sign(serialize(options[:value]), **cookie_metadata(name, options))
636
636
 
637
637
  raise CookieOverflow if options[:value].bytesize > MAX_COOKIE_SIZE
638
638
  end
@@ -44,7 +44,6 @@ module ActionDispatch
44
44
  end
45
45
 
46
46
  private
47
-
48
47
  def invoke_interceptors(request, exception)
49
48
  backtrace_cleaner = request.get_header("action_dispatch.backtrace_cleaner")
50
49
  wrapper = ExceptionWrapper.new(backtrace_cleaner, exception)
@@ -137,6 +136,7 @@ module ActionDispatch
137
136
 
138
137
  def log_error(request, wrapper)
139
138
  logger = logger(request)
139
+
140
140
  return unless logger
141
141
 
142
142
  exception = wrapper.exception
@@ -157,10 +157,14 @@ module ActionDispatch
157
157
  end
158
158
 
159
159
  def log_array(logger, array)
160
+ lines = Array(array)
161
+
162
+ return if lines.empty?
163
+
160
164
  if logger.formatter && logger.formatter.respond_to?(:tags_text)
161
- logger.fatal array.join("\n#{logger.formatter.tags_text}")
165
+ logger.fatal lines.join("\n#{logger.formatter.tags_text}")
162
166
  else
163
- logger.fatal array.join("\n")
167
+ logger.fatal lines.join("\n")
164
168
  end
165
169
  end
166
170
 
@@ -58,11 +58,9 @@ module ActionDispatch
58
58
  end
59
59
 
60
60
  def params_valid?
61
- begin
62
- @request.parameters
63
- rescue ActionController::BadRequest
64
- false
65
- end
61
+ @request.parameters
62
+ rescue ActionController::BadRequest
63
+ false
66
64
  end
67
65
  end
68
66
  end
@@ -130,7 +130,6 @@ module ActionDispatch
130
130
  end
131
131
 
132
132
  private
133
-
134
133
  def backtrace
135
134
  Array(@exception.backtrace)
136
135
  end
@@ -30,7 +30,6 @@ module ActionDispatch
30
30
  end
31
31
 
32
32
  private
33
-
34
33
  def sanitize_hosts(hosts)
35
34
  Array(hosts).map do |host|
36
35
  case host
@@ -87,7 +86,6 @@ module ActionDispatch
87
86
  end
88
87
 
89
88
  private
90
-
91
89
  def authorized?(request)
92
90
  origin_host = request.get_header("HTTP_HOST").to_s.sub(/:\d+\z/, "")
93
91
  forwarded_host = request.x_forwarded_host.to_s.split(/,\s?/).last.to_s.sub(/:\d+\z/, "")
@@ -32,7 +32,6 @@ module ActionDispatch
32
32
  end
33
33
 
34
34
  private
35
-
36
35
  def render(status, content_type, body)
37
36
  format = "to_#{content_type.to_sym}" if content_type
38
37
  if format && body.respond_to?(format)
@@ -156,7 +156,6 @@ module ActionDispatch
156
156
  end
157
157
 
158
158
  private
159
-
160
159
  def ips_from(header) # :doc:
161
160
  return [] unless header
162
161
  # Split the comma-separated list into an array of strings.
@@ -30,7 +30,6 @@ module ActionDispatch
30
30
  end
31
31
 
32
32
  private
33
-
34
33
  def initialize_sid # :doc:
35
34
  @default_options.delete(:sidbits)
36
35
  @default_options.delete(:secure_random)
@@ -76,7 +76,6 @@ module ActionDispatch
76
76
  end
77
77
 
78
78
  private
79
-
80
79
  def extract_session_id(req)
81
80
  stale_session_check! do
82
81
  sid = unpacked_cookie_data(req)["session_id"]
@@ -40,7 +40,6 @@ module ActionDispatch
40
40
  end
41
41
 
42
42
  private
43
-
44
43
  def render_exception(request, exception)
45
44
  backtrace_cleaner = request.get_header "action_dispatch.backtrace_cleaner"
46
45
  wrapper = ExceptionWrapper.new(backtrace_cleaner, exception)
@@ -91,6 +91,7 @@ module ActionDispatch
91
91
  def unshift(klass, *args, &block)
92
92
  middlewares.unshift(build_middleware(klass, args, block))
93
93
  end
94
+ ruby2_keywords(:unshift) if respond_to?(:ruby2_keywords, true)
94
95
 
95
96
  def initialize_copy(other)
96
97
  self.middlewares = other.middlewares.dup
@@ -100,6 +101,7 @@ module ActionDispatch
100
101
  index = assert_index(index, :before)
101
102
  middlewares.insert(index, build_middleware(klass, args, block))
102
103
  end
104
+ ruby2_keywords(:insert) if respond_to?(:ruby2_keywords, true)
103
105
 
104
106
  alias_method :insert_before, :insert
105
107
 
@@ -107,12 +109,14 @@ module ActionDispatch
107
109
  index = assert_index(index, :after)
108
110
  insert(index + 1, *args, &block)
109
111
  end
112
+ ruby2_keywords(:insert_after) if respond_to?(:ruby2_keywords, true)
110
113
 
111
114
  def swap(target, *args, &block)
112
115
  index = assert_index(target, :before)
113
116
  insert(index, *args, &block)
114
117
  middlewares.delete_at(index + 1)
115
118
  end
119
+ ruby2_keywords(:swap) if respond_to?(:ruby2_keywords, true)
116
120
 
117
121
  def delete(target)
118
122
  middlewares.delete_if { |m| m.klass == target }
@@ -121,6 +125,7 @@ module ActionDispatch
121
125
  def use(klass, *args, &block)
122
126
  middlewares.push(build_middleware(klass, args, block))
123
127
  end
128
+ ruby2_keywords(:use) if respond_to?(:ruby2_keywords, true)
124
129
 
125
130
  def build(app = nil, &block)
126
131
  instrumenting = ActiveSupport::Notifications.notifier.listening?(InstrumentationProxy::EVENT_NAME)
@@ -134,7 +139,6 @@ module ActionDispatch
134
139
  end
135
140
 
136
141
  private
137
-
138
142
  def assert_index(index, where)
139
143
  i = index.is_a?(Integer) ? index : middlewares.index { |m| m.klass == index }
140
144
  raise "No such middleware to insert #{where}: #{index.inspect}" unless i
@@ -42,7 +42,7 @@ module ActionDispatch
42
42
  false
43
43
  end
44
44
  }
45
- return ::Rack::Utils.escape_path(match).b
45
+ ::Rack::Utils.escape_path(match).b
46
46
  end
47
47
  end
48
48
 
@@ -222,7 +222,6 @@ module ActionDispatch
222
222
  end
223
223
 
224
224
  private
225
-
226
225
  def load_for_read!
227
226
  load! if !loaded? && exists?
228
227
  end
@@ -177,7 +177,6 @@ module ActionDispatch
177
177
  end
178
178
 
179
179
  private
180
-
181
180
  def draw_section(routes)
182
181
  header_lengths = ["Prefix", "Verb", "URI Pattern"].map(&:length)
183
182
  name_width, verb_width, path_width = widths(routes).zip(header_lengths).map(&:max)
@@ -210,7 +209,6 @@ module ActionDispatch
210
209
  end
211
210
 
212
211
  private
213
-
214
212
  def draw_expanded_section(routes)
215
213
  routes.map.each_with_index do |r, i|
216
214
  <<~MESSAGE.chomp
@@ -362,7 +362,7 @@ module ActionDispatch
362
362
 
363
363
  def translate_controller(controller)
364
364
  return controller if Regexp === controller
365
- return controller.to_s if controller =~ /\A[a-z_0-9][a-z_0-9\/]*\z/
365
+ return controller.to_s if /\A[a-z_0-9][a-z_0-9\/]*\z/.match?(controller)
366
366
 
367
367
  yield
368
368
  end
@@ -398,7 +398,7 @@ module ActionDispatch
398
398
  # for root cases, where the latter is the correct one.
399
399
  def self.normalize_path(path)
400
400
  path = Journey::Router::Utils.normalize_path(path)
401
- path.gsub!(%r{/(\(+)/?}, '\1/') unless path =~ %r{^/(\(+[^)]+\)){1,}$}
401
+ path.gsub!(%r{/(\(+)/?}, '\1/') unless %r{^/(\(+[^)]+\)){1,}$}.match?(path)
402
402
  path
403
403
  end
404
404
 
@@ -1668,7 +1668,6 @@ module ActionDispatch
1668
1668
  end
1669
1669
 
1670
1670
  private
1671
-
1672
1671
  def parent_resource
1673
1672
  @scope[:scope_level_resource]
1674
1673
  end