aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_controller
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib/action_controller')
-rw-r--r--actionpack/lib/action_controller/base.rb1
-rw-r--r--actionpack/lib/action_controller/caching.rb1
-rw-r--r--actionpack/lib/action_controller/metal.rb3
-rw-r--r--actionpack/lib/action_controller/metal/content_security_policy.rb1
-rw-r--r--actionpack/lib/action_controller/metal/data_streaming.rb2
-rw-r--r--actionpack/lib/action_controller/metal/feature_policy.rb46
-rw-r--r--actionpack/lib/action_controller/metal/http_authentication.rb2
-rw-r--r--actionpack/lib/action_controller/metal/instrumentation.rb1
-rw-r--r--actionpack/lib/action_controller/metal/live.rb4
-rw-r--r--actionpack/lib/action_controller/metal/mime_responds.rb4
-rw-r--r--actionpack/lib/action_controller/metal/params_wrapper.rb1
-rw-r--r--actionpack/lib/action_controller/metal/renderers.rb2
-rw-r--r--actionpack/lib/action_controller/metal/rendering.rb7
-rw-r--r--actionpack/lib/action_controller/metal/request_forgery_protection.rb4
-rw-r--r--actionpack/lib/action_controller/metal/streaming.rb1
-rw-r--r--actionpack/lib/action_controller/metal/strong_parameters.rb70
-rw-r--r--actionpack/lib/action_controller/template_assertions.rb2
-rw-r--r--actionpack/lib/action_controller/test_case.rb7
18 files changed, 118 insertions, 41 deletions
diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb
index 2e565d5d44..63c138af55 100644
--- a/actionpack/lib/action_controller/base.rb
+++ b/actionpack/lib/action_controller/base.rb
@@ -226,6 +226,7 @@ module ActionController
FormBuilder,
RequestForgeryProtection,
ContentSecurityPolicy,
+ FeaturePolicy,
ForceSSL,
Streaming,
DataStreaming,
diff --git a/actionpack/lib/action_controller/caching.rb b/actionpack/lib/action_controller/caching.rb
index bf3b00a7b7..83e3e0c37c 100644
--- a/actionpack/lib/action_controller/caching.rb
+++ b/actionpack/lib/action_controller/caching.rb
@@ -30,7 +30,6 @@ module ActionController
end
private
-
def instrument_payload(key)
{
controller: controller_name,
diff --git a/actionpack/lib/action_controller/metal.rb b/actionpack/lib/action_controller/metal.rb
index b9088e6d86..ec2207b8da 100644
--- a/actionpack/lib/action_controller/metal.rb
+++ b/actionpack/lib/action_controller/metal.rb
@@ -35,7 +35,6 @@ module ActionController
end
private
-
INCLUDE = ->(list, action) { list.include? action }
EXCLUDE = ->(list, action) { !list.include? action }
NULL = ->(list, action) { true }
@@ -148,7 +147,7 @@ module ActionController
attr_internal :response, :request
delegate :session, to: "@_request"
delegate :headers, :status=, :location=, :content_type=,
- :status, :location, :content_type, to: "@_response"
+ :status, :location, :content_type, :media_type, to: "@_response"
def initialize
@_request = nil
diff --git a/actionpack/lib/action_controller/metal/content_security_policy.rb b/actionpack/lib/action_controller/metal/content_security_policy.rb
index b8fab4ebe3..ebd90f07c8 100644
--- a/actionpack/lib/action_controller/metal/content_security_policy.rb
+++ b/actionpack/lib/action_controller/metal/content_security_policy.rb
@@ -36,7 +36,6 @@ module ActionController #:nodoc:
end
private
-
def content_security_policy?
request.content_security_policy
end
diff --git a/actionpack/lib/action_controller/metal/data_streaming.rb b/actionpack/lib/action_controller/metal/data_streaming.rb
index 9ef4f50df1..879745a895 100644
--- a/actionpack/lib/action_controller/metal/data_streaming.rb
+++ b/actionpack/lib/action_controller/metal/data_streaming.rb
@@ -53,7 +53,7 @@ module ActionController #:nodoc:
#
# Show a 404 page in the browser:
#
- # send_file '/path/to/404.html', type: 'text/html; charset=utf-8', status: 404
+ # send_file '/path/to/404.html', type: 'text/html; charset=utf-8', disposition: 'inline', status: 404
#
# Read about the other Content-* HTTP headers if you'd like to
# provide the user with more information (such as Content-Description) in
diff --git a/actionpack/lib/action_controller/metal/feature_policy.rb b/actionpack/lib/action_controller/metal/feature_policy.rb
new file mode 100644
index 0000000000..a627eabea6
--- /dev/null
+++ b/actionpack/lib/action_controller/metal/feature_policy.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+module ActionController #:nodoc:
+ # HTTP Feature Policy is a web standard for defining a mechanism to
+ # allow and deny the use of browser features in its own context, and
+ # in content within any <iframe> elements in the document.
+ #
+ # Full details of HTTP Feature Policy specification and guidelines can
+ # be found at MDN:
+ #
+ # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Feature-Policy
+ #
+ # Examples of usage:
+ #
+ # # Global policy
+ # Rails.application.config.feature_policy do |f|
+ # f.camera :none
+ # f.gyroscope :none
+ # f.microphone :none
+ # f.usb :none
+ # f.fullscreen :self
+ # f.payment :self, "https://secure.example.com"
+ # end
+ #
+ # # Controller level policy
+ # class PagesController < ApplicationController
+ # feature_policy do |p|
+ # p.geolocation "https://example.com"
+ # end
+ # end
+ module FeaturePolicy
+ extend ActiveSupport::Concern
+
+ module ClassMethods
+ def feature_policy(**options, &block)
+ before_action(options) do
+ if block_given?
+ policy = request.feature_policy.clone
+ yield policy
+ request.feature_policy = policy
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/actionpack/lib/action_controller/metal/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb
index 6a274d35cb..ec0c9ecc67 100644
--- a/actionpack/lib/action_controller/metal/http_authentication.rb
+++ b/actionpack/lib/action_controller/metal/http_authentication.rb
@@ -482,7 +482,7 @@ module ActionController
def raw_params(auth)
_raw_params = auth.sub(TOKEN_REGEX, "").split(/\s*#{AUTHN_PAIR_DELIMITERS}\s*/)
- if !(_raw_params.first =~ %r{\A#{TOKEN_KEY}})
+ if !(%r{\A#{TOKEN_KEY}}.match?(_raw_params.first))
_raw_params[0] = "#{TOKEN_KEY}#{_raw_params.first}"
end
diff --git a/actionpack/lib/action_controller/metal/instrumentation.rb b/actionpack/lib/action_controller/metal/instrumentation.rb
index 51fac08749..6f7fc0d624 100644
--- a/actionpack/lib/action_controller/metal/instrumentation.rb
+++ b/actionpack/lib/action_controller/metal/instrumentation.rb
@@ -69,7 +69,6 @@ module ActionController
end
private
-
# A hook invoked every time a before callback is halted.
def halted_callback_hook(filter)
ActiveSupport::Notifications.instrument("halted_callback.action_controller", filter: filter)
diff --git a/actionpack/lib/action_controller/metal/live.rb b/actionpack/lib/action_controller/metal/live.rb
index dd69930e25..4454ba1e3d 100644
--- a/actionpack/lib/action_controller/metal/live.rb
+++ b/actionpack/lib/action_controller/metal/live.rb
@@ -107,7 +107,6 @@ module ActionController
end
private
-
def perform_write(json, options)
current_options = @options.merge(options).stringify_keys
@@ -205,7 +204,6 @@ module ActionController
end
private
-
def each_chunk(&block)
loop do
str = nil
@@ -220,7 +218,6 @@ module ActionController
class Response < ActionDispatch::Response #:nodoc: all
private
-
def before_committed
super
jar = request.cookie_jar
@@ -286,7 +283,6 @@ module ActionController
end
private
-
# Spawn a new thread to serve up the controller in. This is to get
# around the fact that Rack isn't based around IOs and we need to use
# a thread to stream data from the response bodies. Nobody should call
diff --git a/actionpack/lib/action_controller/metal/mime_responds.rb b/actionpack/lib/action_controller/metal/mime_responds.rb
index bf5e7a433f..a993c76af9 100644
--- a/actionpack/lib/action_controller/metal/mime_responds.rb
+++ b/actionpack/lib/action_controller/metal/mime_responds.rb
@@ -142,7 +142,7 @@ module ActionController #:nodoc:
#
# You can set the variant in a +before_action+:
#
- # request.variant = :tablet if request.user_agent =~ /iPad/
+ # request.variant = :tablet if /iPad/.match?(request.user_agent)
#
# Respond to variants in the action just like you respond to formats:
#
@@ -205,7 +205,7 @@ module ActionController #:nodoc:
yield collector if block_given?
if format = collector.negotiate_format(request)
- if content_type && content_type != format
+ if media_type && media_type != format
raise ActionController::RespondToMismatchError
end
_process_format(format)
diff --git a/actionpack/lib/action_controller/metal/params_wrapper.rb b/actionpack/lib/action_controller/metal/params_wrapper.rb
index e635abec8e..150ae2666c 100644
--- a/actionpack/lib/action_controller/metal/params_wrapper.rb
+++ b/actionpack/lib/action_controller/metal/params_wrapper.rb
@@ -246,7 +246,6 @@ module ActionController
end
private
-
# Returns the wrapper key which will be used to store wrapped parameters.
def _wrapper_key
_wrapper_options.name
diff --git a/actionpack/lib/action_controller/metal/renderers.rb b/actionpack/lib/action_controller/metal/renderers.rb
index b81d3ef539..a251c29d23 100644
--- a/actionpack/lib/action_controller/metal/renderers.rb
+++ b/actionpack/lib/action_controller/metal/renderers.rb
@@ -157,7 +157,7 @@ module ActionController
json = json.to_json(options) unless json.kind_of?(String)
if options[:callback].present?
- if content_type.nil? || content_type == Mime[:json]
+ if media_type.nil? || media_type == Mime[:json]
self.content_type = Mime[:js]
end
diff --git a/actionpack/lib/action_controller/metal/rendering.rb b/actionpack/lib/action_controller/metal/rendering.rb
index 7d0a944381..fd22c4fa64 100644
--- a/actionpack/lib/action_controller/metal/rendering.rb
+++ b/actionpack/lib/action_controller/metal/rendering.rb
@@ -53,7 +53,6 @@ module ActionController
end
private
-
def _process_variant(options)
if defined?(request) && !request.nil? && request.variant.present?
options[:variant] = request.variant
@@ -73,11 +72,15 @@ module ActionController
end
def _set_rendered_content_type(format)
- if format && !response.content_type
+ if format && !response.media_type
self.content_type = format.to_s
end
end
+ def _set_vary_header
+ self.headers["Vary"] = "Accept" if request.should_apply_vary_header?
+ end
+
# Normalize arguments by catching blocks and setting them on :update.
def _normalize_args(action = nil, options = {}, &blk)
options = super
diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
index 4bf8d90b69..e923afb17c 100644
--- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb
+++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
@@ -151,7 +151,6 @@ module ActionController #:nodoc:
end
private
-
def protection_method_class(name)
ActionController::RequestForgeryProtection::ProtectionMethods.const_get(name.to_s.classify)
rescue NameError
@@ -175,7 +174,6 @@ module ActionController #:nodoc:
end
private
-
class NullSessionHash < Rack::Session::Abstract::SessionHash #:nodoc:
def initialize(req)
super(nil, req)
@@ -282,7 +280,7 @@ module ActionController #:nodoc:
# Check for cross-origin JavaScript responses.
def non_xhr_javascript_response? # :doc:
- content_type =~ %r(\A(?:text|application)/javascript) && !request.xhr?
+ %r(\A(?:text|application)/javascript).match?(content_type) && !request.xhr?
end
AUTHENTICITY_TOKEN_LENGTH = 32
diff --git a/actionpack/lib/action_controller/metal/streaming.rb b/actionpack/lib/action_controller/metal/streaming.rb
index 8dc01a5eb9..94a62e5cab 100644
--- a/actionpack/lib/action_controller/metal/streaming.rb
+++ b/actionpack/lib/action_controller/metal/streaming.rb
@@ -196,7 +196,6 @@ module ActionController #:nodoc:
extend ActiveSupport::Concern
private
-
# Set proper cache control and transfer encoding when streaming
def _process_options(options)
super
diff --git a/actionpack/lib/action_controller/metal/strong_parameters.rb b/actionpack/lib/action_controller/metal/strong_parameters.rb
index ae774b01f1..4c9eb20c65 100644
--- a/actionpack/lib/action_controller/metal/strong_parameters.rb
+++ b/actionpack/lib/action_controller/metal/strong_parameters.rb
@@ -223,6 +223,12 @@ module ActionController
# config.always_permitted_parameters = %w( controller action format )
cattr_accessor :always_permitted_parameters, default: %w( controller action )
+ class << self
+ def nested_attribute?(key, value) # :nodoc:
+ /\A-?\d+\z/.match?(key) && (value.is_a?(Hash) || value.is_a?(Parameters))
+ end
+ end
+
# Returns a new instance of <tt>ActionController::Parameters</tt>.
# Also, sets the +permitted+ attribute to the default value of
# <tt>ActionController::Parameters.permit_all_parameters</tt>.
@@ -253,6 +259,11 @@ module ActionController
@parameters == other
end
end
+ alias eql? ==
+
+ def hash
+ [@parameters.hash, @permitted].hash
+ end
# Returns a safe <tt>ActiveSupport::HashWithIndifferentAccess</tt>
# representation of the parameters with all unpermitted keys removed.
@@ -673,22 +684,37 @@ module ActionController
# Returns a new <tt>ActionController::Parameters</tt> instance with the
# results of running +block+ once for every key. The values are unchanged.
def transform_keys(&block)
- if block
- new_instance_with_inherited_permitted_status(
- @parameters.transform_keys(&block)
- )
- else
- @parameters.transform_keys
- end
+ return to_enum(:transform_keys) unless block_given?
+ new_instance_with_inherited_permitted_status(
+ @parameters.transform_keys(&block)
+ )
end
# Performs keys transformation and returns the altered
# <tt>ActionController::Parameters</tt> instance.
def transform_keys!(&block)
+ return to_enum(:transform_keys!) unless block_given?
@parameters.transform_keys!(&block)
self
end
+ # Returns a new <tt>ActionController::Parameters</tt> instance with the
+ # results of running +block+ once for every key. This includes the keys
+ # from the root hash and from all nested hashes and arrays. The values are unchanged.
+ def deep_transform_keys(&block)
+ new_instance_with_inherited_permitted_status(
+ @parameters.deep_transform_keys(&block)
+ )
+ end
+
+ # Returns the <tt>ActionController::Parameters</tt> instance changing its keys.
+ # This includes the keys from the root hash and from all nested hashes and arrays.
+ # The values are unchanged.
+ def deep_transform_keys!(&block)
+ @parameters.deep_transform_keys!(&block)
+ self
+ end
+
# Deletes a key-value pair from +Parameters+ and returns the value. If
# +key+ is not found, returns +nil+ (or, with optional code block, yields
# +key+ and returns the result). Cf. +#extract!+, which returns the
@@ -723,6 +749,18 @@ module ActionController
end
alias_method :delete_if, :reject!
+ # Returns a new instance of <tt>ActionController::Parameters</tt> without the blank values.
+ # Uses Object#blank? for determining if a value is blank.
+ def compact_blank
+ reject { |_k, v| v.blank? }
+ end
+
+ # Removes all blank values in place and returns self.
+ # Uses Object#blank? for determining if a value is blank.
+ def compact_blank!
+ reject! { |_k, v| v.blank? }
+ end
+
# Returns values that were assigned to the given +keys+. Note that all the
# +Hash+ objects will be converted to <tt>ActionController::Parameters</tt>.
def values_at(*keys)
@@ -811,8 +849,14 @@ module ActionController
attr_writer :permitted
- def fields_for_style?
- @parameters.all? { |k, v| k =~ /\A-?\d+\z/ && (v.is_a?(Hash) || v.is_a?(Parameters)) }
+ def nested_attributes?
+ @parameters.any? { |k, v| Parameters.nested_attribute?(k, v) }
+ end
+
+ def each_nested_attribute
+ hash = self.class.new
+ self.each { |k, v| hash[k] = yield v if Parameters.nested_attribute?(k, v) }
+ hash
end
private
@@ -857,15 +901,13 @@ module ActionController
end
end
- def each_element(object)
+ def each_element(object, &block)
case object
when Array
object.grep(Parameters).map { |el| yield el }.compact
when Parameters
- if object.fields_for_style?
- hash = object.class.new
- object.each { |k, v| hash[k] = yield v }
- hash
+ if object.nested_attributes?
+ object.each_nested_attribute(&block)
else
yield object
end
diff --git a/actionpack/lib/action_controller/template_assertions.rb b/actionpack/lib/action_controller/template_assertions.rb
index dd83c1a283..ec44dbe157 100644
--- a/actionpack/lib/action_controller/template_assertions.rb
+++ b/actionpack/lib/action_controller/template_assertions.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module ActionController
- module TemplateAssertions
+ module TemplateAssertions # :nodoc:
def assert_template(options = {}, message = nil)
raise NoMethodError,
"assert_template has been extracted to a gem. To continue using it,
diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb
index 57921f32b7..1632ac3ae8 100644
--- a/actionpack/lib/action_controller/test_case.rb
+++ b/actionpack/lib/action_controller/test_case.rb
@@ -158,7 +158,6 @@ module ActionController
end.new
private
-
def params_parsers
super.merge @custom_param_parsers
end
@@ -208,7 +207,6 @@ module ActionController
end
private
-
def load!
@id
end
@@ -594,10 +592,9 @@ module ActionController
end
private
-
def scrub_env!(env)
- env.delete_if { |k, v| k =~ /^(action_dispatch|rack)\.request/ }
- env.delete_if { |k, v| k =~ /^action_dispatch\.rescue/ }
+ env.delete_if { |k, v| k.match?(/^(action_dispatch|rack)\.request/) }
+ env.delete_if { |k, v| k.match?(/^action_dispatch\.rescue/) }
env.delete "action_dispatch.request.query_parameters"
env.delete "action_dispatch.request.request_parameters"
env["rack.input"] = StringIO.new