actionpack 6.1.7.6 → 7.0.0.alpha1

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 (107) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +99 -584
  3. data/MIT-LICENSE +2 -1
  4. data/README.rdoc +2 -3
  5. data/lib/abstract_controller/asset_paths.rb +1 -1
  6. data/lib/abstract_controller/base.rb +7 -21
  7. data/lib/abstract_controller/caching/fragments.rb +2 -2
  8. data/lib/abstract_controller/caching.rb +1 -1
  9. data/lib/abstract_controller/callbacks.rb +9 -8
  10. data/lib/abstract_controller/collector.rb +2 -2
  11. data/lib/abstract_controller/error.rb +1 -1
  12. data/lib/abstract_controller/helpers.rb +3 -2
  13. data/lib/abstract_controller/logger.rb +1 -1
  14. data/lib/abstract_controller/railties/routes_helpers.rb +2 -0
  15. data/lib/abstract_controller/translation.rb +0 -2
  16. data/lib/abstract_controller/url_for.rb +4 -6
  17. data/lib/action_controller/api.rb +1 -1
  18. data/lib/action_controller/log_subscriber.rb +3 -1
  19. data/lib/action_controller/metal/conditional_get.rb +38 -1
  20. data/lib/action_controller/metal/content_security_policy.rb +1 -1
  21. data/lib/action_controller/metal/cookies.rb +1 -1
  22. data/lib/action_controller/metal/data_streaming.rb +5 -13
  23. data/lib/action_controller/metal/exceptions.rb +19 -30
  24. data/lib/action_controller/metal/flash.rb +6 -2
  25. data/lib/action_controller/metal/http_authentication.rb +15 -16
  26. data/lib/action_controller/metal/instrumentation.rb +55 -52
  27. data/lib/action_controller/metal/live.rb +42 -2
  28. data/lib/action_controller/metal/mime_responds.rb +3 -3
  29. data/lib/action_controller/metal/params_wrapper.rb +7 -7
  30. data/lib/action_controller/metal/permissions_policy.rb +1 -1
  31. data/lib/action_controller/metal/query_tags.rb +16 -0
  32. data/lib/action_controller/metal/redirecting.rb +49 -34
  33. data/lib/action_controller/metal/rendering.rb +9 -9
  34. data/lib/action_controller/metal/request_forgery_protection.rb +64 -20
  35. data/lib/action_controller/metal/rescue.rb +1 -1
  36. data/lib/action_controller/metal/streaming.rb +1 -3
  37. data/lib/action_controller/metal/strong_parameters.rb +25 -29
  38. data/lib/action_controller/metal/testing.rb +0 -2
  39. data/lib/action_controller/metal.rb +7 -10
  40. data/lib/action_controller/railtie.rb +42 -5
  41. data/lib/action_controller/test_case.rb +6 -2
  42. data/lib/action_controller.rb +2 -5
  43. data/lib/action_dispatch/http/cache.rb +14 -7
  44. data/lib/action_dispatch/http/content_security_policy.rb +47 -37
  45. data/lib/action_dispatch/http/filter_parameters.rb +5 -0
  46. data/lib/action_dispatch/http/mime_negotiation.rb +13 -3
  47. data/lib/action_dispatch/http/mime_type.rb +9 -11
  48. data/lib/action_dispatch/http/parameters.rb +4 -4
  49. data/lib/action_dispatch/http/permissions_policy.rb +1 -1
  50. data/lib/action_dispatch/http/request.rb +10 -19
  51. data/lib/action_dispatch/http/response.rb +3 -3
  52. data/lib/action_dispatch/http/url.rb +9 -10
  53. data/lib/action_dispatch/journey/gtg/builder.rb +11 -12
  54. data/lib/action_dispatch/journey/gtg/simulator.rb +10 -4
  55. data/lib/action_dispatch/journey/gtg/transition_table.rb +77 -21
  56. data/lib/action_dispatch/journey/nodes/node.rb +70 -5
  57. data/lib/action_dispatch/journey/path/pattern.rb +22 -13
  58. data/lib/action_dispatch/journey/route.rb +5 -12
  59. data/lib/action_dispatch/journey/router/utils.rb +2 -2
  60. data/lib/action_dispatch/journey/router.rb +1 -1
  61. data/lib/action_dispatch/journey/routes.rb +3 -3
  62. data/lib/action_dispatch/journey/visualizer/fsm.js +49 -24
  63. data/lib/action_dispatch/journey/visualizer/index.html.erb +1 -1
  64. data/lib/action_dispatch/middleware/actionable_exceptions.rb +0 -1
  65. data/lib/action_dispatch/middleware/cookies.rb +27 -31
  66. data/lib/action_dispatch/middleware/debug_exceptions.rb +6 -4
  67. data/lib/action_dispatch/middleware/debug_locks.rb +3 -3
  68. data/lib/action_dispatch/middleware/exception_wrapper.rb +4 -0
  69. data/lib/action_dispatch/middleware/executor.rb +1 -1
  70. data/lib/action_dispatch/middleware/flash.rb +9 -11
  71. data/lib/action_dispatch/middleware/host_authorization.rb +25 -73
  72. data/lib/action_dispatch/middleware/remote_ip.rb +16 -4
  73. data/lib/action_dispatch/middleware/session/abstract_store.rb +1 -1
  74. data/lib/action_dispatch/middleware/show_exceptions.rb +6 -18
  75. data/lib/action_dispatch/middleware/stack.rb +50 -9
  76. data/lib/action_dispatch/middleware/static.rb +2 -5
  77. data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +1 -1
  78. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +4 -11
  79. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +2 -2
  80. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +2 -2
  81. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +4 -4
  82. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +3 -3
  83. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +28 -18
  84. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +3 -3
  85. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +3 -3
  86. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +3 -3
  87. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +3 -3
  88. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +3 -3
  89. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +5 -14
  90. data/lib/action_dispatch/railtie.rb +8 -2
  91. data/lib/action_dispatch/request/session.rb +43 -13
  92. data/lib/action_dispatch/routing/mapper.rb +44 -72
  93. data/lib/action_dispatch/routing/redirection.rb +0 -2
  94. data/lib/action_dispatch/routing/route_set.rb +7 -4
  95. data/lib/action_dispatch/routing/routes_proxy.rb +1 -1
  96. data/lib/action_dispatch/routing/url_for.rb +1 -2
  97. data/lib/action_dispatch/routing.rb +2 -2
  98. data/lib/action_dispatch/system_test_case.rb +6 -12
  99. data/lib/action_dispatch/system_testing/driver.rb +24 -4
  100. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +10 -6
  101. data/lib/action_dispatch/testing/assertions.rb +2 -5
  102. data/lib/action_dispatch/testing/integration.rb +6 -8
  103. data/lib/action_dispatch/testing/test_process.rb +2 -2
  104. data/lib/action_dispatch.rb +1 -1
  105. data/lib/action_pack/gem_version.rb +4 -4
  106. data/lib/action_pack.rb +1 -1
  107. metadata +21 -21
@@ -27,28 +27,13 @@ module ActionController
27
27
  super("param is missing or the value is empty: #{param}")
28
28
  end
29
29
 
30
- class Correction
31
- def initialize(error)
32
- @error = error
33
- end
34
-
35
- def corrections
36
- if @error.param && @error.keys
37
- maybe_these = @error.keys
30
+ if defined?(DidYouMean::Correctable) && defined?(DidYouMean::SpellChecker)
31
+ include DidYouMean::Correctable # :nodoc:
38
32
 
39
- maybe_these.sort_by { |n|
40
- DidYouMean::Jaro.distance(@error.param.to_s, n)
41
- }.reverse.first(4)
42
- else
43
- []
44
- end
33
+ def corrections # :nodoc:
34
+ @corrections ||= DidYouMean::SpellChecker.new(dictionary: keys).correct(param.to_s)
45
35
  end
46
36
  end
47
-
48
- # We may not have DYM, and DYM might not let us register error handlers
49
- if defined?(DidYouMean) && DidYouMean.respond_to?(:correct_error)
50
- DidYouMean.correct_error(self, Correction)
51
- end
52
37
  end
53
38
 
54
39
  # Raised when a supplied parameter is not expected and
@@ -106,11 +91,13 @@ module ActionController
106
91
  #
107
92
  # * +permit_all_parameters+ - If it's +true+, all the parameters will be
108
93
  # permitted by default. The default is +false+.
109
- # * +action_on_unpermitted_parameters+ - Allow to control the behavior when parameters
110
- # that are not explicitly permitted are found. The values can be +false+ to just filter them
111
- # out, <tt>:log</tt> to additionally write a message on the logger, or <tt>:raise</tt> to raise
112
- # ActionController::UnpermittedParameters exception. The default value is <tt>:log</tt>
113
- # in test and development environments, +false+ otherwise.
94
+ # * +action_on_unpermitted_parameters+ - Controls behavior when parameters that are not explicitly
95
+ # permitted are found. The default value is <tt>:log</tt> in test and development environments,
96
+ # +false+ otherwise. The values can be:
97
+ # * +false+ to take no action.
98
+ # * <tt>:log</tt> to emit an <tt>ActiveSupport::Notifications.instrument</tt> event on the
99
+ # <tt>unpermitted_parameters.action_controller</tt> topic and log at the DEBUG level.
100
+ # * <tt>:raise</tt> to raise a <tt>ActionController::UnpermittedParameters</tt> exception.
114
101
  #
115
102
  # Examples:
116
103
  #
@@ -277,8 +264,9 @@ module ActionController
277
264
  # params = ActionController::Parameters.new(name: "Francesco")
278
265
  # params.permitted? # => true
279
266
  # Person.new(params) # => #<Person id: nil, name: "Francesco">
280
- def initialize(parameters = {})
267
+ def initialize(parameters = {}, logging_context = {})
281
268
  @parameters = parameters.with_indifferent_access
269
+ @logging_context = logging_context
282
270
  @permitted = self.class.permit_all_parameters
283
271
  end
284
272
 
@@ -940,7 +928,7 @@ module ActionController
940
928
  when Array
941
929
  return value if converted_arrays.member?(value)
942
930
  converted = value.map { |_| convert_value_to_parameters(_) }
943
- converted_arrays << converted.dup
931
+ converted_arrays << converted
944
932
  converted
945
933
  when Hash
946
934
  self.class.new(value)
@@ -952,7 +940,7 @@ module ActionController
952
940
  def each_element(object, &block)
953
941
  case object
954
942
  when Array
955
- object.grep(Parameters).map { |el| yield el }.compact
943
+ object.grep(Parameters).filter_map(&block)
956
944
  when Parameters
957
945
  if object.nested_attributes?
958
946
  object.each_nested_attribute(&block)
@@ -968,7 +956,7 @@ module ActionController
968
956
  case self.class.action_on_unpermitted_parameters
969
957
  when :log
970
958
  name = "unpermitted_parameters.action_controller"
971
- ActiveSupport::Notifications.instrument(name, keys: unpermitted_keys)
959
+ ActiveSupport::Notifications.instrument(name, keys: unpermitted_keys, context: @logging_context)
972
960
  when :raise
973
961
  raise ActionController::UnpermittedParameters.new(unpermitted_keys)
974
962
  end
@@ -1184,7 +1172,15 @@ module ActionController
1184
1172
  # Returns a new ActionController::Parameters object that
1185
1173
  # has been instantiated with the <tt>request.parameters</tt>.
1186
1174
  def params
1187
- @_params ||= Parameters.new(request.parameters)
1175
+ @_params ||= begin
1176
+ context = {
1177
+ controller: self.class.name,
1178
+ action: action_name,
1179
+ request: request,
1180
+ params: request.filtered_parameters
1181
+ }
1182
+ Parameters.new(request.parameters, context)
1183
+ end
1188
1184
  end
1189
1185
 
1190
1186
  # Assigns the given +value+ to the +params+ hash. If +value+
@@ -2,8 +2,6 @@
2
2
 
3
3
  module ActionController
4
4
  module Testing
5
- extend ActiveSupport::Concern
6
-
7
5
  # Behavior specific to functional tests
8
6
  module Functional # :nodoc:
9
7
  def recycle!
@@ -2,8 +2,6 @@
2
2
 
3
3
  require "active_support/core_ext/array/extract_options"
4
4
  require "action_dispatch/middleware/stack"
5
- require "action_dispatch/http/request"
6
- require "action_dispatch/http/response"
7
5
 
8
6
  module ActionController
9
7
  # Extend ActionDispatch middleware stack to make it aware of options
@@ -13,8 +11,8 @@ module ActionController
13
11
  # use AuthenticationMiddleware, except: [:index, :show]
14
12
  # end
15
13
  #
16
- class MiddlewareStack < ActionDispatch::MiddlewareStack #:nodoc:
17
- class Middleware < ActionDispatch::MiddlewareStack::Middleware #:nodoc:
14
+ class MiddlewareStack < ActionDispatch::MiddlewareStack # :nodoc:
15
+ class Middleware < ActionDispatch::MiddlewareStack::Middleware # :nodoc:
18
16
  def initialize(klass, args, actions, strategy, block)
19
17
  @actions = actions
20
18
  @strategy = strategy
@@ -184,7 +182,7 @@ module ActionController
184
182
  response_body || response.committed?
185
183
  end
186
184
 
187
- def dispatch(name, request, response) #:nodoc:
185
+ def dispatch(name, request, response) # :nodoc:
188
186
  set_request!(request)
189
187
  set_response!(response)
190
188
  process(name)
@@ -196,12 +194,12 @@ module ActionController
196
194
  @_response = response
197
195
  end
198
196
 
199
- def set_request!(request) #:nodoc:
197
+ def set_request!(request) # :nodoc:
200
198
  @_request = request
201
199
  @_request.controller_instance = self
202
200
  end
203
201
 
204
- def to_a #:nodoc:
202
+ def to_a # :nodoc:
205
203
  response.to_a
206
204
  end
207
205
 
@@ -219,10 +217,9 @@ module ActionController
219
217
  class << self
220
218
  # Pushes the given Rack middleware and its arguments to the bottom of the
221
219
  # middleware stack.
222
- def use(*args, &block)
223
- middleware_stack.use(*args, &block)
220
+ def use(...)
221
+ middleware_stack.use(...)
224
222
  end
225
- ruby2_keywords(:use) if respond_to?(:ruby2_keywords, true)
226
223
  end
227
224
 
228
225
  # Alias for +middleware_stack+.
@@ -8,8 +8,10 @@ require "action_controller/railties/helpers"
8
8
  require "action_view/railtie"
9
9
 
10
10
  module ActionController
11
- class Railtie < Rails::Railtie #:nodoc:
11
+ class Railtie < Rails::Railtie # :nodoc:
12
12
  config.action_controller = ActiveSupport::OrderedOptions.new
13
+ config.action_controller.raise_on_open_redirects = false
14
+ config.action_controller.log_query_tags_around_actions = true
13
15
 
14
16
  config.eager_load_namespaces << ActionController
15
17
 
@@ -25,14 +27,19 @@ module ActionController
25
27
  options = app.config.action_controller
26
28
 
27
29
  ActiveSupport.on_load(:action_controller, run_once: true) do
28
- ActionController::Parameters.permit_all_parameters = options.delete(:permit_all_parameters) { false }
30
+ ActionController::Parameters.permit_all_parameters = options.permit_all_parameters || false
29
31
  if app.config.action_controller[:always_permitted_parameters]
30
32
  ActionController::Parameters.always_permitted_parameters =
31
- app.config.action_controller.delete(:always_permitted_parameters)
33
+ app.config.action_controller.always_permitted_parameters
32
34
  end
33
- ActionController::Parameters.action_on_unpermitted_parameters = options.delete(:action_on_unpermitted_parameters) do
34
- (Rails.env.test? || Rails.env.development?) ? :log : false
35
+
36
+ action_on_unpermitted_parameters = options.action_on_unpermitted_parameters
37
+
38
+ if action_on_unpermitted_parameters.nil?
39
+ action_on_unpermitted_parameters = (Rails.env.test? || Rails.env.development?) ? :log : false
35
40
  end
41
+
42
+ ActionController::Parameters.action_on_unpermitted_parameters = action_on_unpermitted_parameters
36
43
  end
37
44
  end
38
45
 
@@ -55,6 +62,14 @@ module ActionController
55
62
  extend ::AbstractController::Railties::RoutesHelpers.with(app.routes)
56
63
  extend ::ActionController::Railties::Helpers
57
64
 
65
+ # Configs used in other initializers
66
+ options = options.except(
67
+ :log_query_tags_around_actions,
68
+ :permit_all_parameters,
69
+ :action_on_unpermitted_parameters,
70
+ :always_permitted_parameters
71
+ )
72
+
58
73
  options.each do |k, v|
59
74
  k = "#{k}="
60
75
  if respond_to?(k)
@@ -85,5 +100,27 @@ module ActionController
85
100
  ActionController::Metal.descendants.each(&:action_methods) if config.eager_load
86
101
  end
87
102
  end
103
+
104
+ initializer "action_controller.query_log_tags" do |app|
105
+ query_logs_tags_enabled = app.config.respond_to?(:active_record) &&
106
+ app.config.active_record.query_log_tags_enabled &&
107
+ app.config.action_controller.log_query_tags_around_actions
108
+
109
+ if query_logs_tags_enabled
110
+ app.config.active_record.query_log_tags += [:controller, :action]
111
+
112
+ ActiveSupport.on_load(:action_controller) do
113
+ include ActionController::QueryTags
114
+ end
115
+
116
+ ActiveSupport.on_load(:active_record) do
117
+ ActiveRecord::QueryLogs.taggings.merge!(
118
+ controller: ->(context) { context[:controller].controller_name },
119
+ action: ->(context) { context[:controller].action_name },
120
+ namespaced_controller: ->(context) { context[:controller].class.name }
121
+ )
122
+ end
123
+ end
124
+ end
88
125
  end
89
126
  end
@@ -31,7 +31,7 @@ module ActionController
31
31
 
32
32
  # ActionController::TestCase will be deprecated and moved to a gem in the future.
33
33
  # Please use ActionDispatch::IntegrationTest going forward.
34
- class TestRequest < ActionDispatch::TestRequest #:nodoc:
34
+ class TestRequest < ActionDispatch::TestRequest # :nodoc:
35
35
  DEFAULT_ENV = ActionDispatch::TestRequest::DEFAULT_ENV.dup
36
36
  DEFAULT_ENV.delete "PATH_INFO"
37
37
 
@@ -179,7 +179,7 @@ module ActionController
179
179
 
180
180
  # Methods #destroy and #load! are overridden to avoid calling methods on the
181
181
  # @store object, which does not exist for the TestSession class.
182
- class TestSession < Rack::Session::Abstract::PersistedSecure::SecureSessionHash #:nodoc:
182
+ class TestSession < Rack::Session::Abstract::PersistedSecure::SecureSessionHash # :nodoc:
183
183
  DEFAULT_OPTIONS = Rack::Session::Abstract::Persisted::DEFAULT_OPTIONS
184
184
 
185
185
  def initialize(session = {})
@@ -214,6 +214,10 @@ module ActionController
214
214
  @data.fetch(key.to_s, *args, &block)
215
215
  end
216
216
 
217
+ def enabled?
218
+ true
219
+ end
220
+
217
221
  private
218
222
  def load!
219
223
  @id
@@ -18,10 +18,6 @@ module ActionController
18
18
  end
19
19
 
20
20
  autoload_under "metal" do
21
- eager_autoload do
22
- autoload :Live
23
- end
24
-
25
21
  autoload :ConditionalGet
26
22
  autoload :ContentSecurityPolicy
27
23
  autoload :Cookies
@@ -37,9 +33,11 @@ module ActionController
37
33
  autoload :BasicImplicitRender
38
34
  autoload :ImplicitRender
39
35
  autoload :Instrumentation
36
+ autoload :Live
40
37
  autoload :Logging
41
38
  autoload :MimeResponds
42
39
  autoload :ParamsWrapper
40
+ autoload :QueryTags
43
41
  autoload :Redirecting
44
42
  autoload :Renderers
45
43
  autoload :Rendering
@@ -65,5 +63,4 @@ require "active_support/core_ext/module/attribute_accessors"
65
63
  require "active_support/core_ext/load_error"
66
64
  require "active_support/core_ext/module/attr_internal"
67
65
  require "active_support/core_ext/name_error"
68
- require "active_support/core_ext/uri"
69
66
  require "active_support/inflector"
@@ -18,7 +18,7 @@ module ActionDispatch
18
18
  end
19
19
 
20
20
  def if_none_match_etags
21
- if_none_match ? if_none_match.split(",").each(&:strip!) : []
21
+ if_none_match ? if_none_match.split(/\s*,\s*/) : []
22
22
  end
23
23
 
24
24
  def not_modified?(modified_at)
@@ -187,13 +187,20 @@ module ActionDispatch
187
187
 
188
188
  return if control.empty? && cache_control.empty? # Let middleware handle default behavior
189
189
 
190
- if extras = control.delete(:extras)
191
- cache_control[:extras] ||= []
192
- cache_control[:extras] += extras
193
- cache_control[:extras].uniq!
194
- end
190
+ if cache_control.any?
191
+ # Any caching directive coming from a controller overrides
192
+ # no-cache/no-store in the default Cache-Control header.
193
+ control.delete(:no_cache)
194
+ control.delete(:no_store)
195
195
 
196
- control.merge! cache_control
196
+ if extras = control.delete(:extras)
197
+ cache_control[:extras] ||= []
198
+ cache_control[:extras] += extras
199
+ cache_control[:extras].uniq!
200
+ end
201
+
202
+ control.merge! cache_control
203
+ end
197
204
 
198
205
  options = []
199
206
 
@@ -1,9 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/core_ext/object/deep_dup"
4
- require "active_support/core_ext/array/wrap"
5
4
 
6
- module ActionDispatch #:nodoc:
5
+ module ActionDispatch # :nodoc:
7
6
  class ContentSecurityPolicy
8
7
  class Middleware
9
8
  CONTENT_TYPE = "Content-Type"
@@ -18,6 +17,7 @@ module ActionDispatch #:nodoc:
18
17
  request = ActionDispatch::Request.new env
19
18
  _, headers, _ = response = @app.call(env)
20
19
 
20
+ return response unless html_response?(headers)
21
21
  return response if policy_present?(headers)
22
22
 
23
23
  if policy = request.content_security_policy
@@ -31,6 +31,12 @@ module ActionDispatch #:nodoc:
31
31
  end
32
32
 
33
33
  private
34
+ def html_response?(headers)
35
+ if content_type = headers[CONTENT_TYPE]
36
+ /html/.match?(content_type)
37
+ end
38
+ end
39
+
34
40
  def header_name(request)
35
41
  if request.content_security_policy_report_only
36
42
  POLICY_REPORT_ONLY
@@ -100,43 +106,47 @@ module ActionDispatch #:nodoc:
100
106
  end
101
107
 
102
108
  MAPPINGS = {
103
- self: "'self'",
104
- unsafe_eval: "'unsafe-eval'",
105
- unsafe_inline: "'unsafe-inline'",
106
- none: "'none'",
107
- http: "http:",
108
- https: "https:",
109
- data: "data:",
110
- mediastream: "mediastream:",
111
- blob: "blob:",
112
- filesystem: "filesystem:",
113
- report_sample: "'report-sample'",
114
- strict_dynamic: "'strict-dynamic'",
115
- ws: "ws:",
116
- wss: "wss:"
109
+ self: "'self'",
110
+ unsafe_eval: "'unsafe-eval'",
111
+ unsafe_inline: "'unsafe-inline'",
112
+ none: "'none'",
113
+ http: "http:",
114
+ https: "https:",
115
+ data: "data:",
116
+ mediastream: "mediastream:",
117
+ allow_duplicates: "'allow-duplicates'",
118
+ blob: "blob:",
119
+ filesystem: "filesystem:",
120
+ report_sample: "'report-sample'",
121
+ script: "'script'",
122
+ strict_dynamic: "'strict-dynamic'",
123
+ ws: "ws:",
124
+ wss: "wss:"
117
125
  }.freeze
118
126
 
119
127
  DIRECTIVES = {
120
- base_uri: "base-uri",
121
- child_src: "child-src",
122
- connect_src: "connect-src",
123
- default_src: "default-src",
124
- font_src: "font-src",
125
- form_action: "form-action",
126
- frame_ancestors: "frame-ancestors",
127
- frame_src: "frame-src",
128
- img_src: "img-src",
129
- manifest_src: "manifest-src",
130
- media_src: "media-src",
131
- object_src: "object-src",
132
- prefetch_src: "prefetch-src",
133
- script_src: "script-src",
134
- script_src_attr: "script-src-attr",
135
- script_src_elem: "script-src-elem",
136
- style_src: "style-src",
137
- style_src_attr: "style-src-attr",
138
- style_src_elem: "style-src-elem",
139
- worker_src: "worker-src"
128
+ base_uri: "base-uri",
129
+ child_src: "child-src",
130
+ connect_src: "connect-src",
131
+ default_src: "default-src",
132
+ font_src: "font-src",
133
+ form_action: "form-action",
134
+ frame_ancestors: "frame-ancestors",
135
+ frame_src: "frame-src",
136
+ img_src: "img-src",
137
+ manifest_src: "manifest-src",
138
+ media_src: "media-src",
139
+ object_src: "object-src",
140
+ prefetch_src: "prefetch-src",
141
+ require_trusted_types_for: "require-trusted-types-for",
142
+ script_src: "script-src",
143
+ script_src_attr: "script-src-attr",
144
+ script_src_elem: "script-src-elem",
145
+ style_src: "style-src",
146
+ style_src_attr: "style-src-attr",
147
+ style_src_elem: "style-src-elem",
148
+ trusted_types: "trusted-types",
149
+ worker_src: "worker-src"
140
150
  }.freeze
141
151
 
142
152
  DEFAULT_NONCE_DIRECTIVES = %w[script-src style-src].freeze
@@ -266,7 +276,7 @@ module ActionDispatch #:nodoc:
266
276
  raise RuntimeError, "Missing context for the dynamic content security policy source: #{source.inspect}"
267
277
  else
268
278
  resolved = context.instance_exec(&source)
269
- apply_mappings(Array.wrap(resolved))
279
+ resolved.is_a?(Symbol) ? apply_mapping(resolved) : resolved
270
280
  end
271
281
  else
272
282
  raise RuntimeError, "Unexpected content security policy source: #{source.inspect}"
@@ -18,6 +18,11 @@ module ActionDispatch
18
18
  # env["action_dispatch.parameter_filter"] = [:foo, "bar"]
19
19
  # => replaces the value to all keys matching /foo|bar/i with "[FILTERED]"
20
20
  #
21
+ # env["action_dispatch.parameter_filter"] = [ /\Apin\z/i, /\Apin_/i ]
22
+ # => replaces the value for the exact (case-insensitive) key 'pin' and all
23
+ # (case-insensitive) keys beginning with 'pin_', with "[FILTERED]"
24
+ # Does not match keys with 'pin' as a substring, such as 'shipping_id'.
25
+ #
21
26
  # env["action_dispatch.parameter_filter"] = [ "credit_card.code" ]
22
27
  # => replaces { credit_card: {code: "xxxx"} } with "[FILTERED]", does not
23
28
  # change { file: { code: "xxxx"} }
@@ -16,12 +16,13 @@ module ActionDispatch
16
16
 
17
17
  included do
18
18
  mattr_accessor :ignore_accept_header, default: false
19
+ cattr_accessor :return_only_media_type_on_content_type, default: false
19
20
  end
20
21
 
21
22
  # The MIME type of the HTTP request, such as Mime[:xml].
22
23
  def content_mime_type
23
24
  fetch_header("action_dispatch.request.content_type") do |k|
24
- v = if get_header("CONTENT_TYPE") =~ /^([^,\;]*)/
25
+ v = if get_header("CONTENT_TYPE") =~ /^([^,;]*)/
25
26
  Mime::Type.lookup($1.strip.downcase)
26
27
  else
27
28
  nil
@@ -33,7 +34,16 @@ module ActionDispatch
33
34
  end
34
35
 
35
36
  def content_type
36
- content_mime_type && content_mime_type.to_s
37
+ if self.class.return_only_media_type_on_content_type
38
+ ActiveSupport::Deprecation.warn(
39
+ "Rails 7.1 will return Content-Type header without modification." \
40
+ " If you want just the MIME type, please use `#media_type` instead."
41
+ )
42
+
43
+ content_mime_type&.to_s
44
+ else
45
+ super
46
+ end
37
47
  end
38
48
 
39
49
  def has_content_type? # :nodoc:
@@ -92,7 +102,7 @@ module ActionDispatch
92
102
  def variant=(variant)
93
103
  variant = Array(variant)
94
104
 
95
- if variant.all? { |v| v.is_a?(Symbol) }
105
+ if variant.all?(Symbol)
96
106
  @variant = ActiveSupport::ArrayInquirer.new(variant)
97
107
  else
98
108
  raise ArgumentError, "request.variant must be set to a Symbol or an Array of Symbols."
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "singleton"
4
- require "active_support/core_ext/symbol/starts_ends_with"
5
4
 
6
5
  module Mime
7
6
  class Mimes
@@ -14,8 +13,8 @@ module Mime
14
13
  @symbols = []
15
14
  end
16
15
 
17
- def each
18
- @mimes.each { |x| yield x }
16
+ def each(&block)
17
+ @mimes.each(&block)
19
18
  end
20
19
 
21
20
  def <<(type)
@@ -43,9 +42,9 @@ module Mime
43
42
  Type.lookup_by_extension(type)
44
43
  end
45
44
 
46
- def fetch(type)
45
+ def fetch(type, &block)
47
46
  return type if type.is_a?(Type)
48
- EXTENSION_LOOKUP.fetch(type.to_s) { |k| yield k }
47
+ EXTENSION_LOOKUP.fetch(type.to_s, &block)
49
48
  end
50
49
  end
51
50
 
@@ -68,7 +67,7 @@ module Mime
68
67
  @register_callbacks = []
69
68
 
70
69
  # A simple helper class used in parsing the accept header.
71
- class AcceptItem #:nodoc:
70
+ class AcceptItem # :nodoc:
72
71
  attr_accessor :index, :name, :q
73
72
  alias :to_s :name
74
73
 
@@ -86,7 +85,7 @@ module Mime
86
85
  end
87
86
  end
88
87
 
89
- class AcceptList #:nodoc:
88
+ class AcceptList # :nodoc:
90
89
  def self.sort!(list)
91
90
  list.sort!
92
91
 
@@ -226,10 +225,9 @@ module Mime
226
225
  attr_reader :hash
227
226
 
228
227
  MIME_NAME = "[a-zA-Z0-9][a-zA-Z0-9#{Regexp.escape('!#$&-^_.+')}]{0,126}"
229
- MIME_PARAMETER_KEY = "[a-zA-Z0-9][a-zA-Z0-9#{Regexp.escape('!#$&-^_.+')}]{0,126}"
230
- MIME_PARAMETER_VALUE = "#{Regexp.escape('"')}?[a-zA-Z0-9][a-zA-Z0-9#{Regexp.escape('!#$&-^_.+')}]{0,126}#{Regexp.escape('"')}?"
231
- MIME_PARAMETER = "\s*\;\s*#{MIME_PARAMETER_KEY}(?:\=#{MIME_PARAMETER_VALUE})?"
232
- MIME_REGEXP = /\A(?:\*\/\*|#{MIME_NAME}\/(?:\*|#{MIME_NAME})(?>\s*#{MIME_PARAMETER}\s*)*)\z/
228
+ MIME_PARAMETER_VALUE = "#{Regexp.escape('"')}?#{MIME_NAME}#{Regexp.escape('"')}?"
229
+ MIME_PARAMETER = "\s*;\s*#{MIME_NAME}(?:=#{MIME_PARAMETER_VALUE})?"
230
+ MIME_REGEXP = /\A(?:\*\/\*|#{MIME_NAME}\/(?:\*|#{MIME_NAME})(?>#{MIME_PARAMETER})*\s*)\z/
233
231
 
234
232
  class InvalidMimeType < StandardError; end
235
233
 
@@ -17,8 +17,8 @@ module ActionDispatch
17
17
  # Raised when raw data from the request cannot be parsed by the parser
18
18
  # defined for request's content MIME type.
19
19
  class ParseError < StandardError
20
- def initialize
21
- super($!.message)
20
+ def initialize(message = $!.message)
21
+ super(message)
22
22
  end
23
23
  end
24
24
 
@@ -62,7 +62,7 @@ module ActionDispatch
62
62
  end
63
63
  alias :params :parameters
64
64
 
65
- def path_parameters=(parameters) #:nodoc:
65
+ def path_parameters=(parameters) # :nodoc:
66
66
  delete_header("action_dispatch.request.parameters")
67
67
 
68
68
  parameters = Request::Utils.set_binary_encoding(self, parameters, parameters[:controller], parameters[:action])
@@ -93,7 +93,7 @@ module ActionDispatch
93
93
  strategy.call(raw_post)
94
94
  rescue # JSON or Ruby code block errors.
95
95
  log_parse_error_once
96
- raise ParseError
96
+ raise ParseError, "Error occurred while parsing request parameters"
97
97
  end
98
98
  end
99
99
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  require "active_support/core_ext/object/deep_dup"
4
4
 
5
- module ActionDispatch #:nodoc:
5
+ module ActionDispatch # :nodoc:
6
6
  class PermissionsPolicy
7
7
  class Middleware
8
8
  CONTENT_TYPE = "Content-Type"