actionpack 6.0.0.beta3 → 6.0.2.rc2

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 (57) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +111 -3
  3. data/README.rdoc +2 -1
  4. data/lib/action_controller.rb +4 -1
  5. data/lib/action_controller/metal.rb +3 -3
  6. data/lib/action_controller/metal/exceptions.rb +1 -1
  7. data/lib/action_controller/metal/helpers.rb +1 -1
  8. data/lib/action_controller/metal/live.rb +1 -1
  9. data/lib/action_controller/metal/mime_responds.rb +1 -1
  10. data/lib/action_controller/metal/params_wrapper.rb +2 -2
  11. data/lib/action_controller/metal/renderers.rb +4 -4
  12. data/lib/action_controller/metal/rendering.rb +1 -1
  13. data/lib/action_controller/metal/request_forgery_protection.rb +2 -2
  14. data/lib/action_controller/metal/strong_parameters.rb +5 -11
  15. data/lib/action_controller/renderer.rb +2 -2
  16. data/lib/action_controller/template_assertions.rb +1 -1
  17. data/lib/action_controller/test_case.rb +3 -2
  18. data/lib/action_dispatch.rb +1 -1
  19. data/lib/action_dispatch/http/content_security_policy.rb +20 -9
  20. data/lib/action_dispatch/http/mime_type.rb +13 -1
  21. data/lib/action_dispatch/http/response.rb +27 -7
  22. data/lib/action_dispatch/journey/formatter.rb +1 -1
  23. data/lib/action_dispatch/journey/path/pattern.rb +6 -1
  24. data/lib/action_dispatch/journey/route.rb +5 -4
  25. data/lib/action_dispatch/journey/routes.rb +0 -1
  26. data/lib/action_dispatch/middleware/actionable_exceptions.rb +39 -0
  27. data/lib/action_dispatch/middleware/cookies.rb +7 -3
  28. data/lib/action_dispatch/middleware/debug_exceptions.rb +8 -2
  29. data/lib/action_dispatch/middleware/debug_view.rb +12 -0
  30. data/lib/action_dispatch/middleware/exception_wrapper.rb +1 -0
  31. data/lib/action_dispatch/middleware/public_exceptions.rb +6 -2
  32. data/lib/action_dispatch/middleware/remote_ip.rb +3 -3
  33. data/lib/action_dispatch/middleware/stack.rb +34 -2
  34. data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +13 -0
  35. data/lib/action_dispatch/middleware/templates/rescues/_actions.text.erb +0 -0
  36. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +3 -1
  37. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +1 -1
  38. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +6 -2
  39. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +1 -1
  40. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +3 -0
  41. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +2 -0
  42. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +4 -0
  43. data/lib/action_dispatch/railtie.rb +6 -2
  44. data/lib/action_dispatch/routing.rb +4 -4
  45. data/lib/action_dispatch/routing/mapper.rb +26 -11
  46. data/lib/action_dispatch/routing/route_set.rb +13 -15
  47. data/lib/action_dispatch/system_test_case.rb +22 -3
  48. data/lib/action_dispatch/system_testing/browser.rb +23 -0
  49. data/lib/action_dispatch/system_testing/driver.rb +2 -0
  50. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +2 -1
  51. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +7 -6
  52. data/lib/action_dispatch/testing/assertions.rb +1 -1
  53. data/lib/action_dispatch/testing/request_encoder.rb +2 -2
  54. data/lib/action_dispatch/testing/test_response.rb +1 -1
  55. data/lib/action_pack/gem_version.rb +2 -2
  56. metadata +20 -15
  57. data/lib/action_dispatch/system_testing/test_helpers/undef_methods.rb +0 -26
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a5a16ad6b7bbc7a93fbbe113780c3d5ad6bf791facc02dbf7c708ce0aa3b12a2
4
- data.tar.gz: c09c775266bb80b7da86600aa3ecdf9db41a711210014e94cceadbd0db2e4569
3
+ metadata.gz: d44df405c2e632ae4646871b8f5e08787c81a7348a8ade4b438cc2eef09fa827
4
+ data.tar.gz: 7f8ffc32efec243949b412fa7c15ef14eb672318ff14a00bc1a34044b6ac0f9d
5
5
  SHA512:
6
- metadata.gz: 9b667c6f5ba393b3470643d1bc3025e8c6a1062c8052a6129fb495a282132868673f625eef15dd1dee772ef79027c7ab45c4ed0c5184078292f7a8edd54a7289
7
- data.tar.gz: 131617cc29ed16b18d06507eca871e1e8b199d913765123488205a0c4a5abb0916be4d6558677d28cb4b37963580f5be8a3597c966863d87fd4c5205c4484ed4
6
+ metadata.gz: e30fa22231fd2de1bd198139ce016ecc35470fd46225d2c732a0a25a2ea624c1468197be68626775f710f5f8fa36396414965dd31e8da3c58c7cf2de3bd57fab
7
+ data.tar.gz: bd75118e12a3879f17cb4d4b0f35443ebbc2c4db77bd82f972807c061f513db95dc46a69de9015ba51693ddc3607d7dbec95e3224af316b66413b51543fc05b0
@@ -1,3 +1,111 @@
1
+ ## Rails 6.0.2.rc2 (December 09, 2019) ##
2
+
3
+ * Allow using mountable engine route helpers in System Tests.
4
+
5
+ *Chalo Fernandez*
6
+
7
+
8
+ ## Rails 6.0.1 (November 5, 2019) ##
9
+
10
+ * `ActionDispatch::SystemTestCase` now inherits from `ActiveSupport::TestCase`
11
+ rather than `ActionDispatch::IntegrationTest`. This permits running jobs in
12
+ system tests.
13
+
14
+ *George Claghorn*, *Edouard Chin*
15
+
16
+ * Registered MIME types may contain extra flags:
17
+
18
+ ```ruby
19
+ Mime::Type.register "text/html; fragment", :html_fragment
20
+ ```
21
+
22
+ *Aaron Patterson*
23
+
24
+
25
+ ## Rails 6.0.0 (August 16, 2019) ##
26
+
27
+ * No changes.
28
+
29
+
30
+ ## Rails 6.0.0.rc2 (July 22, 2019) ##
31
+
32
+ * Add the ability to set the CSP nonce only to the specified directives.
33
+
34
+ Fixes #35137.
35
+
36
+ *Yuji Yaginuma*
37
+
38
+ * Keep part when scope option has value.
39
+
40
+ When a route was defined within an optional scope, if that route didn't
41
+ take parameters the scope was lost when using path helpers. This commit
42
+ ensures scope is kept both when the route takes parameters or when it
43
+ doesn't.
44
+
45
+ Fixes #33219
46
+
47
+ *Alberto Almagro*
48
+
49
+ * Change `ActionDispatch::Response#content_type` to return Content-Type header as it is.
50
+
51
+ Previously, `ActionDispatch::Response#content_type` returned value does NOT
52
+ contain charset part. This behavior changed to returned Content-Type header
53
+ containing charset part as it is.
54
+
55
+ If you want just MIME type, please use `ActionDispatch::Response#media_type`
56
+ instead.
57
+
58
+ Enable `action_dispatch.return_only_media_type_on_content_type` to use this change.
59
+ If not enabled, `ActionDispatch::Response#content_type` returns the same
60
+ value as before version, but its behavior is deprecate.
61
+
62
+ *Yuji Yaginuma*
63
+
64
+ * Calling `ActionController::Parameters#transform_keys/!` without a block now returns
65
+ an enumerator for the parameters instead of the underlying hash.
66
+
67
+ *Eugene Kenny*
68
+
69
+ * Fix a bug where DebugExceptions throws an error when malformed query parameters are provided
70
+
71
+ *Yuki Nishijima*, *Stan Lo*
72
+
73
+
74
+ ## Rails 6.0.0.rc1 (April 24, 2019) ##
75
+
76
+ * Make system tests take a failed screenshot in a `before_teardown` hook
77
+ rather than an `after_teardown` hook.
78
+
79
+ This helps minimize the time gap between when an assertion fails and when
80
+ the screenshot is taken (reducing the time in which the page could have
81
+ been dynamically updated after the assertion failed).
82
+
83
+ *Richard Macklin*
84
+
85
+ * Introduce `ActionDispatch::ActionableExceptions`.
86
+
87
+ The `ActionDispatch::ActionableExceptions` middleware dispatches actions
88
+ from `ActiveSupport::ActionableError` descendants.
89
+
90
+ Actionable errors let's you dispatch actions from Rails' error pages.
91
+
92
+ *Vipul A M*, *Yao Jie*, *Genadi Samokovarov*
93
+
94
+ * Raise an `ArgumentError` if a resource custom param contains a colon (`:`).
95
+
96
+ After this change it's not possible anymore to configure routes like this:
97
+
98
+ ```
99
+ routes.draw do
100
+ resources :users, param: 'name/:sneaky'
101
+ end
102
+ ```
103
+
104
+ Fixes #30467.
105
+
106
+ *Josua Schmid*
107
+
108
+
1
109
  ## Rails 6.0.0.beta3 (March 11, 2019) ##
2
110
 
3
111
  * No changes.
@@ -28,12 +136,12 @@
28
136
 
29
137
  *Rafael Mendonça França*
30
138
 
31
- * Introduce ActionDispatch::HostAuthorization
139
+ * Introduce `ActionDispatch::HostAuthorization`.
32
140
 
33
141
  This is a new middleware that guards against DNS rebinding attacks by
34
142
  explicitly permitting the hosts a request can be made to.
35
143
 
36
- Each host is checked with the case operator (`#===`) to support `RegExp`,
144
+ Each host is checked with the case operator (`#===`) to support `Regexp`,
37
145
  `Proc`, `IPAddr` and custom objects as host allowances.
38
146
 
39
147
  *Genadi Samokovarov*
@@ -58,7 +166,7 @@
58
166
 
59
167
  * Raise an error on root route naming conflicts.
60
168
 
61
- Raises an ArgumentError when multiple root routes are defined in the
169
+ Raises an `ArgumentError` when multiple root routes are defined in the
62
170
  same context instead of assigning nil names to subsequent roots.
63
171
 
64
172
  *Gannon McGibbon*
@@ -23,6 +23,7 @@ by default and Action View rendering is implicitly triggered by Action
23
23
  Controller. However, these modules are designed to function on their own and
24
24
  can be used outside of Rails.
25
25
 
26
+ You can read more about Action Pack in the {Action Controller Overview}[https://guides.rubyonrails.org/action_controller_overview.html] guide.
26
27
 
27
28
  == Download and installation
28
29
 
@@ -46,7 +47,7 @@ Action Pack is released under the MIT license:
46
47
 
47
48
  API documentation is at:
48
49
 
49
- * http://api.rubyonrails.org
50
+ * https://api.rubyonrails.org
50
51
 
51
52
  Bug reports for the Ruby on Rails project can be filed here:
52
53
 
@@ -3,7 +3,6 @@
3
3
  require "active_support/rails"
4
4
  require "abstract_controller"
5
5
  require "action_dispatch"
6
- require "action_controller/metal/live"
7
6
  require "action_controller/metal/strong_parameters"
8
7
 
9
8
  module ActionController
@@ -21,6 +20,10 @@ module ActionController
21
20
  end
22
21
 
23
22
  autoload_under "metal" do
23
+ eager_autoload do
24
+ autoload :Live
25
+ end
26
+
24
27
  autoload :ConditionalGet
25
28
  autoload :ContentSecurityPolicy
26
29
  autoload :Cookies
@@ -26,10 +26,10 @@ module ActionController
26
26
  end
27
27
  end
28
28
 
29
- def build(action, app = Proc.new)
29
+ def build(action, app = nil, &block)
30
30
  action = action.to_s
31
31
 
32
- middlewares.reverse.inject(app) do |a, middleware|
32
+ middlewares.reverse.inject(app || block) do |a, middleware|
33
33
  middleware.valid?(action) ? middleware.build(a) : a
34
34
  end
35
35
  end
@@ -148,7 +148,7 @@ module ActionController
148
148
  attr_internal :response, :request
149
149
  delegate :session, to: "@_request"
150
150
  delegate :headers, :status=, :location=, :content_type=,
151
- :status, :location, :content_type, to: "@_response"
151
+ :status, :location, :content_type, :media_type, to: "@_response"
152
152
 
153
153
  def initialize
154
154
  @_request = nil
@@ -27,7 +27,7 @@ module ActionController
27
27
 
28
28
  class MethodNotAllowed < ActionControllerError #:nodoc:
29
29
  def initialize(*allowed_methods)
30
- super("Only #{allowed_methods.to_sentence(locale: :en)} requests are allowed.")
30
+ super("Only #{allowed_methods.to_sentence} requests are allowed.")
31
31
  end
32
32
  end
33
33
 
@@ -34,7 +34,7 @@ module ActionController
34
34
  # end
35
35
  # end
36
36
  #
37
- # Then, in any view rendered by <tt>EventController</tt>, the <tt>format_time</tt> method can be called:
37
+ # Then, in any view rendered by <tt>EventsController</tt>, the <tt>format_time</tt> method can be called:
38
38
  #
39
39
  # <% @events.each do |event| -%>
40
40
  # <p>
@@ -305,7 +305,7 @@ module ActionController
305
305
 
306
306
  logger.fatal do
307
307
  message = +"\n#{exception.class} (#{exception.message}):\n"
308
- message << exception.annoted_source_code.to_s if exception.respond_to?(:annoted_source_code)
308
+ message << exception.annotated_source_code.to_s if exception.respond_to?(:annotated_source_code)
309
309
  message << " " << exception.backtrace.join("\n ")
310
310
  "#{message}\n\n"
311
311
  end
@@ -205,7 +205,7 @@ module ActionController #:nodoc:
205
205
  yield collector if block_given?
206
206
 
207
207
  if format = collector.negotiate_format(request)
208
- if content_type && content_type != format
208
+ if media_type && media_type != format
209
209
  raise ActionController::RespondToMismatchError
210
210
  end
211
211
  _process_format(format)
@@ -93,7 +93,7 @@ module ActionController
93
93
  end
94
94
 
95
95
  def model
96
- super || synchronize { super || self.model = _default_wrap_model }
96
+ super || self.model = _default_wrap_model
97
97
  end
98
98
 
99
99
  def include
@@ -115,7 +115,7 @@ module ActionController
115
115
 
116
116
  if m.respond_to?(:nested_attributes_options) && m.nested_attributes_options.keys.any?
117
117
  self.include += m.nested_attributes_options.keys.map do |key|
118
- key.to_s.concat("_attributes")
118
+ (+key.to_s).concat("_attributes")
119
119
  end
120
120
  end
121
121
 
@@ -157,24 +157,24 @@ module ActionController
157
157
  json = json.to_json(options) unless json.kind_of?(String)
158
158
 
159
159
  if options[:callback].present?
160
- if content_type.nil? || content_type == Mime[:json]
160
+ if media_type.nil? || media_type == Mime[:json]
161
161
  self.content_type = Mime[:js]
162
162
  end
163
163
 
164
164
  "/**/#{options[:callback]}(#{json})"
165
165
  else
166
- self.content_type ||= Mime[:json]
166
+ self.content_type = Mime[:json] if media_type.nil?
167
167
  json
168
168
  end
169
169
  end
170
170
 
171
171
  add :js do |js, options|
172
- self.content_type ||= Mime[:js]
172
+ self.content_type = Mime[:js] if media_type.nil?
173
173
  js.respond_to?(:to_js) ? js.to_js(options) : js
174
174
  end
175
175
 
176
176
  add :xml do |xml, options|
177
- self.content_type ||= Mime[:xml]
177
+ self.content_type = Mime[:xml] if media_type.nil?
178
178
  xml.respond_to?(:to_xml) ? xml.to_xml(options) : xml
179
179
  end
180
180
  end
@@ -73,7 +73,7 @@ module ActionController
73
73
  end
74
74
 
75
75
  def _set_rendered_content_type(format)
76
- if format && !response.content_type
76
+ if format && !response.media_type
77
77
  self.content_type = format.to_s
78
78
  end
79
79
  end
@@ -282,7 +282,7 @@ module ActionController #:nodoc:
282
282
 
283
283
  # Check for cross-origin JavaScript responses.
284
284
  def non_xhr_javascript_response? # :doc:
285
- content_type =~ %r(\A(?:text|application)/javascript) && !request.xhr?
285
+ %r(\A(?:text|application)/javascript).match?(media_type) && !request.xhr?
286
286
  end
287
287
 
288
288
  AUTHENTICITY_TOKEN_LENGTH = 32
@@ -431,7 +431,7 @@ module ActionController #:nodoc:
431
431
  The browser returned a 'null' origin for a request with origin-based forgery protection turned on. This usually
432
432
  means you have the 'no-referrer' Referrer-Policy header enabled, or that the request came from a site that
433
433
  refused to give its origin. This makes it impossible for Rails to verify the source of the requests. Likely the
434
- best solution is to change your referrer policy to something less strict like same-origin or strict-same-origin.
434
+ best solution is to change your referrer policy to something less strict like same-origin or strict-origin.
435
435
  If you cannot change the referrer policy, you can disable origin checking with the
436
436
  Rails.application.config.action_controller.forgery_protection_origin_check setting.
437
437
  MSG
@@ -4,7 +4,6 @@ require "active_support/core_ext/hash/indifferent_access"
4
4
  require "active_support/core_ext/array/wrap"
5
5
  require "active_support/core_ext/string/filters"
6
6
  require "active_support/core_ext/object/to_query"
7
- require "active_support/rescuable"
8
7
  require "action_dispatch/http/upload"
9
8
  require "rack/test"
10
9
  require "stringio"
@@ -674,18 +673,16 @@ module ActionController
674
673
  # Returns a new <tt>ActionController::Parameters</tt> instance with the
675
674
  # results of running +block+ once for every key. The values are unchanged.
676
675
  def transform_keys(&block)
677
- if block
678
- new_instance_with_inherited_permitted_status(
679
- @parameters.transform_keys(&block)
680
- )
681
- else
682
- @parameters.transform_keys
683
- end
676
+ return to_enum(:transform_keys) unless block_given?
677
+ new_instance_with_inherited_permitted_status(
678
+ @parameters.transform_keys(&block)
679
+ )
684
680
  end
685
681
 
686
682
  # Performs keys transformation and returns the altered
687
683
  # <tt>ActionController::Parameters</tt> instance.
688
684
  def transform_keys!(&block)
685
+ return to_enum(:transform_keys!) unless block_given?
689
686
  @parameters.transform_keys!(&block)
690
687
  self
691
688
  end
@@ -1092,9 +1089,6 @@ module ActionController
1092
1089
  # See ActionController::Parameters.require and ActionController::Parameters.permit
1093
1090
  # for more information.
1094
1091
  module StrongParameters
1095
- extend ActiveSupport::Concern
1096
- include ActiveSupport::Rescuable
1097
-
1098
1092
  # Returns a new ActionController::Parameters object that
1099
1093
  # has been instantiated with the <tt>request.parameters</tt>.
1100
1094
  def params
@@ -74,7 +74,7 @@ module ActionController
74
74
  # * <tt>:partial</tt> - See <tt>ActionView::PartialRenderer</tt> for details.
75
75
  # * <tt>:file</tt> - Renders an explicit template file. Add <tt>:locals</tt> to pass in, if so desired.
76
76
  # It shouldn’t be used directly with unsanitized user input due to lack of validation.
77
- # * <tt>:inline</tt> - Renders a ERB template string.
77
+ # * <tt>:inline</tt> - Renders an ERB template string.
78
78
  # * <tt>:plain</tt> - Renders provided text and sets the content type as <tt>text/plain</tt>.
79
79
  # * <tt>:html</tt> - Renders the provided HTML safe string, otherwise
80
80
  # performs HTML escape on the string first. Sets the content type as <tt>text/html</tt>.
@@ -116,7 +116,7 @@ module ActionController
116
116
 
117
117
  RACK_VALUE_TRANSLATION = {
118
118
  https: ->(v) { v ? "on" : "off" },
119
- method: ->(v) { v.upcase },
119
+ method: ->(v) { -v.upcase },
120
120
  }
121
121
 
122
122
  def rack_key_for(key)
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActionController
4
- module TemplateAssertions
4
+ module TemplateAssertions # :nodoc:
5
5
  def assert_template(options = {}, message = nil)
6
6
  raise NoMethodError,
7
7
  "assert_template has been extracted to a gem. To continue using it,
@@ -457,6 +457,7 @@ module ActionController
457
457
  def process(action, method: "GET", params: nil, session: nil, body: nil, flash: {}, format: nil, xhr: false, as: nil)
458
458
  check_required_ivars
459
459
 
460
+ action = +action.to_s
460
461
  http_method = method.to_s.upcase
461
462
 
462
463
  @html_document = nil
@@ -488,11 +489,11 @@ module ActionController
488
489
  parameters[:format] = format
489
490
  end
490
491
 
491
- generated_extras = @routes.generate_extras(parameters.merge(controller: controller_class_name, action: action.to_s))
492
+ generated_extras = @routes.generate_extras(parameters.merge(controller: controller_class_name, action: action))
492
493
  generated_path = generated_path(generated_extras)
493
494
  query_string_keys = query_parameter_names(generated_extras)
494
495
 
495
- @request.assign_parameters(@routes, controller_class_name, action.to_s, parameters, generated_path, query_string_keys)
496
+ @request.assign_parameters(@routes, controller_class_name, action, parameters, generated_path, query_string_keys)
496
497
 
497
498
  @request.session.update(session) if session
498
499
  @request.flash.update(flash || {})
@@ -53,6 +53,7 @@ module ActionDispatch
53
53
  autoload :RequestId
54
54
  autoload :Callbacks
55
55
  autoload :Cookies
56
+ autoload :ActionableExceptions
56
57
  autoload :DebugExceptions
57
58
  autoload :DebugLocks
58
59
  autoload :DebugView
@@ -79,7 +80,6 @@ module ActionDispatch
79
80
  autoload :MimeNegotiation
80
81
  autoload :Parameters
81
82
  autoload :ParameterFilter
82
- autoload :Upload
83
83
  autoload :UploadedFile, "action_dispatch/http/upload"
84
84
  autoload :URL
85
85
  end
@@ -22,8 +22,9 @@ module ActionDispatch #:nodoc:
22
22
 
23
23
  if policy = request.content_security_policy
24
24
  nonce = request.content_security_policy_nonce
25
+ nonce_directives = request.content_security_policy_nonce_directives
25
26
  context = request.controller_instance || request
26
- headers[header_name(request)] = policy.build(context, nonce)
27
+ headers[header_name(request)] = policy.build(context, nonce, nonce_directives)
27
28
  end
28
29
 
29
30
  response
@@ -55,6 +56,7 @@ module ActionDispatch #:nodoc:
55
56
  POLICY_REPORT_ONLY = "action_dispatch.content_security_policy_report_only"
56
57
  NONCE_GENERATOR = "action_dispatch.content_security_policy_nonce_generator"
57
58
  NONCE = "action_dispatch.content_security_policy_nonce"
59
+ NONCE_DIRECTIVES = "action_dispatch.content_security_policy_nonce_directives"
58
60
 
59
61
  def content_security_policy
60
62
  get_header(POLICY)
@@ -80,6 +82,14 @@ module ActionDispatch #:nodoc:
80
82
  set_header(NONCE_GENERATOR, generator)
81
83
  end
82
84
 
85
+ def content_security_policy_nonce_directives
86
+ get_header(NONCE_DIRECTIVES)
87
+ end
88
+
89
+ def content_security_policy_nonce_directives=(generator)
90
+ set_header(NONCE_DIRECTIVES, generator)
91
+ end
92
+
83
93
  def content_security_policy_nonce
84
94
  if content_security_policy_nonce_generator
85
95
  if nonce = get_header(NONCE)
@@ -133,9 +143,9 @@ module ActionDispatch #:nodoc:
133
143
  worker_src: "worker-src"
134
144
  }.freeze
135
145
 
136
- NONCE_DIRECTIVES = %w[script-src style-src].freeze
146
+ DEFAULT_NONCE_DIRECTIVES = %w[script-src style-src].freeze
137
147
 
138
- private_constant :MAPPINGS, :DIRECTIVES, :NONCE_DIRECTIVES
148
+ private_constant :MAPPINGS, :DIRECTIVES, :DEFAULT_NONCE_DIRECTIVES
139
149
 
140
150
  attr_reader :directives
141
151
 
@@ -204,8 +214,9 @@ module ActionDispatch #:nodoc:
204
214
  end
205
215
  end
206
216
 
207
- def build(context = nil, nonce = nil)
208
- build_directives(context, nonce).compact.join("; ")
217
+ def build(context = nil, nonce = nil, nonce_directives = nil)
218
+ nonce_directives = DEFAULT_NONCE_DIRECTIVES if nonce_directives.nil?
219
+ build_directives(context, nonce, nonce_directives).compact.join("; ")
209
220
  end
210
221
 
211
222
  private
@@ -228,10 +239,10 @@ module ActionDispatch #:nodoc:
228
239
  end
229
240
  end
230
241
 
231
- def build_directives(context, nonce)
242
+ def build_directives(context, nonce, nonce_directives)
232
243
  @directives.map do |directive, sources|
233
244
  if sources.is_a?(Array)
234
- if nonce && nonce_directive?(directive)
245
+ if nonce && nonce_directive?(directive, nonce_directives)
235
246
  "#{directive} #{build_directive(sources, context).join(' ')} 'nonce-#{nonce}'"
236
247
  else
237
248
  "#{directive} #{build_directive(sources, context).join(' ')}"
@@ -266,8 +277,8 @@ module ActionDispatch #:nodoc:
266
277
  end
267
278
  end
268
279
 
269
- def nonce_directive?(directive)
270
- NONCE_DIRECTIVES.include?(directive)
280
+ def nonce_directive?(directive, nonce_directives)
281
+ nonce_directives.include?(directive)
271
282
  end
272
283
  end
273
284
  end