actionpack 7.0.8.1 → 7.2.2.1

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 (171) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +94 -500
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +2 -2
  5. data/lib/abstract_controller/asset_paths.rb +2 -0
  6. data/lib/abstract_controller/base.rb +119 -106
  7. data/lib/abstract_controller/caching/fragments.rb +51 -52
  8. data/lib/abstract_controller/caching.rb +2 -0
  9. data/lib/abstract_controller/callbacks.rb +94 -67
  10. data/lib/abstract_controller/collector.rb +6 -6
  11. data/lib/abstract_controller/deprecator.rb +9 -0
  12. data/lib/abstract_controller/error.rb +2 -0
  13. data/lib/abstract_controller/helpers.rb +121 -91
  14. data/lib/abstract_controller/logger.rb +2 -0
  15. data/lib/abstract_controller/railties/routes_helpers.rb +3 -16
  16. data/lib/abstract_controller/rendering.rb +14 -13
  17. data/lib/abstract_controller/translation.rb +12 -30
  18. data/lib/abstract_controller/url_for.rb +9 -5
  19. data/lib/abstract_controller.rb +8 -0
  20. data/lib/action_controller/api/api_rendering.rb +2 -0
  21. data/lib/action_controller/api.rb +78 -73
  22. data/lib/action_controller/base.rb +199 -141
  23. data/lib/action_controller/caching.rb +16 -11
  24. data/lib/action_controller/deprecator.rb +9 -0
  25. data/lib/action_controller/form_builder.rb +21 -16
  26. data/lib/action_controller/log_subscriber.rb +19 -5
  27. data/lib/action_controller/metal/allow_browser.rb +123 -0
  28. data/lib/action_controller/metal/basic_implicit_render.rb +2 -0
  29. data/lib/action_controller/metal/conditional_get.rb +187 -174
  30. data/lib/action_controller/metal/content_security_policy.rb +26 -25
  31. data/lib/action_controller/metal/cookies.rb +4 -2
  32. data/lib/action_controller/metal/data_streaming.rb +65 -54
  33. data/lib/action_controller/metal/default_headers.rb +6 -2
  34. data/lib/action_controller/metal/etag_with_flash.rb +4 -0
  35. data/lib/action_controller/metal/etag_with_template_digest.rb +18 -14
  36. data/lib/action_controller/metal/exceptions.rb +19 -9
  37. data/lib/action_controller/metal/flash.rb +12 -10
  38. data/lib/action_controller/metal/head.rb +20 -16
  39. data/lib/action_controller/metal/helpers.rb +64 -67
  40. data/lib/action_controller/metal/http_authentication.rb +214 -200
  41. data/lib/action_controller/metal/implicit_render.rb +21 -17
  42. data/lib/action_controller/metal/instrumentation.rb +22 -12
  43. data/lib/action_controller/metal/live.rb +125 -92
  44. data/lib/action_controller/metal/logging.rb +6 -4
  45. data/lib/action_controller/metal/mime_responds.rb +151 -142
  46. data/lib/action_controller/metal/parameter_encoding.rb +34 -32
  47. data/lib/action_controller/metal/params_wrapper.rb +58 -58
  48. data/lib/action_controller/metal/permissions_policy.rb +14 -13
  49. data/lib/action_controller/metal/rate_limiting.rb +62 -0
  50. data/lib/action_controller/metal/redirecting.rb +110 -84
  51. data/lib/action_controller/metal/renderers.rb +50 -49
  52. data/lib/action_controller/metal/rendering.rb +103 -82
  53. data/lib/action_controller/metal/request_forgery_protection.rb +279 -161
  54. data/lib/action_controller/metal/rescue.rb +12 -8
  55. data/lib/action_controller/metal/streaming.rb +174 -132
  56. data/lib/action_controller/metal/strong_parameters.rb +598 -473
  57. data/lib/action_controller/metal/testing.rb +2 -0
  58. data/lib/action_controller/metal/url_for.rb +23 -14
  59. data/lib/action_controller/metal.rb +145 -61
  60. data/lib/action_controller/railtie.rb +25 -9
  61. data/lib/action_controller/railties/helpers.rb +2 -0
  62. data/lib/action_controller/renderer.rb +105 -66
  63. data/lib/action_controller/template_assertions.rb +4 -2
  64. data/lib/action_controller/test_case.rb +157 -128
  65. data/lib/action_controller.rb +17 -3
  66. data/lib/action_dispatch/constants.rb +34 -0
  67. data/lib/action_dispatch/deprecator.rb +9 -0
  68. data/lib/action_dispatch/http/cache.rb +28 -29
  69. data/lib/action_dispatch/http/content_disposition.rb +2 -0
  70. data/lib/action_dispatch/http/content_security_policy.rb +69 -49
  71. data/lib/action_dispatch/http/filter_parameters.rb +27 -12
  72. data/lib/action_dispatch/http/filter_redirect.rb +22 -1
  73. data/lib/action_dispatch/http/headers.rb +23 -21
  74. data/lib/action_dispatch/http/mime_negotiation.rb +37 -48
  75. data/lib/action_dispatch/http/mime_type.rb +60 -30
  76. data/lib/action_dispatch/http/mime_types.rb +5 -1
  77. data/lib/action_dispatch/http/parameters.rb +12 -10
  78. data/lib/action_dispatch/http/permissions_policy.rb +32 -34
  79. data/lib/action_dispatch/http/rack_cache.rb +4 -0
  80. data/lib/action_dispatch/http/request.rb +132 -79
  81. data/lib/action_dispatch/http/response.rb +136 -103
  82. data/lib/action_dispatch/http/upload.rb +19 -15
  83. data/lib/action_dispatch/http/url.rb +75 -73
  84. data/lib/action_dispatch/journey/formatter.rb +19 -6
  85. data/lib/action_dispatch/journey/gtg/builder.rb +4 -3
  86. data/lib/action_dispatch/journey/gtg/simulator.rb +2 -0
  87. data/lib/action_dispatch/journey/gtg/transition_table.rb +10 -8
  88. data/lib/action_dispatch/journey/nfa/dot.rb +2 -0
  89. data/lib/action_dispatch/journey/nodes/node.rb +6 -5
  90. data/lib/action_dispatch/journey/parser.rb +4 -3
  91. data/lib/action_dispatch/journey/parser_extras.rb +2 -0
  92. data/lib/action_dispatch/journey/path/pattern.rb +18 -15
  93. data/lib/action_dispatch/journey/route.rb +12 -9
  94. data/lib/action_dispatch/journey/router/utils.rb +16 -15
  95. data/lib/action_dispatch/journey/router.rb +13 -10
  96. data/lib/action_dispatch/journey/routes.rb +6 -4
  97. data/lib/action_dispatch/journey/scanner.rb +4 -2
  98. data/lib/action_dispatch/journey/visitors.rb +2 -0
  99. data/lib/action_dispatch/journey.rb +2 -0
  100. data/lib/action_dispatch/log_subscriber.rb +25 -0
  101. data/lib/action_dispatch/middleware/actionable_exceptions.rb +7 -6
  102. data/lib/action_dispatch/middleware/assume_ssl.rb +27 -0
  103. data/lib/action_dispatch/middleware/callbacks.rb +4 -0
  104. data/lib/action_dispatch/middleware/cookies.rb +192 -194
  105. data/lib/action_dispatch/middleware/debug_exceptions.rb +36 -27
  106. data/lib/action_dispatch/middleware/debug_locks.rb +18 -13
  107. data/lib/action_dispatch/middleware/debug_view.rb +9 -2
  108. data/lib/action_dispatch/middleware/exception_wrapper.rb +181 -27
  109. data/lib/action_dispatch/middleware/executor.rb +9 -1
  110. data/lib/action_dispatch/middleware/flash.rb +65 -46
  111. data/lib/action_dispatch/middleware/host_authorization.rb +22 -17
  112. data/lib/action_dispatch/middleware/public_exceptions.rb +12 -8
  113. data/lib/action_dispatch/middleware/reloader.rb +9 -5
  114. data/lib/action_dispatch/middleware/remote_ip.rb +88 -83
  115. data/lib/action_dispatch/middleware/request_id.rb +15 -8
  116. data/lib/action_dispatch/middleware/server_timing.rb +8 -6
  117. data/lib/action_dispatch/middleware/session/abstract_store.rb +7 -0
  118. data/lib/action_dispatch/middleware/session/cache_store.rb +14 -7
  119. data/lib/action_dispatch/middleware/session/cookie_store.rb +32 -25
  120. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +9 -3
  121. data/lib/action_dispatch/middleware/show_exceptions.rb +42 -28
  122. data/lib/action_dispatch/middleware/ssl.rb +60 -45
  123. data/lib/action_dispatch/middleware/stack.rb +15 -9
  124. data/lib/action_dispatch/middleware/static.rb +40 -34
  125. data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +2 -2
  126. data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +4 -4
  127. data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +8 -1
  128. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +7 -7
  129. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +2 -2
  130. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +17 -0
  131. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +16 -12
  132. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +1 -1
  133. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +3 -3
  134. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +4 -4
  135. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +1 -1
  136. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +1 -1
  137. data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +3 -0
  138. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +47 -38
  139. data/lib/action_dispatch/railtie.rb +12 -4
  140. data/lib/action_dispatch/request/session.rb +39 -27
  141. data/lib/action_dispatch/request/utils.rb +10 -3
  142. data/lib/action_dispatch/routing/endpoint.rb +2 -0
  143. data/lib/action_dispatch/routing/inspector.rb +59 -9
  144. data/lib/action_dispatch/routing/mapper.rb +686 -639
  145. data/lib/action_dispatch/routing/polymorphic_routes.rb +70 -61
  146. data/lib/action_dispatch/routing/redirection.rb +52 -38
  147. data/lib/action_dispatch/routing/route_set.rb +106 -62
  148. data/lib/action_dispatch/routing/routes_proxy.rb +16 -19
  149. data/lib/action_dispatch/routing/url_for.rb +131 -122
  150. data/lib/action_dispatch/routing.rb +152 -150
  151. data/lib/action_dispatch/system_test_case.rb +91 -81
  152. data/lib/action_dispatch/system_testing/browser.rb +27 -19
  153. data/lib/action_dispatch/system_testing/driver.rb +16 -22
  154. data/lib/action_dispatch/system_testing/server.rb +2 -0
  155. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +53 -31
  156. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +2 -0
  157. data/lib/action_dispatch/testing/assertion_response.rb +9 -7
  158. data/lib/action_dispatch/testing/assertions/response.rb +36 -26
  159. data/lib/action_dispatch/testing/assertions/routing.rb +203 -95
  160. data/lib/action_dispatch/testing/assertions.rb +5 -1
  161. data/lib/action_dispatch/testing/integration.rb +240 -229
  162. data/lib/action_dispatch/testing/request_encoder.rb +6 -1
  163. data/lib/action_dispatch/testing/test_helpers/page_dump_helper.rb +35 -0
  164. data/lib/action_dispatch/testing/test_process.rb +14 -9
  165. data/lib/action_dispatch/testing/test_request.rb +4 -2
  166. data/lib/action_dispatch/testing/test_response.rb +34 -19
  167. data/lib/action_dispatch.rb +52 -21
  168. data/lib/action_pack/gem_version.rb +5 -3
  169. data/lib/action_pack/version.rb +3 -1
  170. data/lib/action_pack.rb +18 -17
  171. metadata +91 -32
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "rack/session/abstract/id"
4
6
 
5
7
  module ActionDispatch
@@ -78,6 +80,8 @@ module ActionDispatch
78
80
  @loaded = false
79
81
  @exists = nil # We haven't checked yet.
80
82
  @enabled = enabled
83
+ @id_was = nil
84
+ @id_was_initialized = false
81
85
  end
82
86
 
83
87
  def id
@@ -105,8 +109,8 @@ module ActionDispatch
105
109
  end
106
110
  end
107
111
 
108
- # Returns value of the key stored in the session or
109
- # +nil+ if the given key is not found in the session.
112
+ # Returns value of the key stored in the session or `nil` if the given key is
113
+ # not found in the session.
110
114
  def [](key)
111
115
  load_for_read!
112
116
  key = key.to_s
@@ -118,8 +122,8 @@ module ActionDispatch
118
122
  end
119
123
  end
120
124
 
121
- # Returns the nested value specified by the sequence of keys, returning
122
- # +nil+ if any intermediate step is +nil+.
125
+ # Returns the nested value specified by the sequence of keys, returning `nil` if
126
+ # any intermediate step is `nil`.
123
127
  def dig(*keys)
124
128
  load_for_read!
125
129
  keys = keys.map.with_index { |key, i| i.zero? ? key.to_s : key }
@@ -167,18 +171,23 @@ module ActionDispatch
167
171
 
168
172
  # Updates the session with given Hash.
169
173
  #
170
- # session.to_hash
171
- # # => {"session_id"=>"e29b9ea315edf98aad94cc78c34cc9b2"}
174
+ # session.to_hash
175
+ # # => {"session_id"=>"e29b9ea315edf98aad94cc78c34cc9b2"}
172
176
  #
173
- # session.update({ "foo" => "bar" })
174
- # # => {"session_id"=>"e29b9ea315edf98aad94cc78c34cc9b2", "foo" => "bar"}
177
+ # session.update({ "foo" => "bar" })
178
+ # # => {"session_id"=>"e29b9ea315edf98aad94cc78c34cc9b2", "foo" => "bar"}
175
179
  #
176
- # session.to_hash
177
- # # => {"session_id"=>"e29b9ea315edf98aad94cc78c34cc9b2", "foo" => "bar"}
180
+ # session.to_hash
181
+ # # => {"session_id"=>"e29b9ea315edf98aad94cc78c34cc9b2", "foo" => "bar"}
178
182
  def update(hash)
183
+ unless hash.respond_to?(:to_hash)
184
+ raise TypeError, "no implicit conversion of #{hash.class.name} into Hash"
185
+ end
186
+
179
187
  load_for_write!
180
- @delegate.update hash.stringify_keys
188
+ @delegate.update hash.to_hash.stringify_keys
181
189
  end
190
+ alias :merge! :update
182
191
 
183
192
  # Deletes given key from the session.
184
193
  def delete(key)
@@ -186,20 +195,20 @@ module ActionDispatch
186
195
  @delegate.delete key.to_s
187
196
  end
188
197
 
189
- # Returns value of the given key from the session, or raises +KeyError+
190
- # if can't find the given key and no default value is set.
191
- # Returns default value if specified.
198
+ # Returns value of the given key from the session, or raises `KeyError` if can't
199
+ # find the given key and no default value is set. Returns default value if
200
+ # specified.
192
201
  #
193
- # session.fetch(:foo)
194
- # # => KeyError: key not found: "foo"
202
+ # session.fetch(:foo)
203
+ # # => KeyError: key not found: "foo"
195
204
  #
196
- # session.fetch(:foo, :bar)
197
- # # => :bar
205
+ # session.fetch(:foo, :bar)
206
+ # # => :bar
198
207
  #
199
- # session.fetch(:foo) do
200
- # :bar
201
- # end
202
- # # => :bar
208
+ # session.fetch(:foo) do
209
+ # :bar
210
+ # end
211
+ # # => :bar
203
212
  def fetch(key, default = Unspecified, &block)
204
213
  load_for_read!
205
214
  if default == Unspecified
@@ -232,15 +241,15 @@ module ActionDispatch
232
241
  @delegate.empty?
233
242
  end
234
243
 
235
- def merge!(other)
236
- load_for_write!
237
- @delegate.merge!(other)
238
- end
239
-
240
244
  def each(&block)
241
245
  to_hash.each(&block)
242
246
  end
243
247
 
248
+ def id_was
249
+ load_for_read!
250
+ @id_was
251
+ end
252
+
244
253
  private
245
254
  def load_for_read!
246
255
  load! if !loaded? && exists?
@@ -260,10 +269,13 @@ module ActionDispatch
260
269
 
261
270
  def load!
262
271
  if enabled?
272
+ @id_was_initialized = true unless exists?
263
273
  id, session = @by.load_session @req
264
274
  options[:id] = id
265
275
  @delegate.replace(session.stringify_keys)
276
+ @id_was = id unless @id_was_initialized
266
277
  end
278
+ @id_was_initialized = true
267
279
  @loaded = true
268
280
  end
269
281
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "active_support/core_ext/hash/indifferent_access"
4
6
 
5
7
  module ActionDispatch
@@ -55,9 +57,11 @@ module ActionDispatch
55
57
  if params.has_key?(:tempfile)
56
58
  ActionDispatch::Http::UploadedFile.new(params)
57
59
  else
58
- params.transform_values do |val|
59
- normalize_encode_params(val)
60
- end.with_indifferent_access
60
+ hwia = ActiveSupport::HashWithIndifferentAccess.new
61
+ params.each_pair do |key, val|
62
+ hwia[key] = normalize_encode_params(val)
63
+ end
64
+ hwia
61
65
  end
62
66
  else
63
67
  params
@@ -83,6 +87,9 @@ module ActionDispatch
83
87
  return params unless controller && controller.valid_encoding? && encoding_template = action_encoding_template(request, controller, action)
84
88
  params.except(:controller, :action).each do |key, value|
85
89
  ActionDispatch::Request::Utils.each_param_value(value) do |param|
90
+ # If `param` is frozen, it comes from the router defaults
91
+ next if param.frozen?
92
+
86
93
  if encoding_template[key.to_s]
87
94
  param.force_encoding(encoding_template[key.to_s])
88
95
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionDispatch
4
6
  module Routing
5
7
  class Endpoint # :nodoc:
@@ -1,13 +1,28 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "delegate"
4
6
  require "io/console/size"
5
7
 
6
8
  module ActionDispatch
7
9
  module Routing
8
10
  class RouteWrapper < SimpleDelegator # :nodoc:
11
+ def matches_filter?(filter, value)
12
+ return __getobj__.path.match(value) if filter == :exact_path_match
13
+
14
+ value.match?(public_send(filter))
15
+ end
16
+
9
17
  def endpoint
10
- app.dispatcher? ? "#{controller}##{action}" : rack_app.inspect
18
+ case
19
+ when app.dispatcher?
20
+ "#{controller}##{action}"
21
+ when rack_app.is_a?(Proc)
22
+ "Inline handler (Proc/Lambda)"
23
+ else
24
+ rack_app.inspect
25
+ end
11
26
  end
12
27
 
13
28
  def constraints
@@ -53,8 +68,8 @@ module ActionDispatch
53
68
 
54
69
  ##
55
70
  # This class is just used for displaying route information when someone
56
- # executes `bin/rails routes` or looks at the RoutingError page.
57
- # People should not use this class.
71
+ # executes `bin/rails routes` or looks at the RoutingError page. People should
72
+ # not use this class.
58
73
  class RoutesInspector # :nodoc:
59
74
  def initialize(routes)
60
75
  @engines = {}
@@ -85,8 +100,18 @@ module ActionDispatch
85
100
  if filter[:controller]
86
101
  { controller: /#{filter[:controller].underscore.sub(/_?controller\z/, "")}/ }
87
102
  elsif filter[:grep]
88
- { controller: /#{filter[:grep]}/, action: /#{filter[:grep]}/,
89
- verb: /#{filter[:grep]}/, name: /#{filter[:grep]}/, path: /#{filter[:grep]}/ }
103
+ grep_pattern = Regexp.new(filter[:grep])
104
+ path = RFC2396_PARSER.escape(filter[:grep])
105
+ normalized_path = ("/" + path).squeeze("/")
106
+
107
+ {
108
+ controller: grep_pattern,
109
+ action: grep_pattern,
110
+ verb: grep_pattern,
111
+ name: grep_pattern,
112
+ path: grep_pattern,
113
+ exact_path_match: normalized_path,
114
+ }
90
115
  end
91
116
  end
92
117
 
@@ -94,7 +119,7 @@ module ActionDispatch
94
119
  if filter
95
120
  @routes.select do |route|
96
121
  route_wrapper = RouteWrapper.new(route)
97
- filter.any? { |default, value| value.match?(route_wrapper.send(default)) }
122
+ filter.any? { |filter_type, value| route_wrapper.matches_filter?(filter_type, value) }
98
123
  end
99
124
  else
100
125
  @routes
@@ -110,7 +135,8 @@ module ActionDispatch
110
135
  { name: route.name,
111
136
  verb: route.verb,
112
137
  path: route.path,
113
- reqs: route.reqs }
138
+ reqs: route.reqs,
139
+ source_location: route.source_location }
114
140
  end
115
141
  end
116
142
 
@@ -216,13 +242,16 @@ module ActionDispatch
216
242
  private
217
243
  def draw_expanded_section(routes)
218
244
  routes.map.each_with_index do |r, i|
219
- <<~MESSAGE.chomp
245
+ route_rows = <<~MESSAGE.chomp
220
246
  #{route_header(index: i + 1)}
221
247
  Prefix | #{r[:name]}
222
248
  Verb | #{r[:verb]}
223
249
  URI | #{r[:path]}
224
250
  Controller#Action | #{r[:reqs]}
225
251
  MESSAGE
252
+ source_location = "\nSource Location | #{r[:source_location]}"
253
+ route_rows += source_location if r[:source_location].present?
254
+ route_rows
226
255
  end
227
256
  end
228
257
 
@@ -230,6 +259,27 @@ module ActionDispatch
230
259
  "--[ Route #{index} ]".ljust(@width, "-")
231
260
  end
232
261
  end
262
+
263
+ class Unused < Sheet
264
+ def header(routes)
265
+ @buffer << <<~MSG
266
+ Found #{routes.count} unused #{"route".pluralize(routes.count)}:
267
+ MSG
268
+
269
+ super
270
+ end
271
+
272
+ def no_routes(routes, filter)
273
+ @buffer <<
274
+ if filter.none?
275
+ "No unused routes found."
276
+ elsif filter.key?(:controller)
277
+ "No unused routes found for this controller."
278
+ elsif filter.key?(:grep)
279
+ "No unused routes found for this grep pattern."
280
+ end
281
+ end
282
+ end
233
283
  end
234
284
 
235
285
  class HtmlTableFormatter
@@ -239,7 +289,7 @@ module ActionDispatch
239
289
  end
240
290
 
241
291
  def section_title(title)
242
- @buffer << %(<tr><th colspan="4">#{title}</th></tr>)
292
+ @buffer << %(<tr><th colspan="5">#{title}</th></tr>)
243
293
  end
244
294
 
245
295
  def section(routes)