aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib')
-rw-r--r--actionpack/lib/abstract_controller/base.rb4
-rw-r--r--actionpack/lib/abstract_controller/caching/fragments.rb8
-rw-r--r--actionpack/lib/action_controller/metal/conditional_get.rb6
-rw-r--r--actionpack/lib/action_controller/metal/force_ssl.rb4
-rw-r--r--actionpack/lib/action_controller/metal/helpers.rb3
-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/redirecting.rb2
-rw-r--r--actionpack/lib/action_controller/metal/request_forgery_protection.rb15
-rw-r--r--actionpack/lib/action_controller/metal/strong_parameters.rb50
-rw-r--r--actionpack/lib/action_controller/renderer.rb2
-rw-r--r--actionpack/lib/action_dispatch/http/mime_negotiation.rb5
-rw-r--r--actionpack/lib/action_dispatch/http/parameter_filter.rb17
-rw-r--r--actionpack/lib/action_dispatch/middleware/cookies.rb42
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/routes/_table.html.erb3
-rw-r--r--actionpack/lib/action_dispatch/railtie.rb1
-rw-r--r--actionpack/lib/action_dispatch/request/utils.rb2
-rw-r--r--actionpack/lib/action_dispatch/routing/inspector.rb2
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb4
-rw-r--r--actionpack/lib/action_dispatch/testing/test_process.rb4
20 files changed, 121 insertions, 61 deletions
diff --git a/actionpack/lib/abstract_controller/base.rb b/actionpack/lib/abstract_controller/base.rb
index a312af6715..6e6786d0be 100644
--- a/actionpack/lib/abstract_controller/base.rb
+++ b/actionpack/lib/abstract_controller/base.rb
@@ -78,7 +78,9 @@ module AbstractController
# Except for public instance methods of Base and its ancestors
internal_methods +
# Be sure to include shadowed public instance methods of this class
- public_instance_methods(false)).uniq.map(&:to_s)
+ public_instance_methods(false))
+
+ methods.map!(&:to_s)
methods.to_set
end
diff --git a/actionpack/lib/abstract_controller/caching/fragments.rb b/actionpack/lib/abstract_controller/caching/fragments.rb
index f99b0830b2..95078a2a28 100644
--- a/actionpack/lib/abstract_controller/caching/fragments.rb
+++ b/actionpack/lib/abstract_controller/caching/fragments.rb
@@ -82,13 +82,17 @@ module AbstractController
# Given a key (as described in +expire_fragment+), returns
# a key array suitable for use in reading, writing, or expiring a
# cached fragment. All keys begin with <tt>:views</tt>,
- # followed by ENV["RAILS_CACHE_ID"] or ENV["RAILS_APP_VERSION"] if set,
+ # followed by <tt>ENV["RAILS_CACHE_ID"]</tt> or <tt>ENV["RAILS_APP_VERSION"]</tt> if set,
# followed by any controller-wide key prefix values, ending
# with the specified +key+ value.
def combined_fragment_cache_key(key)
head = self.class.fragment_cache_keys.map { |k| instance_exec(&k) }
tail = key.is_a?(Hash) ? url_for(key).split("://").last : key
- [ :views, (ENV["RAILS_CACHE_ID"] || ENV["RAILS_APP_VERSION"]), *head, *tail ].compact
+
+ cache_key = [:views, ENV["RAILS_CACHE_ID"] || ENV["RAILS_APP_VERSION"], head, tail]
+ cache_key.flatten!(1)
+ cache_key.compact!
+ cache_key
end
# Writes +content+ to the location signified by
diff --git a/actionpack/lib/action_controller/metal/conditional_get.rb b/actionpack/lib/action_controller/metal/conditional_get.rb
index 4be4557e2c..d6911ee2b5 100644
--- a/actionpack/lib/action_controller/metal/conditional_get.rb
+++ b/actionpack/lib/action_controller/metal/conditional_get.rb
@@ -230,6 +230,12 @@ module ActionController
# This method will overwrite an existing Cache-Control header.
# See https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html for more possibilities.
#
+ # HTTP Cache-Control Extensions for Stale Content. See https://tools.ietf.org/html/rfc5861
+ # It helps to cache an asset and serve it while is being revalidated and/or returning with an error.
+ #
+ # expires_in 3.hours, public: true, stale_while_revalidate: 60.seconds
+ # expires_in 3.hours, public: true, stale_while_revalidate: 60.seconds, stale_if_error: 5.minutes
+ #
# The method will also ensure an HTTP Date header for client compatibility.
def expires_in(seconds, options = {})
response.cache_control.merge!(
diff --git a/actionpack/lib/action_controller/metal/force_ssl.rb b/actionpack/lib/action_controller/metal/force_ssl.rb
index 8d53a30e93..26e6f72b66 100644
--- a/actionpack/lib/action_controller/metal/force_ssl.rb
+++ b/actionpack/lib/action_controller/metal/force_ssl.rb
@@ -5,8 +5,8 @@ require "active_support/core_ext/hash/slice"
module ActionController
# This module is deprecated in favor of +config.force_ssl+ in your environment
- # config file. This will ensure all communication to non-whitelisted endpoints
- # served by your application occurs over HTTPS.
+ # config file. This will ensure all endpoints not explicitly marked otherwise
+ # will have all communication served over HTTPS.
module ForceSSL # :nodoc:
extend ActiveSupport::Concern
include AbstractController::Callbacks
diff --git a/actionpack/lib/action_controller/metal/helpers.rb b/actionpack/lib/action_controller/metal/helpers.rb
index 22c84e440b..0faaac1ce4 100644
--- a/actionpack/lib/action_controller/metal/helpers.rb
+++ b/actionpack/lib/action_controller/metal/helpers.rb
@@ -100,8 +100,7 @@ module ActionController
# # => ["application", "chart", "rubygems"]
def all_helpers_from_path(path)
helpers = Array(path).flat_map do |_path|
- extract = /^#{Regexp.quote(_path.to_s)}\/?(.*)_helper.rb$/
- names = Dir["#{_path}/**/*_helper.rb"].map { |file| file.sub(extract, '\1'.freeze) }
+ names = Dir["#{_path}/**/*_helper.rb"].map { |file| file[_path.to_s.size + 1..-"_helper.rb".size - 1] }
names.sort!
end
helpers.uniq!
diff --git a/actionpack/lib/action_controller/metal/live.rb b/actionpack/lib/action_controller/metal/live.rb
index 2f4c8fb83c..b1c2391afe 100644
--- a/actionpack/lib/action_controller/metal/live.rb
+++ b/actionpack/lib/action_controller/metal/live.rb
@@ -86,7 +86,7 @@ module ActionController
# Note: SSEs are not currently supported by IE. However, they are supported
# by Chrome, Firefox, Opera, and Safari.
class SSE
- WHITELISTED_OPTIONS = %w( retry event id )
+ PERMITTED_OPTIONS = %w( retry event id )
def initialize(stream, options = {})
@stream = stream
@@ -111,7 +111,7 @@ module ActionController
def perform_write(json, options)
current_options = @options.merge(options).stringify_keys
- WHITELISTED_OPTIONS.each do |option_name|
+ PERMITTED_OPTIONS.each do |option_name|
if (option_value = current_options[option_name])
@stream.write "#{option_name}: #{option_value}\n"
end
diff --git a/actionpack/lib/action_controller/metal/mime_responds.rb b/actionpack/lib/action_controller/metal/mime_responds.rb
index 2b55b9347c..118da11990 100644
--- a/actionpack/lib/action_controller/metal/mime_responds.rb
+++ b/actionpack/lib/action_controller/metal/mime_responds.rb
@@ -11,7 +11,7 @@ module ActionController #:nodoc:
# @people = Person.all
# end
#
- # That action implicitly responds to all formats, but formats can also be whitelisted:
+ # That action implicitly responds to all formats, but formats can also be explicitly enumerated:
#
# def index
# @people = Person.all
@@ -105,7 +105,7 @@ module ActionController #:nodoc:
#
# Mime::Type.register "image/jpg", :jpg
#
- # Respond to also allows you to specify a common block for different formats by using +any+:
+ # +respond_to+ also allows you to specify a common block for different formats by using +any+:
#
# def index
# @people = Person.all
diff --git a/actionpack/lib/action_controller/metal/redirecting.rb b/actionpack/lib/action_controller/metal/redirecting.rb
index 4c2b5120eb..2804a06a58 100644
--- a/actionpack/lib/action_controller/metal/redirecting.rb
+++ b/actionpack/lib/action_controller/metal/redirecting.rb
@@ -105,7 +105,7 @@ module ActionController
when String
request.protocol + request.host_with_port + options
when Proc
- _compute_redirect_to_location request, options.call
+ _compute_redirect_to_location request, instance_eval(&options)
else
url_for(options)
end.delete("\0\r\n")
diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
index edfef39771..cb109c6ad8 100644
--- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb
+++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
@@ -17,7 +17,7 @@ module ActionController #:nodoc:
# access. When a request reaches your application, \Rails verifies the received
# token with the token in the session. All requests are checked except GET requests
# as these should be idempotent. Keep in mind that all session-oriented requests
- # should be CSRF protected, including JavaScript and HTML requests.
+ # are CSRF protected by default, including JavaScript and HTML requests.
#
# 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
@@ -30,16 +30,23 @@ module ActionController #:nodoc:
# URL on your site. When your JavaScript response loads on their site, it executes.
# With carefully crafted JavaScript on their end, sensitive data in your JavaScript
# response may be extracted. To prevent this, only XmlHttpRequest (known as XHR or
- # Ajax) requests are allowed to make GET requests for JavaScript responses.
+ # Ajax) requests are allowed to make requests for JavaScript responses.
#
- # It's important to remember that XML or JSON requests are also affected and if
- # you're building an API you should change forgery protection method in
+ # It's important to remember that XML or JSON requests are also checked by default. If
+ # you're building an API or an SPA you could change forgery protection method in
# <tt>ApplicationController</tt> (by default: <tt>:exception</tt>):
#
# class ApplicationController < ActionController::Base
# protect_from_forgery unless: -> { request.format.json? }
# end
#
+ # It is generally safe to exclude XHR requests from CSRF protection
+ # (like the code snippet above does), because XHR requests can only be made from
+ # the same origin. Note however that any cross-origin third party domain
+ # allowed via {CORS}[https://en.wikipedia.org/wiki/Cross-origin_resource_sharing]
+ # will also be able to create XHR requests. Be sure to check your
+ # CORS configuration before disabling forgery protection for XHR.
+ #
# CSRF protection is turned on with the <tt>protect_from_forgery</tt> method.
# By default <tt>protect_from_forgery</tt> protects your session with
# <tt>:null_session</tt> method, which provides an empty session
diff --git a/actionpack/lib/action_controller/metal/strong_parameters.rb b/actionpack/lib/action_controller/metal/strong_parameters.rb
index 7af29f8dca..a37f08d944 100644
--- a/actionpack/lib/action_controller/metal/strong_parameters.rb
+++ b/actionpack/lib/action_controller/metal/strong_parameters.rb
@@ -58,7 +58,7 @@ module ActionController
# == Action Controller \Parameters
#
- # Allows you to choose which attributes should be whitelisted for mass updating
+ # Allows you to choose which attributes should be permitted for mass updating
# and thus prevent accidentally exposing that which shouldn't be exposed.
# Provides two methods for this purpose: #require and #permit. The former is
# used to mark parameters as required. The latter is used to set the parameter
@@ -133,6 +133,15 @@ module ActionController
# Returns a hash that can be used as the JSON representation for the parameters.
##
+ # :method: each_key
+ #
+ # :call-seq:
+ # each_key()
+ #
+ # Calls block once for each key in the parameters, passing the key.
+ # If no block is given, an enumerator is returned instead.
+
+ ##
# :method: empty?
#
# :call-seq:
@@ -204,7 +213,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_s, to: :@parameters
+ :as_json, :to_s, :each_key, to: :@parameters
# By default, never raise an UnpermittedParameters exception if these
# params are present. The default includes both 'controller' and 'action'
@@ -505,7 +514,7 @@ module ActionController
#
# Note that if you use +permit+ in a key that points to a hash,
# it won't allow all the hash. You also need to specify which
- # attributes inside the hash should be whitelisted.
+ # attributes inside the hash should be permitted.
#
# params = ActionController::Parameters.new({
# person: {
@@ -904,15 +913,28 @@ module ActionController
PERMITTED_SCALAR_TYPES.any? { |type| value.is_a?(type) }
end
- def permitted_scalar_filter(params, key)
- if has_key?(key) && permitted_scalar?(self[key])
- params[key] = self[key]
+ # Adds existing keys to the params if their values are scalar.
+ #
+ # For example:
+ #
+ # puts self.keys #=> ["zipcode(90210i)"]
+ # params = {}
+ #
+ # permitted_scalar_filter(params, "zipcode")
+ #
+ # puts params.keys # => ["zipcode"]
+ def permitted_scalar_filter(params, permitted_key)
+ permitted_key = permitted_key.to_s
+
+ if has_key?(permitted_key) && permitted_scalar?(self[permitted_key])
+ params[permitted_key] = self[permitted_key]
end
- keys.grep(/\A#{Regexp.escape(key)}\(\d+[if]?\)\z/) do |k|
- if permitted_scalar?(self[k])
- params[k] = self[k]
- end
+ each_key do |key|
+ next unless key =~ /\(\d+[if]?\)\z/
+ next unless $~.pre_match == permitted_key
+
+ params[key] = self[key] if permitted_scalar?(self[key])
end
end
@@ -997,8 +1019,8 @@ module ActionController
#
# It provides an interface for protecting attributes from end-user
# assignment. This makes Action Controller parameters forbidden
- # to be used in Active Model mass assignment until they have been
- # whitelisted.
+ # to be used in Active Model mass assignment until they have been explicitly
+ # enumerated.
#
# In addition, parameters can be marked as required and flow through a
# predefined raise/rescue flow to end up as a <tt>400 Bad Request</tt> with no
@@ -1034,7 +1056,7 @@ module ActionController
# end
#
# In order to use <tt>accepts_nested_attributes_for</tt> with Strong \Parameters, you
- # will need to specify which nested attributes should be whitelisted. You might want
+ # will need to specify which nested attributes should be permitted. You might want
# to allow +:id+ and +:_destroy+, see ActiveRecord::NestedAttributes for more information.
#
# class Person
@@ -1052,7 +1074,7 @@ module ActionController
# private
#
# def person_params
- # # It's mandatory to specify the nested attributes that should be whitelisted.
+ # # It's mandatory to specify the nested attributes that should be permitted.
# # If you use `permit` with just the key that points to the nested attributes hash,
# # it will return an empty hash.
# params.require(:person).permit(:name, :age, pets_attributes: [ :id, :name, :category ])
diff --git a/actionpack/lib/action_controller/renderer.rb b/actionpack/lib/action_controller/renderer.rb
index 2d1523f0fc..2b4559c760 100644
--- a/actionpack/lib/action_controller/renderer.rb
+++ b/actionpack/lib/action_controller/renderer.rb
@@ -81,7 +81,7 @@ module ActionController
# * <tt>:html</tt> - Renders the provided HTML safe string, otherwise
# performs HTML escape on the string first. Sets the content type as <tt>text/html</tt>.
# * <tt>:json</tt> - Renders the provided hash or object in JSON. You don't
- # need to call <tt>.to_json<tt> on the object you want to render.
+ # need to call <tt>.to_json</tt> on the object you want to render.
# * <tt>:body</tt> - Renders provided text and sets content type of <tt>text/plain</tt>.
#
# If no <tt>options</tt> hash is passed or if <tt>:update</tt> is specified, the default is
diff --git a/actionpack/lib/action_dispatch/http/mime_negotiation.rb b/actionpack/lib/action_dispatch/http/mime_negotiation.rb
index d7435fa8df..be129965d1 100644
--- a/actionpack/lib/action_dispatch/http/mime_negotiation.rb
+++ b/actionpack/lib/action_dispatch/http/mime_negotiation.rb
@@ -85,10 +85,7 @@ module ActionDispatch
if variant.all? { |v| v.is_a?(Symbol) }
@variant = ActiveSupport::ArrayInquirer.new(variant)
else
- raise ArgumentError, "request.variant must be set to a Symbol or an Array of Symbols. " \
- "For security reasons, never directly set the variant to a user-provided value, " \
- "like params[:variant].to_sym. Check user-provided value against a whitelist first, " \
- "then set the variant: request.variant = :tablet if params[:variant] == 'tablet'"
+ raise ArgumentError, "request.variant must be set to a Symbol or an Array of Symbols."
end
end
diff --git a/actionpack/lib/action_dispatch/http/parameter_filter.rb b/actionpack/lib/action_dispatch/http/parameter_filter.rb
index 1d58964862..09aab631ed 100644
--- a/actionpack/lib/action_dispatch/http/parameter_filter.rb
+++ b/actionpack/lib/action_dispatch/http/parameter_filter.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
require "active_support/core_ext/object/duplicable"
+require "active_support/core_ext/array/extract"
module ActionDispatch
module Http
@@ -38,8 +39,8 @@ module ActionDispatch
end
end
- deep_regexps, regexps = regexps.partition { |r| r.to_s.include?("\\.".freeze) }
- deep_strings, strings = strings.partition { |s| s.include?("\\.".freeze) }
+ deep_regexps = regexps.extract! { |r| r.to_s.include?("\\.".freeze) }
+ deep_strings = strings.extract! { |s| s.include?("\\.".freeze) }
regexps << Regexp.new(strings.join("|".freeze), true) unless strings.empty?
deep_regexps << Regexp.new(deep_strings.join("|".freeze), true) unless deep_strings.empty?
@@ -55,23 +56,23 @@ module ActionDispatch
@blocks = blocks
end
- def call(original_params, parents = [])
- filtered_params = original_params.class.new
+ def call(params, parents = [], original_params = params)
+ filtered_params = params.class.new
- original_params.each do |key, value|
+ params.each do |key, value|
parents.push(key) if deep_regexps
if regexps.any? { |r| key =~ r }
value = FILTERED
elsif deep_regexps && (joined = parents.join(".")) && deep_regexps.any? { |r| joined =~ r }
value = FILTERED
elsif value.is_a?(Hash)
- value = call(value, parents)
+ value = call(value, parents, original_params)
elsif value.is_a?(Array)
- value = value.map { |v| v.is_a?(Hash) ? call(v, parents) : v }
+ value = value.map { |v| v.is_a?(Hash) ? call(v, parents, original_params) : v }
elsif blocks.any?
key = key.dup if key.duplicable?
value = value.dup if value.duplicable?
- blocks.each { |b| b.call(key, value) }
+ blocks.each { |b| b.arity == 2 ? b.call(key, value) : b.call(key, value, original_params) }
end
parents.pop if deep_regexps
diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb
index c45d947904..34331b7e4b 100644
--- a/actionpack/lib/action_dispatch/middleware/cookies.rb
+++ b/actionpack/lib/action_dispatch/middleware/cookies.rb
@@ -81,6 +81,10 @@ module ActionDispatch
get_header Cookies::COOKIES_ROTATIONS
end
+ def use_cookies_with_metadata
+ get_header Cookies::USE_COOKIES_WITH_METADATA
+ end
+
# :startdoc:
end
@@ -182,6 +186,7 @@ module ActionDispatch
COOKIES_SERIALIZER = "action_dispatch.cookies_serializer".freeze
COOKIES_DIGEST = "action_dispatch.cookies_digest".freeze
COOKIES_ROTATIONS = "action_dispatch.cookies_rotations".freeze
+ USE_COOKIES_WITH_METADATA = "action_dispatch.use_cookies_with_metadata".freeze
# Cookies can typically store 4096 bytes.
MAX_COOKIE_SIZE = 4096
@@ -470,7 +475,7 @@ module ActionDispatch
def [](name)
if data = @parent_jar[name.to_s]
- parse name, data
+ parse(name, data, purpose: "cookie.#{name}") || parse(name, data)
end
end
@@ -481,7 +486,7 @@ module ActionDispatch
options = { value: options }
end
- commit(options)
+ commit(name, options)
@parent_jar[name] = options
end
@@ -497,13 +502,24 @@ module ActionDispatch
end
end
- def parse(name, data); data; end
- def commit(options); end
+ def cookie_metadata(name, options)
+ if request.use_cookies_with_metadata
+ metadata = expiry_options(options)
+ metadata[:purpose] = "cookie.#{name}"
+
+ metadata
+ else
+ {}
+ end
+ end
+
+ def parse(name, data, purpose: nil); data; end
+ def commit(name, options); end
end
class PermanentCookieJar < AbstractCookieJar # :nodoc:
private
- def commit(options)
+ def commit(name, options)
options[:expires] = 20.years.from_now
end
end
@@ -583,14 +599,14 @@ module ActionDispatch
end
private
- def parse(name, signed_message)
+ def parse(name, signed_message, purpose: nil)
deserialize(name) do |rotate|
- @verifier.verified(signed_message, on_rotation: rotate)
+ @verifier.verified(signed_message, on_rotation: rotate, purpose: purpose)
end
end
- def commit(options)
- options[:value] = @verifier.generate(serialize(options[:value]), expiry_options(options))
+ def commit(name, options)
+ options[:value] = @verifier.generate(serialize(options[:value]), cookie_metadata(name, options))
raise CookieOverflow if options[:value].bytesize > MAX_COOKIE_SIZE
end
@@ -631,16 +647,16 @@ module ActionDispatch
end
private
- def parse(name, encrypted_message)
+ def parse(name, encrypted_message, purpose: nil)
deserialize(name) do |rotate|
- @encryptor.decrypt_and_verify(encrypted_message, on_rotation: rotate)
+ @encryptor.decrypt_and_verify(encrypted_message, on_rotation: rotate, purpose: purpose)
end
rescue ActiveSupport::MessageEncryptor::InvalidMessage, ActiveSupport::MessageVerifier::InvalidSignature
parse_legacy_signed_message(name, encrypted_message)
end
- def commit(options)
- options[:value] = @encryptor.encrypt_and_sign(serialize(options[:value]), expiry_options(options))
+ def commit(name, options)
+ options[:value] = @encryptor.encrypt_and_sign(serialize(options[:value]), cookie_metadata(name, options))
raise CookieOverflow if options[:value].bytesize > MAX_COOKIE_SIZE
end
diff --git a/actionpack/lib/action_dispatch/middleware/templates/routes/_table.html.erb b/actionpack/lib/action_dispatch/middleware/templates/routes/_table.html.erb
index 1fa0691303..0242b706b2 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/routes/_table.html.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/routes/_table.html.erb
@@ -197,4 +197,7 @@
setupMatchPaths();
setupRouteToggleHelperLinks();
+
+ // Focus the search input after page has loaded
+ document.getElementById('search').focus();
</script>
diff --git a/actionpack/lib/action_dispatch/railtie.rb b/actionpack/lib/action_dispatch/railtie.rb
index eb6fbca6ba..efc3988bc3 100644
--- a/actionpack/lib/action_dispatch/railtie.rb
+++ b/actionpack/lib/action_dispatch/railtie.rb
@@ -21,6 +21,7 @@ module ActionDispatch
config.action_dispatch.encrypted_signed_cookie_salt = "signed encrypted cookie"
config.action_dispatch.authenticated_encrypted_cookie_salt = "authenticated encrypted cookie"
config.action_dispatch.use_authenticated_cookie_encryption = false
+ config.action_dispatch.use_cookies_with_metadata = false
config.action_dispatch.perform_deep_munge = true
config.action_dispatch.default_headers = {
diff --git a/actionpack/lib/action_dispatch/request/utils.rb b/actionpack/lib/action_dispatch/request/utils.rb
index 0ae464082d..fb0efb9a58 100644
--- a/actionpack/lib/action_dispatch/request/utils.rb
+++ b/actionpack/lib/action_dispatch/request/utils.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true
+require "active_support/core_ext/hash/indifferent_access"
+
module ActionDispatch
class Request
class Utils # :nodoc:
diff --git a/actionpack/lib/action_dispatch/routing/inspector.rb b/actionpack/lib/action_dispatch/routing/inspector.rb
index cba49d1a0b..413e524ef6 100644
--- a/actionpack/lib/action_dispatch/routing/inspector.rb
+++ b/actionpack/lib/action_dispatch/routing/inspector.rb
@@ -83,7 +83,7 @@ module ActionDispatch
private
def normalize_filter(filter)
if filter[:controller]
- { controller: /#{filter[:controller].downcase.sub(/_?controller\z/, '').sub('::', '/')}/ }
+ { controller: /#{filter[:controller].underscore.sub(/_?controller\z/, "")}/ }
elsif filter[:grep]
{ controller: /#{filter[:grep]}/, action: /#{filter[:grep]}/,
verb: /#{filter[:grep]}/, name: /#{filter[:grep]}/, path: /#{filter[:grep]}/ }
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index ff325afc54..07e3be4db8 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -553,10 +553,10 @@ module ActionDispatch
#
# match 'json_only', constraints: { format: 'json' }, via: :get
#
- # class Whitelist
+ # class PermitList
# def matches?(request) request.remote_ip == '1.2.3.4' end
# end
- # match 'path', to: 'c#a', constraints: Whitelist.new, via: :get
+ # match 'path', to: 'c#a', constraints: PermitList.new, via: :get
#
# See <tt>Scoping#constraints</tt> for more examples with its scope
# equivalent.
diff --git a/actionpack/lib/action_dispatch/testing/test_process.rb b/actionpack/lib/action_dispatch/testing/test_process.rb
index 8ac50c730d..0b98f27f11 100644
--- a/actionpack/lib/action_dispatch/testing/test_process.rb
+++ b/actionpack/lib/action_dispatch/testing/test_process.rb
@@ -8,12 +8,12 @@ module ActionDispatch
module FixtureFile
# Shortcut for <tt>Rack::Test::UploadedFile.new(File.join(ActionDispatch::IntegrationTest.fixture_path, path), type)</tt>:
#
- # post :change_avatar, avatar: fixture_file_upload('files/spongebob.png', 'image/png')
+ # post :change_avatar, params: { avatar: fixture_file_upload('files/spongebob.png', 'image/png') }
#
# To upload binary files on Windows, pass <tt>:binary</tt> as the last parameter.
# This will not affect other platforms:
#
- # post :change_avatar, avatar: fixture_file_upload('files/spongebob.png', 'image/png', :binary)
+ # post :change_avatar, params: { avatar: fixture_file_upload('files/spongebob.png', 'image/png', :binary) }
def fixture_file_upload(path, mime_type = nil, binary = false)
if self.class.respond_to?(:fixture_path) && self.class.fixture_path &&
!File.exist?(path)