actionpack 6.0.2.2 → 6.0.3.rc1

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 (63) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +21 -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 +0 -2
  17. data/lib/action_controller/metal/streaming.rb +0 -1
  18. data/lib/action_controller/test_case.rb +7 -5
  19. data/lib/action_dispatch.rb +3 -0
  20. data/lib/action_dispatch/http/cache.rb +0 -1
  21. data/lib/action_dispatch/http/content_security_policy.rb +0 -2
  22. data/lib/action_dispatch/http/filter_parameters.rb +0 -1
  23. data/lib/action_dispatch/http/filter_redirect.rb +0 -1
  24. data/lib/action_dispatch/http/headers.rb +0 -1
  25. data/lib/action_dispatch/http/mime_negotiation.rb +0 -1
  26. data/lib/action_dispatch/http/mime_type.rb +1 -3
  27. data/lib/action_dispatch/http/parameters.rb +1 -2
  28. data/lib/action_dispatch/http/request.rb +9 -1
  29. data/lib/action_dispatch/http/response.rb +0 -1
  30. data/lib/action_dispatch/http/url.rb +0 -1
  31. data/lib/action_dispatch/journey/formatter.rb +0 -1
  32. data/lib/action_dispatch/journey/gtg/builder.rb +0 -1
  33. data/lib/action_dispatch/journey/gtg/transition_table.rb +0 -1
  34. data/lib/action_dispatch/journey/nfa/transition_table.rb +0 -1
  35. data/lib/action_dispatch/journey/path/pattern.rb +0 -1
  36. data/lib/action_dispatch/journey/router.rb +0 -1
  37. data/lib/action_dispatch/journey/routes.rb +0 -1
  38. data/lib/action_dispatch/journey/scanner.rb +0 -1
  39. data/lib/action_dispatch/journey/visitors.rb +0 -3
  40. data/lib/action_dispatch/middleware/cookies.rb +6 -6
  41. data/lib/action_dispatch/middleware/debug_exceptions.rb +7 -3
  42. data/lib/action_dispatch/middleware/debug_view.rb +3 -5
  43. data/lib/action_dispatch/middleware/exception_wrapper.rb +0 -1
  44. data/lib/action_dispatch/middleware/host_authorization.rb +0 -2
  45. data/lib/action_dispatch/middleware/public_exceptions.rb +0 -1
  46. data/lib/action_dispatch/middleware/remote_ip.rb +0 -1
  47. data/lib/action_dispatch/middleware/session/abstract_store.rb +0 -1
  48. data/lib/action_dispatch/middleware/session/cookie_store.rb +0 -1
  49. data/lib/action_dispatch/middleware/show_exceptions.rb +0 -1
  50. data/lib/action_dispatch/middleware/stack.rb +5 -1
  51. data/lib/action_dispatch/middleware/static.rb +1 -1
  52. data/lib/action_dispatch/request/session.rb +0 -1
  53. data/lib/action_dispatch/routing/inspector.rb +0 -2
  54. data/lib/action_dispatch/routing/mapper.rb +2 -3
  55. data/lib/action_dispatch/routing/polymorphic_routes.rb +0 -2
  56. data/lib/action_dispatch/routing/route_set.rb +1 -4
  57. data/lib/action_dispatch/routing/url_for.rb +0 -2
  58. data/lib/action_dispatch/system_test_case.rb +2 -3
  59. data/lib/action_dispatch/system_testing/driver.rb +2 -2
  60. data/lib/action_dispatch/testing/assertion_response.rb +0 -1
  61. data/lib/action_dispatch/testing/integration.rb +22 -7
  62. data/lib/action_pack/gem_version.rb +2 -2
  63. metadata +15 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d94612f90167188b102245be54e8d81f3af10bdda41bf70157b948ac45b7cd15
4
- data.tar.gz: 3cb22c8d148b07e36a92a844f1dfb8144ae12b75d35e6a6bdfb26640e125c9c6
3
+ metadata.gz: f7aba984bfea9afffd852375db3df2f8a08f17550240df3fbc0e5af0454023c2
4
+ data.tar.gz: 0d1d6dd332bcd4cd6779bb7491b9f47ecd79c037842067610c0ad2542c048df9
5
5
  SHA512:
6
- metadata.gz: 55af593812bce57ea8b9da727aa2ce44356c98cf6a7bc84cd2a920499e7d3d14267beb5eb1f055dc9739bbde55292a27830895a76cbefaf2b54554eff2085785
7
- data.tar.gz: a49377e7c82f2464b4b194658b9b93e6e313622601b158e48a613c57972bbbf808467a7fd658d28d645177b5d072d2fc19652954c183fa66c0599f47142960db
6
+ metadata.gz: c67bc93ad10a007615ddcde003392e1035626f8bafd2ba2fb19bdecc0749bb10f234115b78f106a5fc0e3473d96ce055a9788112898fecdf5a9552d34ba9b267
7
+ data.tar.gz: 2225dd79cadfee6d505bfd215b896b65bbe621a727c6f72db6fb8e01d246a0c09b6138c1e9f61128883647706e66bc37e2c2efecbcc76371aa6d60fb6b2a0733
@@ -1,3 +1,24 @@
1
+ ## Rails 6.0.3.rc1 (April 30, 2020) ##
2
+
3
+ * Include child session assertion count in ActionDispatch::IntegrationTest
4
+
5
+ `IntegrationTest#open_session` uses `dup` to create the new session, which
6
+ meant it had its own copy of `@assertions`. This prevented the assertions
7
+ from being correctly counted and reported.
8
+
9
+ Child sessions now have their `attr_accessor` overriden to delegate to the
10
+ root session.
11
+
12
+ Fixes #32142
13
+
14
+ *Sam Bostock*
15
+
16
+
17
+ ## Rails 6.0.2.2 (March 19, 2020) ##
18
+
19
+ * No changes.
20
+
21
+
1
22
  ## Rails 6.0.2.1 (December 18, 2019) ##
2
23
 
3
24
  * Fix possible information leak / session hijacking vulnerability.
@@ -55,4 +55,4 @@ Bug reports for the Ruby on Rails project can be filed here:
55
55
 
56
56
  Feature requests should be discussed on the rails-core mailing list here:
57
57
 
58
- * https://groups.google.com/forum/?fromgroups#!forum/rubyonrails-core
58
+ * https://discuss.rubyonrails.org/c/rubyonrails-core
@@ -176,7 +176,6 @@ module AbstractController
176
176
  end
177
177
 
178
178
  private
179
-
180
179
  # Returns true if the name can be considered an action because
181
180
  # it has a method defined in the controller.
182
181
  #
@@ -15,7 +15,7 @@ module AbstractController
15
15
  end
16
16
 
17
17
  def cache_store=(store)
18
- config.cache_store = ActiveSupport::Cache.lookup_store(store)
18
+ config.cache_store = ActiveSupport::Cache.lookup_store(*store)
19
19
  end
20
20
 
21
21
  private
@@ -22,7 +22,6 @@ module AbstractController
22
22
  end
23
23
 
24
24
  private
25
-
26
25
  def method_missing(symbol, &block)
27
26
  unless mime_constant = Mime[symbol]
28
27
  raise NoMethodError, "To respond to a custom format, register it as a MIME type first: " \
@@ -61,11 +61,12 @@ module AbstractController
61
61
  meths.flatten!
62
62
  self._helper_methods += meths
63
63
 
64
- meths.each do |meth|
64
+ meths.each do |method|
65
65
  _helpers.class_eval <<-ruby_eval, __FILE__, __LINE__ + 1
66
- def #{meth}(*args, &blk) # def current_user(*args, &blk)
67
- controller.send(%(#{meth}), *args, &blk) # controller.send(:current_user, *args, &blk)
68
- end # end
66
+ def #{method}(*args, &blk) # def current_user(*args, &blk)
67
+ controller.send(%(#{method}), *args, &blk) # controller.send(:current_user, *args, &blk)
68
+ end # end
69
+ ruby2_keywords(%(#{method})) if respond_to?(:ruby2_keywords, true)
69
70
  ruby_eval
70
71
  end
71
72
  end
@@ -10,8 +10,7 @@ module AbstractController
10
10
  # <tt>I18n.translate("people.index.foo")</tt>. This makes it less repetitive
11
11
  # to translate many keys within the same controller / action and gives you a
12
12
  # simple framework for scoping them consistently.
13
- def translate(key, options = {})
14
- options = options.dup
13
+ def translate(key, **options)
15
14
  if key.to_s.first == "."
16
15
  path = controller_path.tr("/", ".")
17
16
  defaults = [:"#{path}#{key}"]
@@ -19,13 +18,13 @@ module AbstractController
19
18
  options[:default] = defaults.flatten
20
19
  key = "#{path}.#{action_name}#{key}"
21
20
  end
22
- I18n.translate(key, options)
21
+ I18n.translate(key, **options)
23
22
  end
24
23
  alias :t :translate
25
24
 
26
25
  # Delegates to <tt>I18n.localize</tt>. Also aliased as <tt>l</tt>.
27
- def localize(*args)
28
- I18n.localize(*args)
26
+ def localize(object, **options)
27
+ I18n.localize(object, **options)
29
28
  end
30
29
  alias :l :localize
31
30
  end
@@ -30,7 +30,6 @@ module ActionController
30
30
  end
31
31
 
32
32
  private
33
-
34
33
  def instrument_payload(key)
35
34
  {
36
35
  controller: controller_name,
@@ -35,7 +35,6 @@ module ActionController
35
35
  end
36
36
 
37
37
  private
38
-
39
38
  INCLUDE = ->(list, action) { list.include? action }
40
39
  EXCLUDE = ->(list, action) { !list.include? action }
41
40
  NULL = ->(list, action) { true }
@@ -217,10 +216,13 @@ module ActionController
217
216
  super
218
217
  end
219
218
 
220
- # Pushes the given Rack middleware and its arguments to the bottom of the
221
- # middleware stack.
222
- def self.use(*args, &block)
223
- middleware_stack.use(*args, &block)
219
+ class << self
220
+ # Pushes the given Rack middleware and its arguments to the bottom of the
221
+ # middleware stack.
222
+ def use(*args, &block)
223
+ middleware_stack.use(*args, &block)
224
+ end
225
+ ruby2_keywords(:use) if respond_to?(:ruby2_keywords, true)
224
226
  end
225
227
 
226
228
  # Alias for +middleware_stack+.
@@ -36,7 +36,6 @@ module ActionController #:nodoc:
36
36
  end
37
37
 
38
38
  private
39
-
40
39
  def content_security_policy?
41
40
  request.content_security_policy
42
41
  end
@@ -69,7 +69,6 @@ module ActionController
69
69
  end
70
70
 
71
71
  private
72
-
73
72
  # A hook invoked every time a before callback is halted.
74
73
  def halted_callback_hook(filter)
75
74
  ActiveSupport::Notifications.instrument("halted_callback.action_controller", filter: filter)
@@ -107,7 +107,6 @@ module ActionController
107
107
  end
108
108
 
109
109
  private
110
-
111
110
  def perform_write(json, options)
112
111
  current_options = @options.merge(options).stringify_keys
113
112
 
@@ -205,7 +204,6 @@ module ActionController
205
204
  end
206
205
 
207
206
  private
208
-
209
207
  def each_chunk(&block)
210
208
  loop do
211
209
  str = nil
@@ -220,7 +218,6 @@ module ActionController
220
218
 
221
219
  class Response < ActionDispatch::Response #:nodoc: all
222
220
  private
223
-
224
221
  def before_committed
225
222
  super
226
223
  jar = request.cookie_jar
@@ -286,7 +283,6 @@ module ActionController
286
283
  end
287
284
 
288
285
  private
289
-
290
286
  # Spawn a new thread to serve up the controller in. This is to get
291
287
  # around the fact that Rack isn't based around IOs and we need to use
292
288
  # a thread to stream data from the response bodies. Nobody should call
@@ -246,7 +246,6 @@ module ActionController
246
246
  end
247
247
 
248
248
  private
249
-
250
249
  # Returns the wrapper key which will be used to store wrapped parameters.
251
250
  def _wrapper_key
252
251
  _wrapper_options.name
@@ -53,7 +53,6 @@ module ActionController
53
53
  end
54
54
 
55
55
  private
56
-
57
56
  def _process_variant(options)
58
57
  if defined?(request) && !request.nil? && request.variant.present?
59
58
  options[:variant] = request.variant
@@ -151,7 +151,6 @@ module ActionController #:nodoc:
151
151
  end
152
152
 
153
153
  private
154
-
155
154
  def protection_method_class(name)
156
155
  ActionController::RequestForgeryProtection::ProtectionMethods.const_get(name.to_s.classify)
157
156
  rescue NameError
@@ -175,7 +174,6 @@ module ActionController #:nodoc:
175
174
  end
176
175
 
177
176
  private
178
-
179
177
  class NullSessionHash < Rack::Session::Abstract::SessionHash #:nodoc:
180
178
  def initialize(req)
181
179
  super(nil, req)
@@ -196,7 +196,6 @@ module ActionController #:nodoc:
196
196
  extend ActiveSupport::Concern
197
197
 
198
198
  private
199
-
200
199
  # Set proper cache control and transfer encoding when streaming
201
200
  def _process_options(options)
202
201
  super
@@ -158,7 +158,6 @@ module ActionController
158
158
  end.new
159
159
 
160
160
  private
161
-
162
161
  def params_parsers
163
162
  super.merge @custom_param_parsers
164
163
  end
@@ -177,12 +176,12 @@ module ActionController
177
176
 
178
177
  # Methods #destroy and #load! are overridden to avoid calling methods on the
179
178
  # @store object, which does not exist for the TestSession class.
180
- class TestSession < Rack::Session::Abstract::SessionHash #:nodoc:
179
+ class TestSession < Rack::Session::Abstract::PersistedSecure::SecureSessionHash #:nodoc:
181
180
  DEFAULT_OPTIONS = Rack::Session::Abstract::Persisted::DEFAULT_OPTIONS
182
181
 
183
182
  def initialize(session = {})
184
183
  super(nil, nil)
185
- @id = SecureRandom.hex(16)
184
+ @id = Rack::Session::SessionId.new(SecureRandom.hex(16))
186
185
  @data = stringify_keys(session)
187
186
  @loaded = true
188
187
  end
@@ -203,12 +202,16 @@ module ActionController
203
202
  clear
204
203
  end
205
204
 
205
+ def dig(*keys)
206
+ keys = keys.map.with_index { |key, i| i.zero? ? key.to_s : key }
207
+ @data.dig(*keys)
208
+ end
209
+
206
210
  def fetch(key, *args, &block)
207
211
  @data.fetch(key.to_s, *args, &block)
208
212
  end
209
213
 
210
214
  private
211
-
212
215
  def load!
213
216
  @id
214
217
  end
@@ -595,7 +598,6 @@ module ActionController
595
598
  end
596
599
 
597
600
  private
598
-
599
601
  def scrub_env!(env)
600
602
  env.delete_if { |k, v| k =~ /^(action_dispatch|rack)\.request/ }
601
603
  env.delete_if { |k, v| k =~ /^action_dispatch\.rescue/ }
@@ -40,6 +40,9 @@ module ActionDispatch
40
40
  class IllegalStateError < StandardError
41
41
  end
42
42
 
43
+ class MissingController < NameError
44
+ end
45
+
43
46
  eager_autoload do
44
47
  autoload_under "http" do
45
48
  autoload :ContentSecurityPolicy
@@ -123,7 +123,6 @@ module ActionDispatch
123
123
  end
124
124
 
125
125
  private
126
-
127
126
  DATE = "Date"
128
127
  LAST_MODIFIED = "Last-Modified"
129
128
  SPECIAL_KEYS = Set.new(%w[extras no-cache max-age public private must-revalidate])
@@ -31,7 +31,6 @@ module ActionDispatch #:nodoc:
31
31
  end
32
32
 
33
33
  private
34
-
35
34
  def html_response?(headers)
36
35
  if content_type = headers[CONTENT_TYPE]
37
36
  content_type =~ /html/
@@ -101,7 +100,6 @@ module ActionDispatch #:nodoc:
101
100
  end
102
101
 
103
102
  private
104
-
105
103
  def generate_content_security_policy_nonce
106
104
  content_security_policy_nonce_generator.call(self)
107
105
  end
@@ -56,7 +56,6 @@ module ActionDispatch
56
56
  end
57
57
 
58
58
  private
59
-
60
59
  def parameter_filter # :doc:
61
60
  parameter_filter_for fetch_header("action_dispatch.parameter_filter") {
62
61
  return NULL_PARAM_FILTER
@@ -14,7 +14,6 @@ module ActionDispatch
14
14
  end
15
15
 
16
16
  private
17
-
18
17
  def location_filters
19
18
  if request
20
19
  request.get_header("action_dispatch.redirect_filter") || []
@@ -116,7 +116,6 @@ module ActionDispatch
116
116
  def env; @req.env.dup; end
117
117
 
118
118
  private
119
-
120
119
  # Converts an HTTP header name to an environment variable name if it is
121
120
  # not contained within the headers hash.
122
121
  def env_name(key)
@@ -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};"
@@ -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
@@ -156,7 +156,6 @@ module ActionDispatch
156
156
  end
157
157
 
158
158
  private
159
-
160
159
  def polymorphic_url_for_action(action, record_or_hash, options)
161
160
  polymorphic_url(record_or_hash, options.merge(action: action))
162
161
  end
@@ -323,7 +322,6 @@ module ActionDispatch
323
322
  end
324
323
 
325
324
  private
326
-
327
325
  def polymorphic_mapping(target, record)
328
326
  if record.respond_to?(:to_model)
329
327
  target._routes.polymorphic_mappings[record.to_model.model_name.name]
@@ -40,7 +40,6 @@ module ActionDispatch
40
40
  end
41
41
 
42
42
  private
43
-
44
43
  def controller(req)
45
44
  req.controller_class
46
45
  rescue NameError => e
@@ -59,7 +58,6 @@ module ActionDispatch
59
58
  end
60
59
 
61
60
  private
62
-
63
61
  def controller(_); @controller_class; end
64
62
  end
65
63
 
@@ -215,7 +213,6 @@ module ActionDispatch
215
213
  end
216
214
 
217
215
  private
218
-
219
216
  def optimized_helper(args)
220
217
  params = parameterize_args(args) do
221
218
  raise_generation_error(args)
@@ -839,7 +836,7 @@ module ActionDispatch
839
836
 
840
837
  def recognize_path(path, environment = {})
841
838
  method = (environment[:method] || "GET").to_s.upcase
842
- path = Journey::Router::Utils.normalize_path(path) unless path =~ %r{://}
839
+ path = Journey::Router::Utils.normalize_path(path) unless %r{://}.match?(path)
843
840
  extras = environment[:extras] || {}
844
841
 
845
842
  begin
@@ -215,13 +215,11 @@ module ActionDispatch
215
215
  end
216
216
 
217
217
  protected
218
-
219
218
  def optimize_routes_generation?
220
219
  _routes.optimize_routes_generation? && default_url_options.empty?
221
220
  end
222
221
 
223
222
  private
224
-
225
223
  def _with_routes(routes) # :doc:
226
224
  old_routes, @_routes = @_routes, routes
227
225
  yield
@@ -118,6 +118,7 @@ module ActionDispatch
118
118
 
119
119
  def initialize(*) # :nodoc:
120
120
  super
121
+ self.class.driven_by(:selenium) unless self.class.driver?
121
122
  self.class.driver.use
122
123
  @proxy_route = if ActionDispatch.test_app
123
124
  Class.new do
@@ -166,11 +167,9 @@ module ActionDispatch
166
167
  def self.driven_by(driver, using: :chrome, screen_size: [1400, 1400], options: {}, &capabilities)
167
168
  driver_options = { using: using, screen_size: screen_size, options: options }
168
169
 
169
- self.driver = SystemTesting::Driver.new(driver, driver_options, &capabilities)
170
+ self.driver = SystemTesting::Driver.new(driver, **driver_options, &capabilities)
170
171
  end
171
172
 
172
- driven_by :selenium
173
-
174
173
  def method_missing(method, *args, &block)
175
174
  if @proxy_route.respond_to?(method)
176
175
  @proxy_route.send(method, *args, &block)
@@ -10,7 +10,7 @@ module ActionDispatch
10
10
  @options = options[:options]
11
11
  @capabilities = capabilities
12
12
 
13
- @browser.preload
13
+ @browser.preload unless name == :rack_test
14
14
  end
15
15
 
16
16
  def use
@@ -45,7 +45,7 @@ module ActionDispatch
45
45
  end
46
46
 
47
47
  def register_selenium(app)
48
- Capybara::Selenium::Driver.new(app, { browser: @browser.type }.merge(browser_options)).tap do |driver|
48
+ Capybara::Selenium::Driver.new(app, **{ browser: @browser.type }.merge(browser_options)).tap do |driver|
49
49
  driver.browser.manage.window.size = Selenium::WebDriver::Dimension.new(*@screen_size)
50
50
  end
51
51
  end
@@ -35,7 +35,6 @@ module ActionDispatch
35
35
  end
36
36
 
37
37
  private
38
-
39
38
  def code_from_name(name)
40
39
  GENERIC_RESPONSE_CODES[name] || Rack::Utils::SYMBOL_TO_STATUS_CODE[name]
41
40
  end
@@ -44,8 +44,8 @@ module ActionDispatch
44
44
 
45
45
  # Performs a HEAD request with the given parameters. See ActionDispatch::Integration::Session#process
46
46
  # for more details.
47
- def head(path, *args)
48
- process(:head, path, *args)
47
+ def head(path, **args)
48
+ process(:head, path, **args)
49
49
  end
50
50
 
51
51
  # Follow a single redirect response. If the last response was not a
@@ -310,6 +310,7 @@ module ActionDispatch
310
310
  APP_SESSIONS = {}
311
311
 
312
312
  attr_reader :app
313
+ attr_accessor :root_session # :nodoc:
313
314
 
314
315
  def initialize(*args, &blk)
315
316
  super(*args, &blk)
@@ -348,15 +349,19 @@ module ActionDispatch
348
349
  end
349
350
 
350
351
  %w(get post patch put head delete cookies assigns follow_redirect!).each do |method|
351
- define_method(method) do |*args|
352
+ define_method(method) do |*args, **options|
352
353
  # reset the html_document variable, except for cookies/assigns calls
353
354
  unless method == "cookies" || method == "assigns"
354
355
  @html_document = nil
355
356
  end
356
357
 
357
- integration_session.__send__(method, *args).tap do
358
- copy_session_variables!
358
+ result = if options.any?
359
+ integration_session.__send__(method, *args, **options)
360
+ else
361
+ integration_session.__send__(method, *args)
359
362
  end
363
+ copy_session_variables!
364
+ result
360
365
  end
361
366
  end
362
367
 
@@ -373,10 +378,19 @@ module ActionDispatch
373
378
  def open_session
374
379
  dup.tap do |session|
375
380
  session.reset!
381
+ session.root_session = self.root_session || self
376
382
  yield session if block_given?
377
383
  end
378
384
  end
379
385
 
386
+ def assertions # :nodoc:
387
+ root_session ? root_session.assertions : super
388
+ end
389
+
390
+ def assertions=(assertions) # :nodoc:
391
+ root_session ? root_session.assertions = assertions : super
392
+ end
393
+
380
394
  # Copy the instance variables from the current session instance into the
381
395
  # test instance.
382
396
  def copy_session_variables! #:nodoc:
@@ -408,6 +422,7 @@ module ActionDispatch
408
422
  super
409
423
  end
410
424
  end
425
+ ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
411
426
  end
412
427
  end
413
428
 
@@ -640,8 +655,8 @@ module ActionDispatch
640
655
  @@app = app
641
656
  end
642
657
 
643
- def register_encoder(*args)
644
- RequestEncoder.register_encoder(*args)
658
+ def register_encoder(*args, **options)
659
+ RequestEncoder.register_encoder(*args, **options)
645
660
  end
646
661
  end
647
662
 
@@ -9,8 +9,8 @@ module ActionPack
9
9
  module VERSION
10
10
  MAJOR = 6
11
11
  MINOR = 0
12
- TINY = 2
13
- PRE = "2"
12
+ TINY = 3
13
+ PRE = "rc1"
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: actionpack
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.0.2.2
4
+ version: 6.0.3.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-03-19 00:00:00.000000000 Z
11
+ date: 2020-05-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 6.0.2.2
19
+ version: 6.0.3.rc1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 6.0.2.2
26
+ version: 6.0.3.rc1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rack
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -98,28 +98,28 @@ dependencies:
98
98
  requirements:
99
99
  - - '='
100
100
  - !ruby/object:Gem::Version
101
- version: 6.0.2.2
101
+ version: 6.0.3.rc1
102
102
  type: :runtime
103
103
  prerelease: false
104
104
  version_requirements: !ruby/object:Gem::Requirement
105
105
  requirements:
106
106
  - - '='
107
107
  - !ruby/object:Gem::Version
108
- version: 6.0.2.2
108
+ version: 6.0.3.rc1
109
109
  - !ruby/object:Gem::Dependency
110
110
  name: activemodel
111
111
  requirement: !ruby/object:Gem::Requirement
112
112
  requirements:
113
113
  - - '='
114
114
  - !ruby/object:Gem::Version
115
- version: 6.0.2.2
115
+ version: 6.0.3.rc1
116
116
  type: :development
117
117
  prerelease: false
118
118
  version_requirements: !ruby/object:Gem::Requirement
119
119
  requirements:
120
120
  - - '='
121
121
  - !ruby/object:Gem::Version
122
- version: 6.0.2.2
122
+ version: 6.0.3.rc1
123
123
  description: Web apps on Rails. Simple, battle-tested conventions for building and
124
124
  testing MVC web applications. Works with any Rack-compatible server.
125
125
  email: david@loudthinking.com
@@ -310,10 +310,10 @@ licenses:
310
310
  - MIT
311
311
  metadata:
312
312
  bug_tracker_uri: https://github.com/rails/rails/issues
313
- changelog_uri: https://github.com/rails/rails/blob/v6.0.2.2/actionpack/CHANGELOG.md
314
- documentation_uri: https://api.rubyonrails.org/v6.0.2.2/
315
- mailing_list_uri: https://groups.google.com/forum/#!forum/rubyonrails-talk
316
- source_code_uri: https://github.com/rails/rails/tree/v6.0.2.2/actionpack
313
+ changelog_uri: https://github.com/rails/rails/blob/v6.0.3.rc1/actionpack/CHANGELOG.md
314
+ documentation_uri: https://api.rubyonrails.org/v6.0.3.rc1/
315
+ mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
316
+ source_code_uri: https://github.com/rails/rails/tree/v6.0.3.rc1/actionpack
317
317
  post_install_message:
318
318
  rdoc_options: []
319
319
  require_paths:
@@ -325,12 +325,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
325
325
  version: 2.5.0
326
326
  required_rubygems_version: !ruby/object:Gem::Requirement
327
327
  requirements:
328
- - - ">="
328
+ - - ">"
329
329
  - !ruby/object:Gem::Version
330
- version: '0'
330
+ version: 1.3.1
331
331
  requirements:
332
332
  - none
333
- rubygems_version: 3.0.3
333
+ rubygems_version: 3.1.2
334
334
  signing_key:
335
335
  specification_version: 4
336
336
  summary: Web-flow and rendering framework putting the VC in MVC (part of Rails).