aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib')
-rw-r--r--actionpack/lib/abstract_controller/translation.rb1
-rw-r--r--actionpack/lib/action_controller/metal.rb4
-rw-r--r--actionpack/lib/action_controller/metal/etag_with_template_digest.rb2
-rw-r--r--actionpack/lib/action_controller/metal/helpers.rb2
-rw-r--r--actionpack/lib/action_controller/metal/live.rb4
-rw-r--r--actionpack/lib/action_controller/metal/params_wrapper.rb2
-rw-r--r--actionpack/lib/action_controller/metal/request_forgery_protection.rb2
-rw-r--r--actionpack/lib/action_controller/metal/strong_parameters.rb4
-rw-r--r--actionpack/lib/action_controller/renderer.rb4
-rw-r--r--actionpack/lib/action_dispatch.rb1
-rw-r--r--actionpack/lib/action_dispatch/http/mime_negotiation.rb5
-rw-r--r--actionpack/lib/action_dispatch/http/mime_type.rb14
-rw-r--r--actionpack/lib/action_dispatch/http/response.rb7
-rw-r--r--actionpack/lib/action_dispatch/http/upload.rb5
-rw-r--r--actionpack/lib/action_dispatch/journey/path/pattern.rb7
-rw-r--r--actionpack/lib/action_dispatch/journey/routes.rb1
-rw-r--r--actionpack/lib/action_dispatch/middleware/actionable_exceptions.rb39
-rw-r--r--actionpack/lib/action_dispatch/middleware/cookies.rb2
-rw-r--r--actionpack/lib/action_dispatch/middleware/debug_exceptions.rb10
-rw-r--r--actionpack/lib/action_dispatch/middleware/debug_view.rb14
-rw-r--r--actionpack/lib/action_dispatch/middleware/exception_wrapper.rb1
-rw-r--r--actionpack/lib/action_dispatch/middleware/public_exceptions.rb8
-rw-r--r--actionpack/lib/action_dispatch/middleware/session/cookie_store.rb7
-rw-r--r--actionpack/lib/action_dispatch/middleware/stack.rb36
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb13
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/rescues/_actions.text.erb0
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb4
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb2
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb8
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb2
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb3
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb2
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/rescues/layout.erb4
-rw-r--r--actionpack/lib/action_dispatch/routing.rb8
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb22
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb28
-rw-r--r--actionpack/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb3
-rw-r--r--actionpack/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb12
-rw-r--r--actionpack/lib/action_dispatch/testing/integration.rb4
-rw-r--r--actionpack/lib/action_dispatch/testing/request_encoder.rb4
-rw-r--r--actionpack/lib/action_pack/gem_version.rb4
41 files changed, 231 insertions, 74 deletions
diff --git a/actionpack/lib/abstract_controller/translation.rb b/actionpack/lib/abstract_controller/translation.rb
index 666e154e4c..4dad2a2b93 100644
--- a/actionpack/lib/abstract_controller/translation.rb
+++ b/actionpack/lib/abstract_controller/translation.rb
@@ -11,6 +11,7 @@ module AbstractController
# to translate many keys within the same controller / action and gives you a
# simple framework for scoping them consistently.
def translate(key, options = {})
+ options = options.dup
if key.to_s.first == "."
path = controller_path.tr("/", ".")
defaults = [:"#{path}#{key}"]
diff --git a/actionpack/lib/action_controller/metal.rb b/actionpack/lib/action_controller/metal.rb
index f875aa5e6b..b9088e6d86 100644
--- a/actionpack/lib/action_controller/metal.rb
+++ b/actionpack/lib/action_controller/metal.rb
@@ -26,10 +26,10 @@ module ActionController
end
end
- def build(action, app = Proc.new)
+ def build(action, app = nil, &block)
action = action.to_s
- middlewares.reverse.inject(app) do |a, middleware|
+ middlewares.reverse.inject(app || block) do |a, middleware|
middleware.valid?(action) ? middleware.build(a) : a
end
end
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 640c75536e..2f1544c69c 100644
--- a/actionpack/lib/action_controller/metal/etag_with_template_digest.rb
+++ b/actionpack/lib/action_controller/metal/etag_with_template_digest.rb
@@ -51,7 +51,7 @@ module ActionController
end
def lookup_and_digest_template(template)
- ActionView::Digestor.digest name: template, finder: lookup_context
+ ActionView::Digestor.digest name: template, format: nil, finder: lookup_context
end
end
end
diff --git a/actionpack/lib/action_controller/metal/helpers.rb b/actionpack/lib/action_controller/metal/helpers.rb
index f1fb7ab0f7..193b488f6c 100644
--- a/actionpack/lib/action_controller/metal/helpers.rb
+++ b/actionpack/lib/action_controller/metal/helpers.rb
@@ -34,7 +34,7 @@ module ActionController
# end
# end
#
- # Then, in any view rendered by <tt>EventController</tt>, the <tt>format_time</tt> method can be called:
+ # Then, in any view rendered by <tt>EventsController</tt>, the <tt>format_time</tt> method can be called:
#
# <% @events.each do |event| -%>
# <p>
diff --git a/actionpack/lib/action_controller/metal/live.rb b/actionpack/lib/action_controller/metal/live.rb
index 083b762f5a..dd69930e25 100644
--- a/actionpack/lib/action_controller/metal/live.rb
+++ b/actionpack/lib/action_controller/metal/live.rb
@@ -146,7 +146,7 @@ module ActionController
def write(string)
unless @response.committed?
- @response.set_header "Cache-Control", "no-cache"
+ @response.headers["Cache-Control"] ||= "no-cache"
@response.delete_header "Content-Length"
end
@@ -305,7 +305,7 @@ module ActionController
logger.fatal do
message = +"\n#{exception.class} (#{exception.message}):\n"
- message << exception.annoted_source_code.to_s if exception.respond_to?(:annoted_source_code)
+ message << exception.annotated_source_code.to_s if exception.respond_to?(:annotated_source_code)
message << " " << exception.backtrace.join("\n ")
"#{message}\n\n"
end
diff --git a/actionpack/lib/action_controller/metal/params_wrapper.rb b/actionpack/lib/action_controller/metal/params_wrapper.rb
index 09716f7588..e635abec8e 100644
--- a/actionpack/lib/action_controller/metal/params_wrapper.rb
+++ b/actionpack/lib/action_controller/metal/params_wrapper.rb
@@ -93,7 +93,7 @@ module ActionController
end
def model
- super || synchronize { super || self.model = _default_wrap_model }
+ super || self.model = _default_wrap_model
end
def include
diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
index cb109c6ad8..4bf8d90b69 100644
--- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb
+++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
@@ -431,7 +431,7 @@ module ActionController #:nodoc:
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 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.
+ best solution is to change your referrer policy to something less strict like same-origin or strict-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
diff --git a/actionpack/lib/action_controller/metal/strong_parameters.rb b/actionpack/lib/action_controller/metal/strong_parameters.rb
index 815f82a1f2..ae774b01f1 100644
--- a/actionpack/lib/action_controller/metal/strong_parameters.rb
+++ b/actionpack/lib/action_controller/metal/strong_parameters.rb
@@ -4,7 +4,6 @@ require "active_support/core_ext/hash/indifferent_access"
require "active_support/core_ext/array/wrap"
require "active_support/core_ext/string/filters"
require "active_support/core_ext/object/to_query"
-require "active_support/rescuable"
require "action_dispatch/http/upload"
require "rack/test"
require "stringio"
@@ -1092,9 +1091,6 @@ module ActionController
# See ActionController::Parameters.require and ActionController::Parameters.permit
# for more information.
module StrongParameters
- extend ActiveSupport::Concern
- include ActiveSupport::Rescuable
-
# Returns a new ActionController::Parameters object that
# has been instantiated with the <tt>request.parameters</tt>.
def params
diff --git a/actionpack/lib/action_controller/renderer.rb b/actionpack/lib/action_controller/renderer.rb
index cf8c0159e2..dadf6d3445 100644
--- a/actionpack/lib/action_controller/renderer.rb
+++ b/actionpack/lib/action_controller/renderer.rb
@@ -74,7 +74,7 @@ module ActionController
# * <tt>:partial</tt> - See <tt>ActionView::PartialRenderer</tt> for details.
# * <tt>:file</tt> - Renders an explicit template file. Add <tt>:locals</tt> to pass in, if so desired.
# It shouldn’t be used directly with unsanitized user input due to lack of validation.
- # * <tt>:inline</tt> - Renders a ERB template string.
+ # * <tt>:inline</tt> - Renders an ERB template string.
# * <tt>:plain</tt> - Renders provided text and sets the content type as <tt>text/plain</tt>.
# * <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>.
@@ -116,7 +116,7 @@ module ActionController
RACK_VALUE_TRANSLATION = {
https: ->(v) { v ? "on" : "off" },
- method: ->(v) { v.upcase },
+ method: ->(v) { -v.upcase },
}
def rack_key_for(key)
diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb
index 8f39b88d56..6a4ba9af4a 100644
--- a/actionpack/lib/action_dispatch.rb
+++ b/actionpack/lib/action_dispatch.rb
@@ -53,6 +53,7 @@ module ActionDispatch
autoload :RequestId
autoload :Callbacks
autoload :Cookies
+ autoload :ActionableExceptions
autoload :DebugExceptions
autoload :DebugLocks
autoload :DebugView
diff --git a/actionpack/lib/action_dispatch/http/mime_negotiation.rb b/actionpack/lib/action_dispatch/http/mime_negotiation.rb
index 498b1e6695..4e81ba12a5 100644
--- a/actionpack/lib/action_dispatch/http/mime_negotiation.rb
+++ b/actionpack/lib/action_dispatch/http/mime_negotiation.rb
@@ -79,6 +79,11 @@ module ActionDispatch
else
[Mime[:html]]
end
+
+ v = v.select do |format|
+ format.symbol || format.ref == "*/*"
+ end
+
set_header k, v
end
end
diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb
index c3e0ea3c89..88b3a93211 100644
--- a/actionpack/lib/action_dispatch/http/mime_type.rb
+++ b/actionpack/lib/action_dispatch/http/mime_type.rb
@@ -170,6 +170,7 @@ module Mime
def parse(accept_header)
if !accept_header.include?(",")
accept_header = accept_header.split(PARAMETER_SEPARATOR_REGEXP).first
+ return [] unless accept_header
parse_trailing_star(accept_header) || [Mime::Type.lookup(accept_header)].compact
else
list, index = [], 0
@@ -221,7 +222,18 @@ module Mime
attr_reader :hash
+ MIME_NAME = "[a-zA-Z0-9][a-zA-Z0-9#{Regexp.escape('!#$&-^_.+')}]{0,126}"
+ MIME_PARAMETER_KEY = "[a-zA-Z0-9][a-zA-Z0-9#{Regexp.escape('!#$&-^_.+')}]{0,126}"
+ MIME_PARAMETER_VALUE = "#{Regexp.escape('"')}?[a-zA-Z0-9][a-zA-Z0-9#{Regexp.escape('!#$&-^_.+')}]{0,126}#{Regexp.escape('"')}?"
+ MIME_PARAMETER = "\s*\;\s+#{MIME_PARAMETER_KEY}(?:\=#{MIME_PARAMETER_VALUE})?"
+ MIME_REGEXP = /\A(?:\*\/\*|#{MIME_NAME}\/(?:\*|#{MIME_NAME})(?:\s*#{MIME_PARAMETER}\s*)*)\z/
+
+ class InvalidMimeType < StandardError; end
+
def initialize(string, symbol = nil, synonyms = [])
+ unless MIME_REGEXP.match?(string)
+ raise InvalidMimeType, "#{string.inspect} is not a valid MIME type"
+ end
@symbol, @synonyms = symbol, synonyms
@string = string
@hash = [@string, @synonyms, @symbol].hash
@@ -303,7 +315,7 @@ module Mime
include Singleton
def initialize
- super "*/*", :all
+ super "*/*", nil
end
def all?; true; end
diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb
index 1d38942a31..69798f99e0 100644
--- a/actionpack/lib/action_dispatch/http/response.rb
+++ b/actionpack/lib/action_dispatch/http/response.rb
@@ -82,6 +82,7 @@ module ActionDispatch # :nodoc:
SET_COOKIE = "Set-Cookie"
LOCATION = "Location"
NO_CONTENT_CODES = [100, 101, 102, 204, 205, 304]
+ CONTENT_TYPE_PARSER = /\A(?<type>[^;\s]+)?(?:.*;\s*charset=(?<quote>"?)(?<charset>[^;\s]+)\k<quote>)?/ # :nodoc:
cattr_accessor :default_charset, default: "utf-8"
cattr_accessor :default_headers
@@ -409,10 +410,8 @@ module ActionDispatch # :nodoc:
NullContentTypeHeader = ContentTypeHeader.new nil, nil
def parse_content_type(content_type)
- if content_type
- type, charset = content_type.split(/;\s*charset=/)
- type = nil if type && type.empty?
- ContentTypeHeader.new(type, charset)
+ if content_type && match = CONTENT_TYPE_PARSER.match(content_type)
+ ContentTypeHeader.new(match[:type], match[:charset])
else
NullContentTypeHeader
end
diff --git a/actionpack/lib/action_dispatch/http/upload.rb b/actionpack/lib/action_dispatch/http/upload.rb
index 827f022ca2..0da8f5c14e 100644
--- a/actionpack/lib/action_dispatch/http/upload.rb
+++ b/actionpack/lib/action_dispatch/http/upload.rb
@@ -20,7 +20,6 @@ module ActionDispatch
# A +Tempfile+ object with the actual uploaded file. Note that some of
# its interface is available directly.
attr_accessor :tempfile
- alias :to_io :tempfile
# A string with the headers of the multipart request.
attr_accessor :headers
@@ -84,6 +83,10 @@ module ActionDispatch
def eof?
@tempfile.eof?
end
+
+ def to_io
+ @tempfile.to_io
+ end
end
end
end
diff --git a/actionpack/lib/action_dispatch/journey/path/pattern.rb b/actionpack/lib/action_dispatch/journey/path/pattern.rb
index 697f5b9d8b..dee2980eb1 100644
--- a/actionpack/lib/action_dispatch/journey/path/pattern.rb
+++ b/actionpack/lib/action_dispatch/journey/path/pattern.rb
@@ -119,7 +119,8 @@ module ActionDispatch
class UnanchoredRegexp < AnchoredRegexp # :nodoc:
def accept(node)
- %r{\A#{visit node}(?:\b|\Z)}
+ path = visit node
+ path == "/" ? %r{\A/} : %r{\A#{path}(?:\b|\Z|/)}
end
end
@@ -136,6 +137,10 @@ module ActionDispatch
Array.new(length - 1) { |i| self[i + 1] }
end
+ def named_captures
+ @names.zip(captures).to_h
+ end
+
def [](x)
idx = @offsets[x - 1] + x
@match[idx]
diff --git a/actionpack/lib/action_dispatch/journey/routes.rb b/actionpack/lib/action_dispatch/journey/routes.rb
index c0377459d5..3ba8361d77 100644
--- a/actionpack/lib/action_dispatch/journey/routes.rb
+++ b/actionpack/lib/action_dispatch/journey/routes.rb
@@ -56,7 +56,6 @@ module ActionDispatch
end
def simulator
- return if ast.nil?
@simulator ||= begin
gtg = GTG::Builder.new(ast).transition_table
GTG::Simulator.new(gtg)
diff --git a/actionpack/lib/action_dispatch/middleware/actionable_exceptions.rb b/actionpack/lib/action_dispatch/middleware/actionable_exceptions.rb
new file mode 100644
index 0000000000..e94cc46603
--- /dev/null
+++ b/actionpack/lib/action_dispatch/middleware/actionable_exceptions.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require "erb"
+require "action_dispatch/http/request"
+require "active_support/actionable_error"
+
+module ActionDispatch
+ class ActionableExceptions # :nodoc:
+ cattr_accessor :endpoint, default: "/rails/actions"
+
+ def initialize(app)
+ @app = app
+ end
+
+ def call(env)
+ request = ActionDispatch::Request.new(env)
+ return @app.call(env) unless actionable_request?(request)
+
+ ActiveSupport::ActionableError.dispatch(request.params[:error].to_s.safe_constantize, request.params[:action])
+
+ redirect_to request.params[:location]
+ end
+
+ private
+ def actionable_request?(request)
+ request.show_exceptions? && request.post? && request.path == endpoint
+ end
+
+ def redirect_to(location)
+ body = "<html><body>You are being <a href=\"#{ERB::Util.unwrapped_html_escape(location)}\">redirected</a>.</body></html>"
+
+ [302, {
+ "Content-Type" => "text/html; charset=#{Response.default_charset}",
+ "Content-Length" => body.bytesize.to_s,
+ "Location" => location,
+ }, [body]]
+ end
+ end
+end
diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb
index 1611a8b3dd..b69bcab05c 100644
--- a/actionpack/lib/action_dispatch/middleware/cookies.rb
+++ b/actionpack/lib/action_dispatch/middleware/cookies.rb
@@ -338,7 +338,7 @@ module ActionDispatch
def update_cookies_from_jar
request_jar = @request.cookie_jar.instance_variable_get(:@cookies)
- set_cookies = request_jar.reject { |k, _| @delete_cookies.key?(k) }
+ set_cookies = request_jar.reject { |k, _| @delete_cookies.key?(k) || @set_cookies.key?(k) }
@cookies.update set_cookies if set_cookies
end
diff --git a/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb b/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
index 61773d97a2..0b15c94122 100644
--- a/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
+++ b/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
@@ -4,6 +4,8 @@ require "action_dispatch/http/request"
require "action_dispatch/middleware/exception_wrapper"
require "action_dispatch/routing/inspector"
+require "active_support/actionable_error"
+
require "action_view"
require "action_view/base"
@@ -60,7 +62,11 @@ module ActionDispatch
log_error(request, wrapper)
if request.get_header("action_dispatch.show_detailed_exceptions")
- content_type = request.formats.first
+ begin
+ content_type = request.formats.first
+ rescue Mime::Type::InvalidMimeType
+ render_for_api_request(Mime[:text], wrapper)
+ end
if api_request?(content_type)
render_for_api_request(content_type, wrapper)
@@ -142,7 +148,7 @@ module ActionDispatch
message = []
message << " "
message << "#{exception.class} (#{exception.message}):"
- message.concat(exception.annoted_source_code) if exception.respond_to?(:annoted_source_code)
+ message.concat(exception.annotated_source_code) if exception.respond_to?(:annotated_source_code)
message << " "
message.concat(trace)
diff --git a/actionpack/lib/action_dispatch/middleware/debug_view.rb b/actionpack/lib/action_dispatch/middleware/debug_view.rb
index f16484d1ea..148662a48b 100644
--- a/actionpack/lib/action_dispatch/middleware/debug_view.rb
+++ b/actionpack/lib/action_dispatch/middleware/debug_view.rb
@@ -11,8 +11,8 @@ module ActionDispatch
def initialize(assigns)
paths = [RESCUES_TEMPLATE_PATH]
- renderer = ActionView::Renderer.new ActionView::LookupContext.new(paths)
- super(renderer, assigns)
+ lookup_context = ActionView::LookupContext.new(paths)
+ super(lookup_context, assigns)
end
def compiled_method_container
@@ -52,5 +52,15 @@ module ActionDispatch
super
end
end
+
+ def protect_against_forgery?
+ false
+ end
+
+ def params_valid?
+ @request.parameters
+ rescue ActionController::BadRequest
+ false
+ end
end
end
diff --git a/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb b/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
index 1fb3e9db00..0cc56f5013 100644
--- a/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
+++ b/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
@@ -12,6 +12,7 @@ module ActionDispatch
"ActionController::UnknownHttpMethod" => :method_not_allowed,
"ActionController::NotImplemented" => :not_implemented,
"ActionController::UnknownFormat" => :not_acceptable,
+ "Mime::Type::InvalidMimeType" => :not_acceptable,
"ActionController::MissingExactTemplate" => :not_acceptable,
"ActionController::InvalidAuthenticityToken" => :unprocessable_entity,
"ActionController::InvalidCrossOriginRequest" => :unprocessable_entity,
diff --git a/actionpack/lib/action_dispatch/middleware/public_exceptions.rb b/actionpack/lib/action_dispatch/middleware/public_exceptions.rb
index 3feb3a19f3..a88ad40f21 100644
--- a/actionpack/lib/action_dispatch/middleware/public_exceptions.rb
+++ b/actionpack/lib/action_dispatch/middleware/public_exceptions.rb
@@ -21,8 +21,12 @@ module ActionDispatch
def call(env)
request = ActionDispatch::Request.new(env)
status = request.path_info[1..-1].to_i
- content_type = request.formats.first
- body = { status: status, error: Rack::Utils::HTTP_STATUS_CODES.fetch(status, Rack::Utils::HTTP_STATUS_CODES[500]) }
+ begin
+ content_type = request.formats.first
+ rescue Mime::Type::InvalidMimeType
+ content_type = Mime[:text]
+ end
+ body = { status: status, error: Rack::Utils::HTTP_STATUS_CODES.fetch(status, Rack::Utils::HTTP_STATUS_CODES[500]) }
render(status, content_type, body)
end
diff --git a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb
index 02ccfbc81a..7c43c781c7 100644
--- a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb
+++ b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb
@@ -24,9 +24,10 @@ module ActionDispatch
#
# Rails.application.config.session_store :cookie_store, key: '_your_app_session'
#
- # By default, your secret key base is derived from your application name in
- # the test and development environments. In all other environments, it is stored
- # encrypted in the <tt>config/credentials.yml.enc</tt> file.
+ # In the development and test environments your application's secret key base is
+ # generated by Rails and stored in a temporary file in <tt>tmp/development_secret.txt</tt>.
+ # In all other environments, it is stored encrypted in the
+ # <tt>config/credentials.yml.enc</tt> file.
#
# If your application was not updated to Rails 5.2 defaults, the secret_key_base
# will be found in the old <tt>config/secrets.yml</tt> file.
diff --git a/actionpack/lib/action_dispatch/middleware/stack.rb b/actionpack/lib/action_dispatch/middleware/stack.rb
index b82f8aa3a3..57e4adb457 100644
--- a/actionpack/lib/action_dispatch/middleware/stack.rb
+++ b/actionpack/lib/action_dispatch/middleware/stack.rb
@@ -36,6 +36,31 @@ module ActionDispatch
def build(app)
klass.new(app, *args, &block)
end
+
+ def build_instrumented(app)
+ InstrumentationProxy.new(build(app), inspect)
+ end
+ end
+
+ # This class is used to instrument the execution of a single middleware.
+ # It proxies the `call` method transparently and instruments the method
+ # call.
+ class InstrumentationProxy
+ EVENT_NAME = "process_middleware.action_dispatch"
+
+ def initialize(middleware, class_name)
+ @middleware = middleware
+
+ @payload = {
+ middleware: class_name,
+ }
+ end
+
+ def call(env)
+ ActiveSupport::Notifications.instrument(EVENT_NAME, @payload) do
+ @middleware.call(env)
+ end
+ end
end
include Enumerable
@@ -97,8 +122,15 @@ module ActionDispatch
middlewares.push(build_middleware(klass, args, block))
end
- def build(app = Proc.new)
- middlewares.freeze.reverse.inject(app) { |a, e| e.build(a) }
+ def build(app = nil, &block)
+ instrumenting = ActiveSupport::Notifications.notifier.listening?(InstrumentationProxy::EVENT_NAME)
+ middlewares.freeze.reverse.inject(app || block) do |a, e|
+ if instrumenting
+ e.build_instrumented(a)
+ else
+ e.build(a)
+ end
+ end
end
private
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb
new file mode 100644
index 0000000000..b6c6d2f50d
--- /dev/null
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb
@@ -0,0 +1,13 @@
+<% actions = ActiveSupport::ActionableError.actions(exception) %>
+
+<% if actions.any? %>
+ <div class="actions">
+ <% actions.each do |action, _| %>
+ <%= button_to action, ActionDispatch::ActionableExceptions.endpoint, params: {
+ error: exception.class.name,
+ action: action,
+ location: request.path
+ } %>
+ <% end %>
+ </div>
+<% end %>
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/_actions.text.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/_actions.text.erb
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/_actions.text.erb
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb
index 49b1e83551..04271d8e8a 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb
@@ -6,7 +6,9 @@
<% end %>
<h2 style="margin-top: 30px">Request</h2>
-<p><b>Parameters</b>:</p> <pre><%= debug_params(@request.filtered_parameters) %></pre>
+<% if params_valid? %>
+ <p><b>Parameters</b>:</p> <pre><%= debug_params(@request.filtered_parameters) %></pre>
+<% end %>
<div class="details">
<div class="summary"><a href="#" onclick="return toggleSessionDump()">Toggle session dump</a></div>
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb
index 396768ecee..ca42a6fa8b 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb
@@ -1,5 +1,5 @@
<%
- clean_params = @request.filtered_parameters.clone
+ clean_params = params_valid? ? @request.filtered_parameters.clone : {}
clean_params.delete("action")
clean_params.delete("controller")
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb
index bde26f46c2..57cdcf9aaf 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb
@@ -1,14 +1,18 @@
<header>
<h1>
<%= @exception.class.to_s %>
- <% if @request.parameters['controller'] %>
+ <% if params_valid? && @request.parameters['controller'] %>
in <%= @request.parameters['controller'].camelize %>Controller<% if @request.parameters['action'] %>#<%= @request.parameters['action'] %><% end %>
<% end %>
</h1>
</header>
<div id="container">
- <h2><%= h @exception.message %></h2>
+ <h2>
+ <%= h @exception.message %>
+
+ <%= render "rescues/actions", exception: @exception, request: @request %>
+ </h2>
<%= render "rescues/source", source_extracts: @source_extracts, show_source_idx: @show_source_idx, error_index: 0 %>
<%= render "rescues/trace", traces: @traces, trace_to_show: @trace_to_show, error_index: 0 %>
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb
index 603de54b8b..d3265563a8 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb
@@ -1,5 +1,5 @@
<%= @exception.class.to_s %><%
- if @request.parameters['controller']
+ if params_valid? && @request.parameters['controller']
%> in <%= @request.parameters['controller'].camelize %>Controller<% if @request.parameters['action'] %>#<%= @request.parameters['action'] %><% end %>
<% end %>
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb
index d144fc1cd2..77cfdd20c8 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb
@@ -13,6 +13,9 @@
<% if defined?(ActiveStorage) && @exception.message.match?(%r{#{ActiveStorage::Blob.table_name}|#{ActiveStorage::Attachment.table_name}}) %>
<br />To resolve this issue run: rails active_storage:install
<% end %>
+ <% if defined?(ActionMailbox) && @exception.message.match?(%r{#{ActionMailbox::InboundEmail.table_name}}) %>
+ <br />To resolve this issue run: rails action_mailbox:install
+ <% end %>
</h2>
<%= render "rescues/source", source_extracts: @source_extracts, show_source_idx: @show_source_idx %>
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb
index 55aaf58713..16c3ecc331 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb
@@ -6,6 +6,8 @@
<%= @exception.message %>
<% if defined?(ActiveStorage) && @exception.message.match?(%r{#{ActiveStorage::Blob.table_name}|#{ActiveStorage::Attachment.table_name}}) %>
To resolve this issue run: rails active_storage:install
+<% if defined?(ActionMailbox) && @exception.message.match?(%r{#{ActionMailbox::InboundEmail.table_name}}) %>
+To resolve this issue run: rails action_mailbox:install
<% end %>
<%= render template: "rescues/_source" %>
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/layout.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/layout.erb
index 39ea25bdfc..0f78e23b7f 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/rescues/layout.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/layout.erb
@@ -117,6 +117,10 @@
background-color: #FFCCCC;
}
+ .button_to {
+ display: inline-block;
+ }
+
.hidden {
display: none;
}
diff --git a/actionpack/lib/action_dispatch/routing.rb b/actionpack/lib/action_dispatch/routing.rb
index f832719f19..d78b1c4f71 100644
--- a/actionpack/lib/action_dispatch/routing.rb
+++ b/actionpack/lib/action_dispatch/routing.rb
@@ -210,8 +210,8 @@ module ActionDispatch
# === +assert_routing+
#
# def test_movie_route_properly_splits
- # opts = {controller: "plugin", action: "checkout", id: "2"}
- # assert_routing "plugin/checkout/2", opts
+ # opts = {controller: "plugin", action: "checkout", id: "2"}
+ # assert_routing "plugin/checkout/2", opts
# end
#
# +assert_routing+ lets you test whether or not the route properly resolves into options.
@@ -219,8 +219,8 @@ module ActionDispatch
# === +assert_recognizes+
#
# def test_route_has_options
- # opts = {controller: "plugin", action: "show", id: "12"}
- # assert_recognizes opts, "/plugins/show/12"
+ # opts = {controller: "plugin", action: "show", id: "12"}
+ # assert_recognizes opts, "/plugins/show/12"
# end
#
# Note the subtle difference between the two: +assert_routing+ tests that
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index d67044b4ac..f29f66990d 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -115,9 +115,9 @@ module ActionDispatch
@defaults = defaults
@set = set
- @to = to
- @default_controller = controller
- @default_action = default_action
+ @to = intern(to)
+ @default_controller = intern(controller)
+ @default_action = intern(default_action)
@ast = ast
@anchor = anchor
@via = via
@@ -222,6 +222,10 @@ module ActionDispatch
private :build_path
private
+ def intern(object)
+ object.is_a?(String) ? -object : object
+ end
+
def add_wildcard_options(options, formatted, path_ast)
# Add a constraint for wildcard route to make it non-greedy and match the
# optional format part of the route by default.
@@ -1141,6 +1145,10 @@ module ActionDispatch
attr_reader :controller, :path, :param
def initialize(entities, api_only, shallow, options = {})
+ if options[:param].to_s.include?(":")
+ raise ArgumentError, ":param option can't contain colons"
+ end
+
@name = entities.to_s
@path = (options[:path] || @name).to_s
@controller = (options[:controller] || @name).to_s
@@ -1398,6 +1406,8 @@ module ActionDispatch
# as a comment on a blog post like <tt>/posts/a-long-permalink/comments/1234</tt>
# to be shortened to just <tt>/comments/1234</tt>.
#
+ # Set <tt>shallow: false</tt> on a child resource to ignore a parent's shallow parameter.
+ #
# [:shallow_path]
# Prefixes nested shallow routes with the specified path.
#
@@ -1440,6 +1450,9 @@ module ActionDispatch
# Allows you to specify the default value for optional +format+
# segment or disable it by supplying +false+.
#
+ # [:param]
+ # Allows you to override the default param name of +:id+ in the URL.
+ #
# === Examples
#
# # routes call <tt>Admin::PostsController</tt>
@@ -1665,7 +1678,8 @@ module ActionDispatch
return true
end
- if options.delete(:shallow)
+ if options[:shallow]
+ options.delete(:shallow)
shallow do
send(method, resources.pop, options, &block)
end
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index 972953d4f3..bbb5762b3c 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -317,23 +317,21 @@ module ActionDispatch
#
def define_url_helper(mod, route, name, opts, route_key, url_strategy)
helper = UrlHelper.create(route, opts, route_key, url_strategy)
- mod.module_eval do
- define_method(name) do |*args|
- last = args.last
- options = \
- case last
- when Hash
- args.pop
- when ActionController::Parameters
- args.pop.to_h
- end
- helper.call self, args, options
- end
+ mod.define_method(name) do |*args|
+ last = args.last
+ options = \
+ case last
+ when Hash
+ args.pop
+ when ActionController::Parameters
+ args.pop.to_h
+ end
+ helper.call self, args, options
end
end
end
- # strategy for building urls to send to the client
+ # strategy for building URLs to send to the client
PATH = ->(options) { ActionDispatch::Http::URL.path_for(options) }
UNKNOWN = ->(options) { ActionDispatch::Http::URL.url_for(options) }
@@ -593,14 +591,14 @@ module ActionDispatch
if route.segment_keys.include?(:controller)
ActiveSupport::Deprecation.warn(<<-MSG.squish)
Using a dynamic :controller segment in a route is deprecated and
- will be removed in Rails 6.0.
+ will be removed in Rails 6.1.
MSG
end
if route.segment_keys.include?(:action)
ActiveSupport::Deprecation.warn(<<-MSG.squish)
Using a dynamic :action segment in a route is deprecated and
- will be removed in Rails 6.0.
+ will be removed in Rails 6.1.
MSG
end
diff --git a/actionpack/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb b/actionpack/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb
index 79359a0c8b..056ce51a61 100644
--- a/actionpack/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb
+++ b/actionpack/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb
@@ -39,7 +39,8 @@ module ActionDispatch
private
def image_name
- failed? ? "failures_#{method_name}" : method_name
+ name = method_name[0...225]
+ failed? ? "failures_#{name}" : name
end
def image_path
diff --git a/actionpack/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb b/actionpack/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb
index 600e9c733b..7080dbe022 100644
--- a/actionpack/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb
+++ b/actionpack/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb
@@ -16,12 +16,14 @@ module ActionDispatch
super
end
+ def before_teardown
+ take_failed_screenshot
+ ensure
+ super
+ end
+
def after_teardown
- begin
- take_failed_screenshot
- ensure
- Capybara.reset_sessions!
- end
+ Capybara.reset_sessions!
ensure
super
end
diff --git a/actionpack/lib/action_dispatch/testing/integration.rb b/actionpack/lib/action_dispatch/testing/integration.rb
index 45439a3bb1..bb8b43ad4d 100644
--- a/actionpack/lib/action_dispatch/testing/integration.rb
+++ b/actionpack/lib/action_dispatch/testing/integration.rb
@@ -194,7 +194,7 @@ module ActionDispatch
# Adds request headers characteristic of XMLHttpRequest e.g. HTTP_X_REQUESTED_WITH.
# The headers will be merged into the Rack env hash.
# - +as+: Used for encoding the request with different content type.
- # Supports `:json` by default and will set the approriate request headers.
+ # Supports `:json` by default and will set the appropriate request headers.
# The headers will be merged into the Rack env hash.
#
# This method is rarely used directly. Use +#get+, +#post+, or other standard
@@ -335,7 +335,7 @@ module ActionDispatch
klass = APP_SESSIONS[app] ||= Class.new(Integration::Session) {
# If the app is a Rails app, make url_helpers available on the session.
# This makes app.url_for and app.foo_path available in the console.
- if app.respond_to?(:routes)
+ if app.respond_to?(:routes) && app.routes.is_a?(ActionDispatch::Routing::RouteSet)
include app.routes.url_helpers
include app.routes.mounted_helpers
end
diff --git a/actionpack/lib/action_dispatch/testing/request_encoder.rb b/actionpack/lib/action_dispatch/testing/request_encoder.rb
index 9889f61951..6c65bec62f 100644
--- a/actionpack/lib/action_dispatch/testing/request_encoder.rb
+++ b/actionpack/lib/action_dispatch/testing/request_encoder.rb
@@ -38,8 +38,8 @@ module ActionDispatch
end
def self.parser(content_type)
- mime = Mime::Type.lookup(content_type)
- encoder(mime ? mime.ref : nil).response_parser
+ type = Mime::Type.lookup(content_type).ref if content_type
+ encoder(type).response_parser
end
def self.encoder(name)
diff --git a/actionpack/lib/action_pack/gem_version.rb b/actionpack/lib/action_pack/gem_version.rb
index c7cb3cb91e..5f8905139d 100644
--- a/actionpack/lib/action_pack/gem_version.rb
+++ b/actionpack/lib/action_pack/gem_version.rb
@@ -8,9 +8,9 @@ module ActionPack
module VERSION
MAJOR = 6
- MINOR = 0
+ MINOR = 1
TINY = 0
- PRE = "beta1"
+ PRE = "alpha"
STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
end