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/api.rb2
-rw-r--r--actionpack/lib/action_controller/api/api_rendering.rb2
-rw-r--r--actionpack/lib/action_controller/base.rb3
-rw-r--r--actionpack/lib/action_controller/caching.rb2
-rw-r--r--actionpack/lib/action_controller/form_builder.rb2
-rw-r--r--actionpack/lib/action_controller/log_subscriber.rb4
-rw-r--r--actionpack/lib/action_controller/metal.rb20
-rw-r--r--actionpack/lib/action_controller/metal/basic_implicit_render.rb2
-rw-r--r--actionpack/lib/action_controller/metal/conditional_get.rb4
-rw-r--r--actionpack/lib/action_controller/metal/content_security_policy.rb26
-rw-r--r--actionpack/lib/action_controller/metal/cookies.rb2
-rw-r--r--actionpack/lib/action_controller/metal/data_streaming.rb12
-rw-r--r--actionpack/lib/action_controller/metal/etag_with_flash.rb2
-rw-r--r--actionpack/lib/action_controller/metal/etag_with_template_digest.rb2
-rw-r--r--actionpack/lib/action_controller/metal/exceptions.rb5
-rw-r--r--actionpack/lib/action_controller/metal/flash.rb2
-rw-r--r--actionpack/lib/action_controller/metal/force_ssl.rb6
-rw-r--r--actionpack/lib/action_controller/metal/head.rb2
-rw-r--r--actionpack/lib/action_controller/metal/helpers.rb2
-rw-r--r--actionpack/lib/action_controller/metal/http_authentication.rb17
-rw-r--r--actionpack/lib/action_controller/metal/implicit_render.rb2
-rw-r--r--actionpack/lib/action_controller/metal/instrumentation.rb10
-rw-r--r--actionpack/lib/action_controller/metal/live.rb4
-rw-r--r--actionpack/lib/action_controller/metal/mime_responds.rb2
-rw-r--r--actionpack/lib/action_controller/metal/parameter_encoding.rb2
-rw-r--r--actionpack/lib/action_controller/metal/params_wrapper.rb19
-rw-r--r--actionpack/lib/action_controller/metal/redirecting.rb31
-rw-r--r--actionpack/lib/action_controller/metal/renderers.rb4
-rw-r--r--actionpack/lib/action_controller/metal/rendering.rb4
-rw-r--r--actionpack/lib/action_controller/metal/request_forgery_protection.rb39
-rw-r--r--actionpack/lib/action_controller/metal/rescue.rb8
-rw-r--r--actionpack/lib/action_controller/metal/streaming.rb4
-rw-r--r--actionpack/lib/action_controller/metal/strong_parameters.rb26
-rw-r--r--actionpack/lib/action_controller/metal/testing.rb8
-rw-r--r--actionpack/lib/action_controller/metal/url_for.rb2
-rw-r--r--actionpack/lib/action_controller/railtie.rb32
-rw-r--r--actionpack/lib/action_controller/railties/helpers.rb2
-rw-r--r--actionpack/lib/action_controller/renderer.rb2
-rw-r--r--actionpack/lib/action_controller/template_assertions.rb2
-rw-r--r--actionpack/lib/action_controller/test_case.rb7
40 files changed, 238 insertions, 91 deletions
diff --git a/actionpack/lib/action_controller/api.rb b/actionpack/lib/action_controller/api.rb
index 94698df730..b192e496de 100644
--- a/actionpack/lib/action_controller/api.rb
+++ b/actionpack/lib/action_controller/api.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "action_view"
require "action_controller"
require "action_controller/log_subscriber"
diff --git a/actionpack/lib/action_controller/api/api_rendering.rb b/actionpack/lib/action_controller/api/api_rendering.rb
index 3a08d28c39..aca5265313 100644
--- a/actionpack/lib/action_controller/api/api_rendering.rb
+++ b/actionpack/lib/action_controller/api/api_rendering.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActionController
module ApiRendering
extend ActiveSupport::Concern
diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb
index 8c2b111f89..204a3d400c 100644
--- a/actionpack/lib/action_controller/base.rb
+++ b/actionpack/lib/action_controller/base.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "action_view"
require "action_controller/log_subscriber"
require "action_controller/metal/params_wrapper"
@@ -223,6 +225,7 @@ module ActionController
Flash,
FormBuilder,
RequestForgeryProtection,
+ ContentSecurityPolicy,
ForceSSL,
Streaming,
DataStreaming,
diff --git a/actionpack/lib/action_controller/caching.rb b/actionpack/lib/action_controller/caching.rb
index 954265ad97..97775d1dc8 100644
--- a/actionpack/lib/action_controller/caching.rb
+++ b/actionpack/lib/action_controller/caching.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActionController
# \Caching is a cheap way of speeding up slow applications by keeping the result of
# calculations, renderings, and database calls around for subsequent requests.
diff --git a/actionpack/lib/action_controller/form_builder.rb b/actionpack/lib/action_controller/form_builder.rb
index f2656ca894..09d2ac1837 100644
--- a/actionpack/lib/action_controller/form_builder.rb
+++ b/actionpack/lib/action_controller/form_builder.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActionController
# Override the default form builder for all views rendered by this
# controller and any of its descendants. Accepts a subclass of
diff --git a/actionpack/lib/action_controller/log_subscriber.rb b/actionpack/lib/action_controller/log_subscriber.rb
index d00fcbcd13..14f41eb55f 100644
--- a/actionpack/lib/action_controller/log_subscriber.rb
+++ b/actionpack/lib/action_controller/log_subscriber.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActionController
class LogSubscriber < ActiveSupport::LogSubscriber
INTERNAL_PARAMS = %w(controller action format _method only_path)
@@ -24,7 +26,7 @@ module ActionController
exception_class_name = payload[:exception].first
status = ActionDispatch::ExceptionWrapper.status_code_for_exception(exception_class_name)
end
- message = "Completed #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]} in #{event.duration.round}ms"
+ message = "Completed #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]} in #{event.duration.round}ms".dup
message << " (#{additions.join(" | ".freeze)})" unless additions.empty?
message << "\n\n" if defined?(Rails.env) && Rails.env.development?
diff --git a/actionpack/lib/action_controller/metal.rb b/actionpack/lib/action_controller/metal.rb
index 96c708f45a..f875aa5e6b 100644
--- a/actionpack/lib/action_controller/metal.rb
+++ b/actionpack/lib/action_controller/metal.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "active_support/core_ext/array/extract_options"
require "action_dispatch/middleware/stack"
require "action_dispatch/http/request"
@@ -228,18 +230,16 @@ module ActionController
# Returns a Rack endpoint for the given action name.
def self.action(name)
+ app = lambda { |env|
+ req = ActionDispatch::Request.new(env)
+ res = make_response! req
+ new.dispatch(name, req, res)
+ }
+
if middleware_stack.any?
- middleware_stack.build(name) do |env|
- req = ActionDispatch::Request.new(env)
- res = make_response! req
- new.dispatch(name, req, res)
- end
+ middleware_stack.build(name, app)
else
- lambda { |env|
- req = ActionDispatch::Request.new(env)
- res = make_response! req
- new.dispatch(name, req, res)
- }
+ app
end
end
diff --git a/actionpack/lib/action_controller/metal/basic_implicit_render.rb b/actionpack/lib/action_controller/metal/basic_implicit_render.rb
index cef65a362c..2dc990f303 100644
--- a/actionpack/lib/action_controller/metal/basic_implicit_render.rb
+++ b/actionpack/lib/action_controller/metal/basic_implicit_render.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActionController
module BasicImplicitRender # :nodoc:
def send_action(method, *args)
diff --git a/actionpack/lib/action_controller/metal/conditional_get.rb b/actionpack/lib/action_controller/metal/conditional_get.rb
index 0525252c7c..06b6a95ff8 100644
--- a/actionpack/lib/action_controller/metal/conditional_get.rb
+++ b/actionpack/lib/action_controller/metal/conditional_get.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "active_support/core_ext/hash/keys"
module ActionController
@@ -226,7 +228,7 @@ module ActionController
# expires_in 3.hours, public: true, must_revalidate: true
#
# This method will overwrite an existing Cache-Control header.
- # See http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html for more possibilities.
+ # See https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html for more possibilities.
#
# The method will also ensure an HTTP Date header for client compatibility.
def expires_in(seconds, options = {})
diff --git a/actionpack/lib/action_controller/metal/content_security_policy.rb b/actionpack/lib/action_controller/metal/content_security_policy.rb
new file mode 100644
index 0000000000..48a7109bea
--- /dev/null
+++ b/actionpack/lib/action_controller/metal/content_security_policy.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+module ActionController #:nodoc:
+ module ContentSecurityPolicy
+ # TODO: Documentation
+ extend ActiveSupport::Concern
+
+ module ClassMethods
+ def content_security_policy(**options, &block)
+ before_action(options) do
+ if block_given?
+ policy = request.content_security_policy.clone
+ yield policy
+ request.content_security_policy = policy
+ end
+ end
+ end
+
+ def content_security_policy_report_only(report_only = true, **options)
+ before_action(options) do
+ request.content_security_policy_report_only = report_only
+ end
+ end
+ end
+ end
+end
diff --git a/actionpack/lib/action_controller/metal/cookies.rb b/actionpack/lib/action_controller/metal/cookies.rb
index 44925641a1..ff46966693 100644
--- a/actionpack/lib/action_controller/metal/cookies.rb
+++ b/actionpack/lib/action_controller/metal/cookies.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActionController #:nodoc:
module Cookies
extend ActiveSupport::Concern
diff --git a/actionpack/lib/action_controller/metal/data_streaming.rb b/actionpack/lib/action_controller/metal/data_streaming.rb
index 731e03e2fc..5a82ccf668 100644
--- a/actionpack/lib/action_controller/metal/data_streaming.rb
+++ b/actionpack/lib/action_controller/metal/data_streaming.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "action_controller/metal/exceptions"
module ActionController #:nodoc:
@@ -54,14 +56,14 @@ module ActionController #:nodoc:
#
# Read about the other Content-* HTTP headers if you'd like to
# provide the user with more information (such as Content-Description) in
- # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.11.
+ # https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.11.
#
# Also be aware that the document may be cached by proxies and browsers.
# The Pragma and Cache-Control headers declare how the file may be cached
# by intermediaries. They default to require clients to validate with
# the server before releasing cached responses. See
- # http://www.mnot.net/cache_docs/ for an overview of web caching and
- # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9
+ # https://www.mnot.net/cache_docs/ for an overview of web caching and
+ # https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9
# for the Cache-Control header spec.
def send_file(path, options = {}) #:doc:
raise MissingFile, "Cannot read file #{path}" unless File.file?(path) && File.readable?(path)
@@ -111,10 +113,10 @@ module ActionController #:nodoc:
def send_file_headers!(options)
type_provided = options.has_key?(:type)
- self.content_type = DEFAULT_SEND_FILE_TYPE
+ content_type = options.fetch(:type, DEFAULT_SEND_FILE_TYPE)
+ self.content_type = content_type
response.sending_file = true
- content_type = options.fetch(:type, DEFAULT_SEND_FILE_TYPE)
raise ArgumentError, ":type option required" if content_type.nil?
if content_type.is_a?(Symbol)
diff --git a/actionpack/lib/action_controller/metal/etag_with_flash.rb b/actionpack/lib/action_controller/metal/etag_with_flash.rb
index 7bd338bd7c..38899e2f16 100644
--- a/actionpack/lib/action_controller/metal/etag_with_flash.rb
+++ b/actionpack/lib/action_controller/metal/etag_with_flash.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActionController
# When you're using the flash, it's generally used as a conditional on the view.
# This means the content of the view depends on the flash. Which in turn means
diff --git a/actionpack/lib/action_controller/metal/etag_with_template_digest.rb b/actionpack/lib/action_controller/metal/etag_with_template_digest.rb
index 69c3979a0e..640c75536e 100644
--- a/actionpack/lib/action_controller/metal/etag_with_template_digest.rb
+++ b/actionpack/lib/action_controller/metal/etag_with_template_digest.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActionController
# When our views change, they should bubble up into HTTP cache freshness
# and bust browser caches. So the template digest for the current action
diff --git a/actionpack/lib/action_controller/metal/exceptions.rb b/actionpack/lib/action_controller/metal/exceptions.rb
index 175dd9eb9e..a65857d6ef 100644
--- a/actionpack/lib/action_controller/metal/exceptions.rb
+++ b/actionpack/lib/action_controller/metal/exceptions.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActionController
class ActionControllerError < StandardError #:nodoc:
end
@@ -32,9 +34,6 @@ module ActionController
class NotImplemented < MethodNotAllowed #:nodoc:
end
- class UnknownController < ActionControllerError #:nodoc:
- end
-
class MissingFile < ActionControllerError #:nodoc:
end
diff --git a/actionpack/lib/action_controller/metal/flash.rb b/actionpack/lib/action_controller/metal/flash.rb
index 24d1097ebe..5115c2fadf 100644
--- a/actionpack/lib/action_controller/metal/flash.rb
+++ b/actionpack/lib/action_controller/metal/flash.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActionController #:nodoc:
module Flash
extend ActiveSupport::Concern
diff --git a/actionpack/lib/action_controller/metal/force_ssl.rb b/actionpack/lib/action_controller/metal/force_ssl.rb
index 73e67573ca..7de500d119 100644
--- a/actionpack/lib/action_controller/metal/force_ssl.rb
+++ b/actionpack/lib/action_controller/metal/force_ssl.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "active_support/core_ext/hash/except"
require "active_support/core_ext/hash/slice"
@@ -37,7 +39,7 @@ module ActionController
# end
#
# ==== URL Options
- # You can pass any of the following options to affect the redirect url
+ # You can pass any of the following options to affect the redirect URL
# * <tt>host</tt> - Redirect to a different host name
# * <tt>subdomain</tt> - Redirect to a different subdomain
# * <tt>domain</tt> - Redirect to a different domain
@@ -71,7 +73,7 @@ module ActionController
# Redirect the existing request to use the HTTPS protocol.
#
# ==== Parameters
- # * <tt>host_or_options</tt> - Either a host name or any of the url and
+ # * <tt>host_or_options</tt> - Either a host name or any of the URL and
# redirect options available to the <tt>force_ssl</tt> method.
def force_ssl_redirect(host_or_options = nil)
unless request.ssl?
diff --git a/actionpack/lib/action_controller/metal/head.rb b/actionpack/lib/action_controller/metal/head.rb
index 0c50894bce..bac9bc5e5f 100644
--- a/actionpack/lib/action_controller/metal/head.rb
+++ b/actionpack/lib/action_controller/metal/head.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActionController
module Head
# Returns a response that has no content (merely headers). The options
diff --git a/actionpack/lib/action_controller/metal/helpers.rb b/actionpack/lib/action_controller/metal/helpers.rb
index 913a4b9a04..22c84e440b 100644
--- a/actionpack/lib/action_controller/metal/helpers.rb
+++ b/actionpack/lib/action_controller/metal/helpers.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActionController
# The \Rails framework provides a large number of helpers for working with assets, dates, forms,
# numbers and model objects, to name a few. These helpers are available to all templates
diff --git a/actionpack/lib/action_controller/metal/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb
index d8bc895265..01676f3237 100644
--- a/actionpack/lib/action_controller/metal/http_authentication.rb
+++ b/actionpack/lib/action_controller/metal/http_authentication.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "base64"
require "active_support/security_utils"
@@ -70,10 +72,10 @@ module ActionController
before_action(options.except(:name, :password, :realm)) do
authenticate_or_request_with_http_basic(options[:realm] || "Application") do |name, password|
# This comparison uses & so that it doesn't short circuit and
- # uses `variable_size_secure_compare` so that length information
+ # uses `secure_compare` so that length information
# isn't leaked.
- ActiveSupport::SecurityUtils.variable_size_secure_compare(name, options[:name]) &
- ActiveSupport::SecurityUtils.variable_size_secure_compare(password, options[:password])
+ ActiveSupport::SecurityUtils.secure_compare(name, options[:name]) &
+ ActiveSupport::SecurityUtils.secure_compare(password, options[:password])
end
end
end
@@ -246,7 +248,7 @@ module ActionController
def decode_credentials(header)
ActiveSupport::HashWithIndifferentAccess[header.to_s.gsub(/^Digest\s+/, "").split(",").map do |pair|
key, value = pair.split("=", 2)
- [key.strip, value.to_s.gsub(/^"|"$/, "").delete('\'')]
+ [key.strip, value.to_s.gsub(/^"|"$/, "").delete("'")]
end]
end
@@ -348,10 +350,7 @@ module ActionController
# authenticate_or_request_with_http_token do |token, options|
# # Compare the tokens in a time-constant manner, to mitigate
# # timing attacks.
- # ActiveSupport::SecurityUtils.secure_compare(
- # ::Digest::SHA256.hexdigest(token),
- # ::Digest::SHA256.hexdigest(TOKEN)
- # )
+ # ActiveSupport::SecurityUtils.secure_compare(token, TOKEN)
# end
# end
# end
@@ -475,7 +474,7 @@ module ActionController
# This removes the <tt>"</tt> characters wrapping the value.
def rewrite_param_values(array_params)
- array_params.each { |param| (param[1] || "").gsub! %r/^"|"$/, "" }
+ array_params.each { |param| (param[1] || "".dup).gsub! %r/^"|"$/, "" }
end
# This method takes an authorization body and splits up the key-value
diff --git a/actionpack/lib/action_controller/metal/implicit_render.rb b/actionpack/lib/action_controller/metal/implicit_render.rb
index eeb27f99f4..ac0c127cdc 100644
--- a/actionpack/lib/action_controller/metal/implicit_render.rb
+++ b/actionpack/lib/action_controller/metal/implicit_render.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActionController
# Handles implicit rendering for a controller action that does not
# explicitly respond with +render+, +respond_to+, +redirect+, or +head+.
diff --git a/actionpack/lib/action_controller/metal/instrumentation.rb b/actionpack/lib/action_controller/metal/instrumentation.rb
index 2485d27cec..be9449629f 100644
--- a/actionpack/lib/action_controller/metal/instrumentation.rb
+++ b/actionpack/lib/action_controller/metal/instrumentation.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "benchmark"
require "abstract_controller/logger"
@@ -81,16 +83,13 @@ module ActionController
# def cleanup_view_runtime
# super - time_taken_in_something_expensive
# end
- #
- # :api: plugin
- def cleanup_view_runtime
+ def cleanup_view_runtime # :doc:
yield
end
# Every time after an action is processed, this method is invoked
# with the payload, so you can add more information.
- # :api: plugin
- def append_info_to_payload(payload)
+ def append_info_to_payload(payload) # :doc:
payload[:view_runtime] = view_runtime
end
@@ -98,7 +97,6 @@ module ActionController
# A hook which allows other frameworks to log what happened during
# controller process action. This method should return an array
# with the messages to be added.
- # :api: plugin
def log_process_action(payload) #:nodoc:
messages, view_runtime = [], payload[:view_runtime]
messages << ("Views: %.1fms" % view_runtime.to_f) if view_runtime
diff --git a/actionpack/lib/action_controller/metal/live.rb b/actionpack/lib/action_controller/metal/live.rb
index a607ee2309..2f4c8fb83c 100644
--- a/actionpack/lib/action_controller/metal/live.rb
+++ b/actionpack/lib/action_controller/metal/live.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "action_dispatch/http/response"
require "delegate"
require "active_support/json"
@@ -295,7 +297,7 @@ module ActionController
return unless logger
logger.fatal do
- message = "\n#{exception.class} (#{exception.message}):\n"
+ message = "\n#{exception.class} (#{exception.message}):\n".dup
message << exception.annoted_source_code.to_s if exception.respond_to?(:annoted_source_code)
message << " " << exception.backtrace.join("\n ")
"#{message}\n\n"
diff --git a/actionpack/lib/action_controller/metal/mime_responds.rb b/actionpack/lib/action_controller/metal/mime_responds.rb
index 96bd548268..2233b93406 100644
--- a/actionpack/lib/action_controller/metal/mime_responds.rb
+++ b/actionpack/lib/action_controller/metal/mime_responds.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "abstract_controller/collector"
module ActionController #:nodoc:
diff --git a/actionpack/lib/action_controller/metal/parameter_encoding.rb b/actionpack/lib/action_controller/metal/parameter_encoding.rb
index ecc691619e..7a45732d31 100644
--- a/actionpack/lib/action_controller/metal/parameter_encoding.rb
+++ b/actionpack/lib/action_controller/metal/parameter_encoding.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActionController
# Specify binary encoding for parameters for a given action.
module ParameterEncoding
diff --git a/actionpack/lib/action_controller/metal/params_wrapper.rb b/actionpack/lib/action_controller/metal/params_wrapper.rb
index 68881b8402..a678377d4f 100644
--- a/actionpack/lib/action_controller/metal/params_wrapper.rb
+++ b/actionpack/lib/action_controller/metal/params_wrapper.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "active_support/core_ext/hash/slice"
require "active_support/core_ext/hash/except"
require "active_support/core_ext/module/anonymous"
@@ -110,6 +112,14 @@ module ActionController
else
self.include = m.attribute_names
end
+
+ if m.respond_to?(:nested_attributes_options) && m.nested_attributes_options.keys.any?
+ self.include += m.nested_attributes_options.keys.map do |key|
+ key.to_s.concat("_attributes")
+ end
+ end
+
+ self.include
end
end
end
@@ -232,12 +242,7 @@ module ActionController
# by the metal call stack.
def process_action(*args)
if _wrapper_enabled?
- if request.parameters[_wrapper_key].present?
- wrapped_hash = _extract_parameters(request.parameters)
- else
- wrapped_hash = _wrap_parameters request.request_parameters
- end
-
+ wrapped_hash = _wrap_parameters request.request_parameters
wrapped_keys = request.request_parameters.keys
wrapped_filtered_hash = _wrap_parameters request.filtered_parameters.slice(*wrapped_keys)
@@ -282,7 +287,7 @@ module ActionController
return false unless request.has_content_type?
ref = request.content_mime_type.ref
- _wrapper_formats.include?(ref) && _wrapper_key && !request.request_parameters[_wrapper_key]
+ _wrapper_formats.include?(ref) && _wrapper_key && !request.parameters.key?(_wrapper_key)
end
end
end
diff --git a/actionpack/lib/action_controller/metal/redirecting.rb b/actionpack/lib/action_controller/metal/redirecting.rb
index fdfe82f96b..4c2b5120eb 100644
--- a/actionpack/lib/action_controller/metal/redirecting.rb
+++ b/actionpack/lib/action_controller/metal/redirecting.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActionController
module Redirecting
extend ActiveSupport::Concern
@@ -29,7 +31,7 @@ module ActionController
# redirect_to post_url(@post), status: 301
# redirect_to action: 'atom', status: 302
#
- # The status code can either be a standard {HTTP Status code}[http://www.iana.org/assignments/http-status-codes] as an
+ # The status code can either be a standard {HTTP Status code}[https://www.iana.org/assignments/http-status-codes] as an
# integer, or a symbol representing the downcased, underscored and symbolized description.
# Note that the status code must be a 3xx HTTP code, or redirection will not occur.
#
@@ -66,7 +68,7 @@ module ActionController
# if possible, otherwise redirects to the provided default fallback
# location.
#
- # The referrer information is pulled from the HTTP `Referer` (sic) header on
+ # The referrer information is pulled from the HTTP +Referer+ (sic) header on
# the request. This is an optional header and its presence on the request is
# subject to browser security settings and user preferences. If the request
# is missing this header, the <tt>fallback_location</tt> will be used.
@@ -77,15 +79,18 @@ module ActionController
# redirect_back fallback_location: "/images/screenshot.jpg"
# redirect_back fallback_location: posts_url
# redirect_back fallback_location: proc { edit_post_url(@post) }
+ # redirect_back fallback_location: '/', allow_other_host: false
+ #
+ # ==== Options
+ # * <tt>:fallback_location</tt> - The default fallback location that will be used on missing +Referer+ header.
+ # * <tt>:allow_other_host</tt> - Allow or disallow redirection to the host that is different to the current host, defaults to true.
#
- # All options that can be passed to <tt>redirect_to</tt> are accepted as
+ # All other options that can be passed to <tt>redirect_to</tt> are accepted as
# options and the behavior is identical.
- def redirect_back(fallback_location:, **args)
- if referer = request.headers["Referer"]
- redirect_to referer, **args
- else
- redirect_to fallback_location, **args
- end
+ def redirect_back(fallback_location:, allow_other_host: true, **args)
+ referer = request.headers["Referer"]
+ redirect_to_referer = referer && (allow_other_host || _url_host_allowed?(referer))
+ redirect_to redirect_to_referer ? referer : fallback_location, **args
end
def _compute_redirect_to_location(request, options) #:nodoc:
@@ -93,7 +98,7 @@ module ActionController
# The scheme name consist of a letter followed by any combination of
# letters, digits, and the plus ("+"), period ("."), or hyphen ("-")
# characters; and is terminated by a colon (":").
- # See http://tools.ietf.org/html/rfc3986#section-3.1
+ # See https://tools.ietf.org/html/rfc3986#section-3.1
# The protocol relative scheme starts with a double slash "//".
when /\A([a-z][a-z\d\-+\.]*:|\/\/).*/i
options
@@ -118,5 +123,11 @@ module ActionController
302
end
end
+
+ def _url_host_allowed?(url)
+ URI(url.to_s).host == request.host
+ rescue ArgumentError, URI::Error
+ false
+ end
end
end
diff --git a/actionpack/lib/action_controller/metal/renderers.rb b/actionpack/lib/action_controller/metal/renderers.rb
index 23c21b0501..b81d3ef539 100644
--- a/actionpack/lib/action_controller/metal/renderers.rb
+++ b/actionpack/lib/action_controller/metal/renderers.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "set"
module ActionController
@@ -83,7 +85,7 @@ module ActionController
def self.remove(key)
RENDERERS.delete(key.to_sym)
method_name = _render_with_renderer_method_name(key)
- remove_method(method_name) if method_defined?(method_name)
+ remove_possible_method(method_name)
end
def self._render_with_renderer_method_name(key)
diff --git a/actionpack/lib/action_controller/metal/rendering.rb b/actionpack/lib/action_controller/metal/rendering.rb
index 67f207afc2..6d181e6456 100644
--- a/actionpack/lib/action_controller/metal/rendering.rb
+++ b/actionpack/lib/action_controller/metal/rendering.rb
@@ -1,4 +1,4 @@
-require "active_support/core_ext/string/filters"
+# frozen_string_literal: true
module ActionController
module Rendering
@@ -40,7 +40,7 @@ module ActionController
def render_to_string(*)
result = super
if result.respond_to?(:each)
- string = ""
+ string = "".dup
result.each { |r| string << r }
string
else
diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
index 5051c02a62..0ab313e398 100644
--- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb
+++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
@@ -1,6 +1,9 @@
+# frozen_string_literal: true
+
require "rack/session/abstract/id"
require "action_controller/metal/exceptions"
require "active_support/security_utils"
+require "active_support/core_ext/string/strip"
module ActionController #:nodoc:
class InvalidAuthenticityToken < ActionControllerError #:nodoc:
@@ -20,7 +23,7 @@ module ActionController #:nodoc:
# Since HTML and JavaScript requests are typically made from the browser, we
# need to ensure to verify request authenticity for the web browser. We can
# use session-oriented authentication for these types of requests, by using
- # the `protect_from_forgery` method in our controllers.
+ # the <tt>protect_from_forgery</tt> method in our controllers.
#
# GET requests are not protected since they don't have side effects like writing
# to the database and don't leak sensitive information. JavaScript requests are
@@ -85,6 +88,10 @@ module ActionController #:nodoc:
config_accessor :per_form_csrf_tokens
self.per_form_csrf_tokens = false
+ # Controls whether forgery protection is enabled by default.
+ config_accessor :default_protect_from_forgery
+ self.default_protect_from_forgery = false
+
helper_method :form_authenticity_token
helper_method :protect_against_forgery?
end
@@ -128,6 +135,15 @@ module ActionController #:nodoc:
append_after_action :verify_same_origin_request
end
+ # Turn off request forgery protection. This is a wrapper for:
+ #
+ # skip_before_action :verify_authenticity_token
+ #
+ # See +skip_before_action+ for allowed options.
+ def skip_forgery_protection(options = {})
+ skip_before_action :verify_authenticity_token, options
+ end
+
private
def protection_method_class(name)
@@ -201,7 +217,7 @@ module ActionController #:nodoc:
# The actual before_action that is used to verify the CSRF token.
# Don't override this directly. Provide your own forgery protection
# strategy instead. If you override, you'll disable same-origin
- # `<script>` verification.
+ # <tt><script></tt> verification.
#
# Lean on the protect_from_forgery declaration to mark which actions are
# due for same-origin request verification. If protect_from_forgery is
@@ -233,8 +249,9 @@ module ActionController #:nodoc:
"If you know what you're doing, go ahead and disable forgery " \
"protection on this action to permit cross-origin JavaScript embedding."
private_constant :CROSS_ORIGIN_JAVASCRIPT_WARNING
+ # :startdoc:
- # If `verify_authenticity_token` was run (indicating that we have
+ # If +verify_authenticity_token+ was run (indicating that we have
# forgery protection enabled for this request) then also verify that
# we aren't serving an unauthorized cross-origin response.
def verify_same_origin_request # :doc:
@@ -251,7 +268,7 @@ module ActionController #:nodoc:
@marked_for_same_origin_verification = request.get?
end
- # If the `verify_authenticity_token` before_action ran, verify that
+ # If the +verify_authenticity_token+ before_action ran, verify that
# JavaScript responses are only served to same-origin GET requests.
def marked_for_same_origin_verification? # :doc:
@marked_for_same_origin_verification ||= false
@@ -353,7 +370,7 @@ module ActionController #:nodoc:
end
def compare_with_real_token(token, session) # :doc:
- ActiveSupport::SecurityUtils.secure_compare(token, real_csrf_token(session))
+ ActiveSupport::SecurityUtils.fixed_length_secure_compare(token, real_csrf_token(session))
end
def valid_per_form_csrf_token?(token, session) # :doc:
@@ -364,7 +381,7 @@ module ActionController #:nodoc:
request.request_method
)
- ActiveSupport::SecurityUtils.secure_compare(token, correct_token)
+ ActiveSupport::SecurityUtils.fixed_length_secure_compare(token, correct_token)
else
false
end
@@ -399,11 +416,21 @@ module ActionController #:nodoc:
allow_forgery_protection
end
+ NULL_ORIGIN_MESSAGE = <<-MSG.strip_heredoc
+ The browser returned a 'null' origin for a request with origin-based forgery protection turned on. This usually
+ means you have the 'no-referrer' Referrer-Policy header enabled, or that you the request came from a site that
+ refused to give its origin. This makes it impossible for Rails to verify the source of the requests. Likely the
+ best solution is to change your referrer policy to something less strict like same-origin or strict-same-origin.
+ If you cannot change the referrer policy, you can disable origin checking with the
+ Rails.application.config.action_controller.forgery_protection_origin_check setting.
+ MSG
+
# Checks if the request originated from the same origin by looking at the
# Origin header.
def valid_request_origin? # :doc:
if forgery_protection_origin_check
# We accept blank origin headers because some user agents don't send it.
+ raise InvalidAuthenticityToken, NULL_ORIGIN_MESSAGE if request.origin == "null"
request.origin.nil? || request.origin == request.base_url
else
true
diff --git a/actionpack/lib/action_controller/metal/rescue.rb b/actionpack/lib/action_controller/metal/rescue.rb
index 25757938f5..44f7fb7a07 100644
--- a/actionpack/lib/action_controller/metal/rescue.rb
+++ b/actionpack/lib/action_controller/metal/rescue.rb
@@ -1,5 +1,7 @@
+# frozen_string_literal: true
+
module ActionController #:nodoc:
- # This module is responsible for providing `rescue_from` helpers
+ # This module is responsible for providing +rescue_from+ helpers
# to controllers and configuring when detailed exceptions must be
# shown.
module Rescue
@@ -8,8 +10,8 @@ module ActionController #:nodoc:
# Override this method if you want to customize when detailed
# exceptions must be shown. This method is only called when
- # consider_all_requests_local is false. By default, it returns
- # false, but someone may set it to `request.local?` so local
+ # +consider_all_requests_local+ is +false+. By default, it returns
+ # +false+, but someone may set it to <tt>request.local?</tt> so local
# requests in production still show the detailed exception pages.
def show_detailed_exceptions?
false
diff --git a/actionpack/lib/action_controller/metal/streaming.rb b/actionpack/lib/action_controller/metal/streaming.rb
index 58cf60ad2a..8dc01a5eb9 100644
--- a/actionpack/lib/action_controller/metal/streaming.rb
+++ b/actionpack/lib/action_controller/metal/streaming.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rack/chunked"
module ActionController #:nodoc:
@@ -181,7 +183,7 @@ module ActionController #:nodoc:
# unicorn_rails --config-file unicorn.config.rb
#
# You may also want to configure other parameters like <tt>:tcp_nodelay</tt>.
- # Please check its documentation for more information: http://unicorn.bogomips.org/Unicorn/Configurator.html#method-i-listen
+ # Please check its documentation for more information: https://bogomips.org/unicorn/Unicorn/Configurator.html#method-i-listen
#
# If you are using Unicorn with NGINX, you may need to tweak NGINX.
# Streaming should work out of the box on Rainbows.
diff --git a/actionpack/lib/action_controller/metal/strong_parameters.rb b/actionpack/lib/action_controller/metal/strong_parameters.rb
index 4a60e2eff2..a56ac749f8 100644
--- a/actionpack/lib/action_controller/metal/strong_parameters.rb
+++ b/actionpack/lib/action_controller/metal/strong_parameters.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "active_support/core_ext/hash/indifferent_access"
require "active_support/core_ext/hash/transform_values"
require "active_support/core_ext/array/wrap"
@@ -180,6 +182,14 @@ module ActionController
# Returns a new array of the keys of the parameters.
##
+ # :method: to_s
+ #
+ # :call-seq:
+ # to_s()
+ #
+ # Returns the content of the parameters as a string.
+
+ ##
# :method: value?
#
# :call-seq:
@@ -195,7 +205,7 @@ module ActionController
#
# Returns a new array of the values of the parameters.
delegate :keys, :key?, :has_key?, :values, :has_value?, :value?, :empty?, :include?,
- :as_json, to: :@parameters
+ :as_json, :to_s, to: :@parameters
# By default, never raise an UnpermittedParameters exception if these
# params are present. The default includes both 'controller' and 'action'
@@ -245,7 +255,7 @@ module ActionController
# oddity: "Heavy stone crab"
# })
# params.to_h
- # # => ActionController::UnfilteredParameters: unable to convert unfiltered parameters to hash
+ # # => ActionController::UnfilteredParameters: unable to convert unpermitted parameters to hash
#
# safe_params = params.permit(:name)
# safe_params.to_h # => {"name"=>"Senjougahara Hitagi"}
@@ -265,7 +275,7 @@ module ActionController
# oddity: "Heavy stone crab"
# })
# params.to_hash
- # # => ActionController::UnfilteredParameters: unable to convert unfiltered parameters to hash
+ # # => ActionController::UnfilteredParameters: unable to convert unpermitted parameters to hash
#
# safe_params = params.permit(:name)
# safe_params.to_hash # => {"name"=>"Senjougahara Hitagi"}
@@ -325,7 +335,7 @@ module ActionController
# the same way as <tt>Hash#each_pair</tt>.
def each_pair(&block)
@parameters.each_pair do |key, value|
- yield key, convert_hashes_to_parameters(key, value)
+ yield [key, convert_hashes_to_parameters(key, value)]
end
end
alias_method :each, :each_pair
@@ -665,10 +675,10 @@ module ActionController
self
end
- # Deletes and returns a key-value pair from +Parameters+ whose key is equal
- # to key. If the key is not found, returns the default value. If the
- # optional code block is given and the key is not found, pass in the key
- # and return the result of block.
+ # 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
+ # corresponding +ActionController::Parameters+ object.
def delete(key, &block)
convert_value_to_parameters(@parameters.delete(key, &block))
end
diff --git a/actionpack/lib/action_controller/metal/testing.rb b/actionpack/lib/action_controller/metal/testing.rb
index 9bb416178a..6e8a95040f 100644
--- a/actionpack/lib/action_controller/metal/testing.rb
+++ b/actionpack/lib/action_controller/metal/testing.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActionController
module Testing
extend ActiveSupport::Concern
@@ -10,11 +12,5 @@ module ActionController
self.params = nil
end
end
-
- module ClassMethods
- def before_filters
- _process_action_callbacks.find_all { |x| x.kind == :before }.map(&:name)
- end
- end
end
end
diff --git a/actionpack/lib/action_controller/metal/url_for.rb b/actionpack/lib/action_controller/metal/url_for.rb
index 21ed5b4ec8..84dbb59a63 100644
--- a/actionpack/lib/action_controller/metal/url_for.rb
+++ b/actionpack/lib/action_controller/metal/url_for.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActionController
# Includes +url_for+ into the host class. The class has to provide a +RouteSet+ by implementing
# the <tt>_routes</tt> method. Otherwise, an exception will be raised.
diff --git a/actionpack/lib/action_controller/railtie.rb b/actionpack/lib/action_controller/railtie.rb
index fadfc8de60..7d42f5d931 100644
--- a/actionpack/lib/action_controller/railtie.rb
+++ b/actionpack/lib/action_controller/railtie.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails"
require "action_controller"
require "action_dispatch/railtie"
@@ -22,13 +24,15 @@ module ActionController
initializer "action_controller.parameters_config" do |app|
options = app.config.action_controller
- ActionController::Parameters.permit_all_parameters = options.delete(:permit_all_parameters) { false }
- if app.config.action_controller[:always_permitted_parameters]
- ActionController::Parameters.always_permitted_parameters =
- app.config.action_controller.delete(:always_permitted_parameters)
- end
- ActionController::Parameters.action_on_unpermitted_parameters = options.delete(:action_on_unpermitted_parameters) do
- (Rails.env.test? || Rails.env.development?) ? :log : false
+ ActiveSupport.on_load(:action_controller, run_once: true) do
+ ActionController::Parameters.permit_all_parameters = options.delete(:permit_all_parameters) { false }
+ if app.config.action_controller[:always_permitted_parameters]
+ ActionController::Parameters.always_permitted_parameters =
+ app.config.action_controller.delete(:always_permitted_parameters)
+ end
+ ActionController::Parameters.action_on_unpermitted_parameters = options.delete(:action_on_unpermitted_parameters) do
+ (Rails.env.test? || Rails.env.development?) ? :log : false
+ end
end
end
@@ -67,5 +71,19 @@ module ActionController
config.compile_methods! if config.respond_to?(:compile_methods!)
end
end
+
+ initializer "action_controller.request_forgery_protection" do |app|
+ ActiveSupport.on_load(:action_controller_base) do
+ if app.config.action_controller.default_protect_from_forgery
+ protect_from_forgery with: :exception
+ end
+ end
+ end
+
+ initializer "action_controller.eager_load_actions" do
+ ActiveSupport.on_load(:after_initialize) do
+ ActionController::Metal.descendants.each(&:action_methods) if config.eager_load
+ end
+ end
end
end
diff --git a/actionpack/lib/action_controller/railties/helpers.rb b/actionpack/lib/action_controller/railties/helpers.rb
index 3985c6b273..fa746fa9e8 100644
--- a/actionpack/lib/action_controller/railties/helpers.rb
+++ b/actionpack/lib/action_controller/railties/helpers.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActionController
module Railties
module Helpers
diff --git a/actionpack/lib/action_controller/renderer.rb b/actionpack/lib/action_controller/renderer.rb
index cbb719d8b2..49c5b782f0 100644
--- a/actionpack/lib/action_controller/renderer.rb
+++ b/actionpack/lib/action_controller/renderer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "active_support/core_ext/hash/keys"
module ActionController
diff --git a/actionpack/lib/action_controller/template_assertions.rb b/actionpack/lib/action_controller/template_assertions.rb
index 0179f4afcd..dd83c1a283 100644
--- a/actionpack/lib/action_controller/template_assertions.rb
+++ b/actionpack/lib/action_controller/template_assertions.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActionController
module TemplateAssertions
def assert_template(options = {}, message = nil)
diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb
index bc42d50205..798d142755 100644
--- a/actionpack/lib/action_controller/test_case.rb
+++ b/actionpack/lib/action_controller/test_case.rb
@@ -1,7 +1,10 @@
+# frozen_string_literal: true
+
require "rack/session/abstract/id"
require "active_support/core_ext/hash/conversions"
require "active_support/core_ext/object/to_query"
require "active_support/core_ext/module/anonymous"
+require "active_support/core_ext/module/redefine_method"
require "active_support/core_ext/hash/keys"
require "active_support/testing/constant_lookup"
require "action_controller/template_assertions"
@@ -17,7 +20,7 @@ module ActionController
# the database on the main thread, so they could open a txn, then the
# controller thread will open a new connection and try to access data
# that's only visible to the main thread's txn. This is the problem in #23483.
- remove_method :new_controller_thread
+ silence_redefinition_of_method :new_controller_thread
def new_controller_thread # :nodoc:
yield
end
@@ -253,7 +256,7 @@ module ActionController
#
# def test_create
# json = {book: { title: "Love Hina" }}.to_json
- # post :create, json
+ # post :create, body: json
# end
#
# == Special instance variables