diff options
Diffstat (limited to 'actionpack/lib')
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 |