aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib')
-rw-r--r--actionpack/lib/abstract_controller.rb1
-rw-r--r--actionpack/lib/abstract_controller/base.rb1
-rw-r--r--actionpack/lib/abstract_controller/collector.rb1
-rw-r--r--actionpack/lib/action_controller.rb2
-rw-r--r--actionpack/lib/action_controller/base.rb1
-rw-r--r--actionpack/lib/action_controller/caching.rb1
-rw-r--r--actionpack/lib/action_controller/metal.rb1
-rw-r--r--actionpack/lib/action_controller/metal/content_security_policy.rb1
-rw-r--r--actionpack/lib/action_controller/metal/data_streaming.rb2
-rw-r--r--actionpack/lib/action_controller/metal/feature_policy.rb46
-rw-r--r--actionpack/lib/action_controller/metal/instrumentation.rb1
-rw-r--r--actionpack/lib/action_controller/metal/live.rb4
-rw-r--r--actionpack/lib/action_controller/metal/params_wrapper.rb1
-rw-r--r--actionpack/lib/action_controller/metal/rendering.rb1
-rw-r--r--actionpack/lib/action_controller/metal/request_forgery_protection.rb2
-rw-r--r--actionpack/lib/action_controller/metal/streaming.rb1
-rw-r--r--actionpack/lib/action_controller/metal/strong_parameters.rb5
-rw-r--r--actionpack/lib/action_controller/test_case.rb3
-rw-r--r--actionpack/lib/action_dispatch.rb1
-rw-r--r--actionpack/lib/action_dispatch/http/cache.rb1
-rw-r--r--actionpack/lib/action_dispatch/http/content_security_policy.rb35
-rw-r--r--actionpack/lib/action_dispatch/http/feature_policy.rb168
-rw-r--r--actionpack/lib/action_dispatch/http/filter_parameters.rb1
-rw-r--r--actionpack/lib/action_dispatch/http/filter_redirect.rb1
-rw-r--r--actionpack/lib/action_dispatch/http/headers.rb1
-rw-r--r--actionpack/lib/action_dispatch/http/mime_negotiation.rb1
-rw-r--r--actionpack/lib/action_dispatch/http/mime_type.rb2
-rw-r--r--actionpack/lib/action_dispatch/http/parameters.rb1
-rw-r--r--actionpack/lib/action_dispatch/http/request.rb1
-rw-r--r--actionpack/lib/action_dispatch/http/response.rb15
-rw-r--r--actionpack/lib/action_dispatch/http/url.rb1
-rw-r--r--actionpack/lib/action_dispatch/journey/formatter.rb1
-rw-r--r--actionpack/lib/action_dispatch/journey/gtg/builder.rb1
-rw-r--r--actionpack/lib/action_dispatch/journey/gtg/transition_table.rb1
-rw-r--r--actionpack/lib/action_dispatch/journey/nfa/transition_table.rb1
-rw-r--r--actionpack/lib/action_dispatch/journey/path/pattern.rb1
-rw-r--r--actionpack/lib/action_dispatch/journey/router.rb1
-rw-r--r--actionpack/lib/action_dispatch/journey/routes.rb1
-rw-r--r--actionpack/lib/action_dispatch/journey/scanner.rb1
-rw-r--r--actionpack/lib/action_dispatch/journey/visitors.rb3
-rw-r--r--actionpack/lib/action_dispatch/middleware/cookies.rb2
-rw-r--r--actionpack/lib/action_dispatch/middleware/debug_exceptions.rb5
-rw-r--r--actionpack/lib/action_dispatch/middleware/exception_wrapper.rb16
-rw-r--r--actionpack/lib/action_dispatch/middleware/host_authorization.rb2
-rw-r--r--actionpack/lib/action_dispatch/middleware/public_exceptions.rb1
-rw-r--r--actionpack/lib/action_dispatch/middleware/remote_ip.rb1
-rw-r--r--actionpack/lib/action_dispatch/middleware/session/abstract_store.rb2
-rw-r--r--actionpack/lib/action_dispatch/middleware/session/cookie_store.rb1
-rw-r--r--actionpack/lib/action_dispatch/middleware/show_exceptions.rb1
-rw-r--r--actionpack/lib/action_dispatch/middleware/stack.rb1
-rw-r--r--actionpack/lib/action_dispatch/railtie.rb8
-rw-r--r--actionpack/lib/action_dispatch/request/session.rb1
-rw-r--r--actionpack/lib/action_dispatch/routing/inspector.rb2
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb1
-rw-r--r--actionpack/lib/action_dispatch/routing/polymorphic_routes.rb2
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb3
-rw-r--r--actionpack/lib/action_dispatch/routing/url_for.rb2
-rw-r--r--actionpack/lib/action_dispatch/system_test_case.rb14
-rw-r--r--actionpack/lib/action_dispatch/system_testing/browser.rb23
-rw-r--r--actionpack/lib/action_dispatch/system_testing/driver.rb2
-rw-r--r--actionpack/lib/action_dispatch/testing/assertion_response.rb1
-rw-r--r--actionpack/lib/action_dispatch/testing/integration.rb1
62 files changed, 316 insertions, 91 deletions
diff --git a/actionpack/lib/abstract_controller.rb b/actionpack/lib/abstract_controller.rb
index 3a98931167..d1ff62a032 100644
--- a/actionpack/lib/abstract_controller.rb
+++ b/actionpack/lib/abstract_controller.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
require "action_pack"
+require "active_support"
require "active_support/rails"
require "active_support/i18n"
diff --git a/actionpack/lib/abstract_controller/base.rb b/actionpack/lib/abstract_controller/base.rb
index bb42f2e119..3ff922029b 100644
--- a/actionpack/lib/abstract_controller/base.rb
+++ b/actionpack/lib/abstract_controller/base.rb
@@ -176,7 +176,6 @@ module AbstractController
end
private
-
# Returns true if the name can be considered an action because
# it has a method defined in the controller.
#
diff --git a/actionpack/lib/abstract_controller/collector.rb b/actionpack/lib/abstract_controller/collector.rb
index d4a078ab32..0af546cc96 100644
--- a/actionpack/lib/abstract_controller/collector.rb
+++ b/actionpack/lib/abstract_controller/collector.rb
@@ -22,7 +22,6 @@ module AbstractController
end
private
-
def method_missing(symbol, &block)
unless mime_constant = Mime[symbol]
raise NoMethodError, "To respond to a custom format, register it as a MIME type first: " \
diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb
index 29d61c3ceb..22dc229599 100644
--- a/actionpack/lib/action_controller.rb
+++ b/actionpack/lib/action_controller.rb
@@ -1,6 +1,5 @@
# frozen_string_literal: true
-require "active_support/rails"
require "abstract_controller"
require "action_dispatch"
require "action_controller/metal/live"
@@ -28,6 +27,7 @@ module ActionController
autoload :DefaultHeaders
autoload :EtagWithTemplateDigest
autoload :EtagWithFlash
+ autoload :FeaturePolicy
autoload :Flash
autoload :ForceSSL
autoload :Head
diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb
index 2e565d5d44..63c138af55 100644
--- a/actionpack/lib/action_controller/base.rb
+++ b/actionpack/lib/action_controller/base.rb
@@ -226,6 +226,7 @@ module ActionController
FormBuilder,
RequestForgeryProtection,
ContentSecurityPolicy,
+ FeaturePolicy,
ForceSSL,
Streaming,
DataStreaming,
diff --git a/actionpack/lib/action_controller/caching.rb b/actionpack/lib/action_controller/caching.rb
index bf3b00a7b7..83e3e0c37c 100644
--- a/actionpack/lib/action_controller/caching.rb
+++ b/actionpack/lib/action_controller/caching.rb
@@ -30,7 +30,6 @@ module ActionController
end
private
-
def instrument_payload(key)
{
controller: controller_name,
diff --git a/actionpack/lib/action_controller/metal.rb b/actionpack/lib/action_controller/metal.rb
index 9ca0bbb9db..ec2207b8da 100644
--- a/actionpack/lib/action_controller/metal.rb
+++ b/actionpack/lib/action_controller/metal.rb
@@ -35,7 +35,6 @@ module ActionController
end
private
-
INCLUDE = ->(list, action) { list.include? action }
EXCLUDE = ->(list, action) { !list.include? action }
NULL = ->(list, action) { true }
diff --git a/actionpack/lib/action_controller/metal/content_security_policy.rb b/actionpack/lib/action_controller/metal/content_security_policy.rb
index b8fab4ebe3..ebd90f07c8 100644
--- a/actionpack/lib/action_controller/metal/content_security_policy.rb
+++ b/actionpack/lib/action_controller/metal/content_security_policy.rb
@@ -36,7 +36,6 @@ module ActionController #:nodoc:
end
private
-
def content_security_policy?
request.content_security_policy
end
diff --git a/actionpack/lib/action_controller/metal/data_streaming.rb b/actionpack/lib/action_controller/metal/data_streaming.rb
index 9ef4f50df1..879745a895 100644
--- a/actionpack/lib/action_controller/metal/data_streaming.rb
+++ b/actionpack/lib/action_controller/metal/data_streaming.rb
@@ -53,7 +53,7 @@ module ActionController #:nodoc:
#
# Show a 404 page in the browser:
#
- # send_file '/path/to/404.html', type: 'text/html; charset=utf-8', status: 404
+ # send_file '/path/to/404.html', type: 'text/html; charset=utf-8', disposition: 'inline', status: 404
#
# Read about the other Content-* HTTP headers if you'd like to
# provide the user with more information (such as Content-Description) in
diff --git a/actionpack/lib/action_controller/metal/feature_policy.rb b/actionpack/lib/action_controller/metal/feature_policy.rb
new file mode 100644
index 0000000000..a627eabea6
--- /dev/null
+++ b/actionpack/lib/action_controller/metal/feature_policy.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+module ActionController #:nodoc:
+ # HTTP Feature Policy is a web standard for defining a mechanism to
+ # allow and deny the use of browser features in its own context, and
+ # in content within any <iframe> elements in the document.
+ #
+ # Full details of HTTP Feature Policy specification and guidelines can
+ # be found at MDN:
+ #
+ # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Feature-Policy
+ #
+ # Examples of usage:
+ #
+ # # Global policy
+ # Rails.application.config.feature_policy do |f|
+ # f.camera :none
+ # f.gyroscope :none
+ # f.microphone :none
+ # f.usb :none
+ # f.fullscreen :self
+ # f.payment :self, "https://secure.example.com"
+ # end
+ #
+ # # Controller level policy
+ # class PagesController < ApplicationController
+ # feature_policy do |p|
+ # p.geolocation "https://example.com"
+ # end
+ # end
+ module FeaturePolicy
+ extend ActiveSupport::Concern
+
+ module ClassMethods
+ def feature_policy(**options, &block)
+ before_action(options) do
+ if block_given?
+ policy = request.feature_policy.clone
+ yield policy
+ request.feature_policy = policy
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/actionpack/lib/action_controller/metal/instrumentation.rb b/actionpack/lib/action_controller/metal/instrumentation.rb
index 51fac08749..6f7fc0d624 100644
--- a/actionpack/lib/action_controller/metal/instrumentation.rb
+++ b/actionpack/lib/action_controller/metal/instrumentation.rb
@@ -69,7 +69,6 @@ module ActionController
end
private
-
# A hook invoked every time a before callback is halted.
def halted_callback_hook(filter)
ActiveSupport::Notifications.instrument("halted_callback.action_controller", filter: filter)
diff --git a/actionpack/lib/action_controller/metal/live.rb b/actionpack/lib/action_controller/metal/live.rb
index dd69930e25..4454ba1e3d 100644
--- a/actionpack/lib/action_controller/metal/live.rb
+++ b/actionpack/lib/action_controller/metal/live.rb
@@ -107,7 +107,6 @@ module ActionController
end
private
-
def perform_write(json, options)
current_options = @options.merge(options).stringify_keys
@@ -205,7 +204,6 @@ module ActionController
end
private
-
def each_chunk(&block)
loop do
str = nil
@@ -220,7 +218,6 @@ module ActionController
class Response < ActionDispatch::Response #:nodoc: all
private
-
def before_committed
super
jar = request.cookie_jar
@@ -286,7 +283,6 @@ module ActionController
end
private
-
# Spawn a new thread to serve up the controller in. This is to get
# around the fact that Rack isn't based around IOs and we need to use
# a thread to stream data from the response bodies. Nobody should call
diff --git a/actionpack/lib/action_controller/metal/params_wrapper.rb b/actionpack/lib/action_controller/metal/params_wrapper.rb
index e635abec8e..150ae2666c 100644
--- a/actionpack/lib/action_controller/metal/params_wrapper.rb
+++ b/actionpack/lib/action_controller/metal/params_wrapper.rb
@@ -246,7 +246,6 @@ module ActionController
end
private
-
# Returns the wrapper key which will be used to store wrapped parameters.
def _wrapper_key
_wrapper_options.name
diff --git a/actionpack/lib/action_controller/metal/rendering.rb b/actionpack/lib/action_controller/metal/rendering.rb
index 7f7c736965..efa5de313c 100644
--- a/actionpack/lib/action_controller/metal/rendering.rb
+++ b/actionpack/lib/action_controller/metal/rendering.rb
@@ -53,7 +53,6 @@ module ActionController
end
private
-
def _process_variant(options)
if defined?(request) && !request.nil? && request.variant.present?
options[:variant] = request.variant
diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
index 4bf8d90b69..5a5c04234b 100644
--- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb
+++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
@@ -151,7 +151,6 @@ module ActionController #:nodoc:
end
private
-
def protection_method_class(name)
ActionController::RequestForgeryProtection::ProtectionMethods.const_get(name.to_s.classify)
rescue NameError
@@ -175,7 +174,6 @@ module ActionController #:nodoc:
end
private
-
class NullSessionHash < Rack::Session::Abstract::SessionHash #:nodoc:
def initialize(req)
super(nil, req)
diff --git a/actionpack/lib/action_controller/metal/streaming.rb b/actionpack/lib/action_controller/metal/streaming.rb
index 8dc01a5eb9..94a62e5cab 100644
--- a/actionpack/lib/action_controller/metal/streaming.rb
+++ b/actionpack/lib/action_controller/metal/streaming.rb
@@ -196,7 +196,6 @@ module ActionController #:nodoc:
extend ActiveSupport::Concern
private
-
# Set proper cache control and transfer encoding when streaming
def _process_options(options)
super
diff --git a/actionpack/lib/action_controller/metal/strong_parameters.rb b/actionpack/lib/action_controller/metal/strong_parameters.rb
index 6a07a73d94..6fbd52dd51 100644
--- a/actionpack/lib/action_controller/metal/strong_parameters.rb
+++ b/actionpack/lib/action_controller/metal/strong_parameters.rb
@@ -259,6 +259,11 @@ module ActionController
@parameters == other
end
end
+ alias eql? ==
+
+ def hash
+ [@parameters.hash, @permitted].hash
+ end
# Returns a safe <tt>ActiveSupport::HashWithIndifferentAccess</tt>
# representation of the parameters with all unpermitted keys removed.
diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb
index 57921f32b7..47e0099f20 100644
--- a/actionpack/lib/action_controller/test_case.rb
+++ b/actionpack/lib/action_controller/test_case.rb
@@ -158,7 +158,6 @@ module ActionController
end.new
private
-
def params_parsers
super.merge @custom_param_parsers
end
@@ -208,7 +207,6 @@ module ActionController
end
private
-
def load!
@id
end
@@ -594,7 +592,6 @@ module ActionController
end
private
-
def scrub_env!(env)
env.delete_if { |k, v| k =~ /^(action_dispatch|rack)\.request/ }
env.delete_if { |k, v| k =~ /^action_dispatch\.rescue/ }
diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb
index 6a4ba9af4a..67d303a368 100644
--- a/actionpack/lib/action_dispatch.rb
+++ b/actionpack/lib/action_dispatch.rb
@@ -43,6 +43,7 @@ module ActionDispatch
eager_autoload do
autoload_under "http" do
autoload :ContentSecurityPolicy
+ autoload :FeaturePolicy
autoload :Request
autoload :Response
end
diff --git a/actionpack/lib/action_dispatch/http/cache.rb b/actionpack/lib/action_dispatch/http/cache.rb
index 8cc84ff36c..7be30be77a 100644
--- a/actionpack/lib/action_dispatch/http/cache.rb
+++ b/actionpack/lib/action_dispatch/http/cache.rb
@@ -123,7 +123,6 @@ module ActionDispatch
end
private
-
DATE = "Date"
LAST_MODIFIED = "Last-Modified"
SPECIAL_KEYS = Set.new(%w[extras no-cache max-age public private must-revalidate])
diff --git a/actionpack/lib/action_dispatch/http/content_security_policy.rb b/actionpack/lib/action_dispatch/http/content_security_policy.rb
index b1e5a28be5..9c430b57e3 100644
--- a/actionpack/lib/action_dispatch/http/content_security_policy.rb
+++ b/actionpack/lib/action_dispatch/http/content_security_policy.rb
@@ -22,15 +22,15 @@ module ActionDispatch #:nodoc:
if policy = request.content_security_policy
nonce = request.content_security_policy_nonce
+ nonce_directives = request.content_security_policy_nonce_directives
context = request.controller_instance || request
- headers[header_name(request)] = policy.build(context, nonce)
+ headers[header_name(request)] = policy.build(context, nonce, nonce_directives)
end
response
end
private
-
def html_response?(headers)
if content_type = headers[CONTENT_TYPE]
content_type =~ /html/
@@ -55,6 +55,7 @@ module ActionDispatch #:nodoc:
POLICY_REPORT_ONLY = "action_dispatch.content_security_policy_report_only"
NONCE_GENERATOR = "action_dispatch.content_security_policy_nonce_generator"
NONCE = "action_dispatch.content_security_policy_nonce"
+ NONCE_DIRECTIVES = "action_dispatch.content_security_policy_nonce_directives"
def content_security_policy
get_header(POLICY)
@@ -80,6 +81,14 @@ module ActionDispatch #:nodoc:
set_header(NONCE_GENERATOR, generator)
end
+ def content_security_policy_nonce_directives
+ get_header(NONCE_DIRECTIVES)
+ end
+
+ def content_security_policy_nonce_directives=(generator)
+ set_header(NONCE_DIRECTIVES, generator)
+ end
+
def content_security_policy_nonce
if content_security_policy_nonce_generator
if nonce = get_header(NONCE)
@@ -91,7 +100,6 @@ module ActionDispatch #:nodoc:
end
private
-
def generate_content_security_policy_nonce
content_security_policy_nonce_generator.call(self)
end
@@ -129,13 +137,17 @@ module ActionDispatch #:nodoc:
object_src: "object-src",
prefetch_src: "prefetch-src",
script_src: "script-src",
+ script_src_attr: "script-src-attr",
+ script_src_elem: "script-src-elem",
style_src: "style-src",
+ style_src_attr: "style-src-attr",
+ style_src_elem: "style-src-elem",
worker_src: "worker-src"
}.freeze
- NONCE_DIRECTIVES = %w[script-src style-src].freeze
+ DEFAULT_NONCE_DIRECTIVES = %w[script-src style-src].freeze
- private_constant :MAPPINGS, :DIRECTIVES, :NONCE_DIRECTIVES
+ private_constant :MAPPINGS, :DIRECTIVES, :DEFAULT_NONCE_DIRECTIVES
attr_reader :directives
@@ -204,8 +216,9 @@ module ActionDispatch #:nodoc:
end
end
- def build(context = nil, nonce = nil)
- build_directives(context, nonce).compact.join("; ")
+ def build(context = nil, nonce = nil, nonce_directives = nil)
+ nonce_directives = DEFAULT_NONCE_DIRECTIVES if nonce_directives.nil?
+ build_directives(context, nonce, nonce_directives).compact.join("; ")
end
private
@@ -228,10 +241,10 @@ module ActionDispatch #:nodoc:
end
end
- def build_directives(context, nonce)
+ def build_directives(context, nonce, nonce_directives)
@directives.map do |directive, sources|
if sources.is_a?(Array)
- if nonce && nonce_directive?(directive)
+ if nonce && nonce_directive?(directive, nonce_directives)
"#{directive} #{build_directive(sources, context).join(' ')} 'nonce-#{nonce}'"
else
"#{directive} #{build_directive(sources, context).join(' ')}"
@@ -266,8 +279,8 @@ module ActionDispatch #:nodoc:
end
end
- def nonce_directive?(directive)
- NONCE_DIRECTIVES.include?(directive)
+ def nonce_directive?(directive, nonce_directives)
+ nonce_directives.include?(directive)
end
end
end
diff --git a/actionpack/lib/action_dispatch/http/feature_policy.rb b/actionpack/lib/action_dispatch/http/feature_policy.rb
new file mode 100644
index 0000000000..592b6e4393
--- /dev/null
+++ b/actionpack/lib/action_dispatch/http/feature_policy.rb
@@ -0,0 +1,168 @@
+# frozen_string_literal: true
+
+require "active_support/core_ext/object/deep_dup"
+
+module ActionDispatch #:nodoc:
+ class FeaturePolicy
+ class Middleware
+ CONTENT_TYPE = "Content-Type"
+ POLICY = "Feature-Policy"
+
+ def initialize(app)
+ @app = app
+ end
+
+ def call(env)
+ request = ActionDispatch::Request.new(env)
+ _, headers, _ = response = @app.call(env)
+
+ return response unless html_response?(headers)
+ return response if policy_present?(headers)
+
+ if policy = request.feature_policy
+ headers[POLICY] = policy.build(request.controller_instance)
+ end
+
+ if policy_empty?(policy)
+ headers.delete(POLICY)
+ end
+
+ response
+ end
+
+ private
+ def html_response?(headers)
+ if content_type = headers[CONTENT_TYPE]
+ content_type =~ /html/
+ end
+ end
+
+ def policy_present?(headers)
+ headers[POLICY]
+ end
+
+ def policy_empty?(policy)
+ policy.try(:directives) && policy.directives.empty?
+ end
+ end
+
+ module Request
+ POLICY = "action_dispatch.feature_policy"
+
+ def feature_policy
+ get_header(POLICY)
+ end
+
+ def feature_policy=(policy)
+ set_header(POLICY, policy)
+ end
+ end
+
+ MAPPINGS = {
+ self: "'self'",
+ none: "'none'",
+ }.freeze
+
+ # List of available features can be found at
+ # https://github.com/WICG/feature-policy/blob/master/features.md#policy-controlled-features
+ DIRECTIVES = {
+ accelerometer: "accelerometer",
+ ambient_light_sensor: "ambient-light-sensor",
+ autoplay: "autoplay",
+ camera: "camera",
+ encrypted_media: "encrypted-media",
+ fullscreen: "fullscreen",
+ geolocation: "geolocation",
+ gyroscope: "gyroscope",
+ magnetometer: "magnetometer",
+ microphone: "microphone",
+ midi: "midi",
+ payment: "payment",
+ picture_in_picture: "picture-in-picture",
+ speaker: "speaker",
+ usb: "usb",
+ vibrate: "vibrate",
+ vr: "vr",
+ }.freeze
+
+ private_constant :MAPPINGS, :DIRECTIVES
+
+ attr_reader :directives
+
+ def initialize
+ @directives = {}
+ yield self if block_given?
+ end
+
+ def initialize_copy(other)
+ @directives = other.directives.deep_dup
+ end
+
+ DIRECTIVES.each do |name, directive|
+ define_method(name) do |*sources|
+ if sources.first
+ @directives[directive] = apply_mappings(sources)
+ else
+ @directives.delete(directive)
+ end
+ end
+ end
+
+ def build(context = nil)
+ build_directives(context).compact.join("; ")
+ end
+
+ private
+ def apply_mappings(sources)
+ sources.map do |source|
+ case source
+ when Symbol
+ apply_mapping(source)
+ when String, Proc
+ source
+ else
+ raise ArgumentError, "Invalid HTTP feature policy source: #{source.inspect}"
+ end
+ end
+ end
+
+ def apply_mapping(source)
+ MAPPINGS.fetch(source) do
+ raise ArgumentError, "Unknown HTTP feature policy source mapping: #{source.inspect}"
+ end
+ end
+
+ def build_directives(context)
+ @directives.map do |directive, sources|
+ if sources.is_a?(Array)
+ "#{directive} #{build_directive(sources, context).join(' ')}"
+ elsif sources
+ directive
+ else
+ nil
+ end
+ end
+ end
+
+ def build_directive(sources, context)
+ sources.map { |source| resolve_source(source, context) }
+ end
+
+ def resolve_source(source, context)
+ case source
+ when String
+ source
+ when Symbol
+ source.to_s
+ when Proc
+ if context.nil?
+ raise RuntimeError, "Missing context for the dynamic feature policy source: #{source.inspect}"
+ else
+ context.instance_exec(&source)
+ end
+ else
+ raise RuntimeError, "Unexpected feature policy source: #{source.inspect}"
+ end
+ end
+ end
+end
diff --git a/actionpack/lib/action_dispatch/http/filter_parameters.rb b/actionpack/lib/action_dispatch/http/filter_parameters.rb
index cbb772175c..7a7a493f64 100644
--- a/actionpack/lib/action_dispatch/http/filter_parameters.rb
+++ b/actionpack/lib/action_dispatch/http/filter_parameters.rb
@@ -56,7 +56,6 @@ module ActionDispatch
end
private
-
def parameter_filter # :doc:
parameter_filter_for fetch_header("action_dispatch.parameter_filter") {
return NULL_PARAM_FILTER
diff --git a/actionpack/lib/action_dispatch/http/filter_redirect.rb b/actionpack/lib/action_dispatch/http/filter_redirect.rb
index 8c4e852235..d780d5f793 100644
--- a/actionpack/lib/action_dispatch/http/filter_redirect.rb
+++ b/actionpack/lib/action_dispatch/http/filter_redirect.rb
@@ -14,7 +14,6 @@ module ActionDispatch
end
private
-
def location_filters
if request
request.get_header("action_dispatch.redirect_filter") || []
diff --git a/actionpack/lib/action_dispatch/http/headers.rb b/actionpack/lib/action_dispatch/http/headers.rb
index 6c7d24d2d0..6ab913bfd0 100644
--- a/actionpack/lib/action_dispatch/http/headers.rb
+++ b/actionpack/lib/action_dispatch/http/headers.rb
@@ -116,7 +116,6 @@ module ActionDispatch
def env; @req.env.dup; end
private
-
# Converts an HTTP header name to an environment variable name if it is
# not contained within the headers hash.
def env_name(key)
diff --git a/actionpack/lib/action_dispatch/http/mime_negotiation.rb b/actionpack/lib/action_dispatch/http/mime_negotiation.rb
index 4e81ba12a5..a2cac49082 100644
--- a/actionpack/lib/action_dispatch/http/mime_negotiation.rb
+++ b/actionpack/lib/action_dispatch/http/mime_negotiation.rb
@@ -154,7 +154,6 @@ module ActionDispatch
end
private
-
BROWSER_LIKE_ACCEPTS = /,\s*\*\/\*|\*\/\*\s*,/
def valid_accept_header # :doc:
diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb
index 88b3a93211..ed1d50f3b9 100644
--- a/actionpack/lib/action_dispatch/http/mime_type.rb
+++ b/actionpack/lib/action_dispatch/http/mime_type.rb
@@ -290,11 +290,9 @@ module Mime
def all?; false; end
protected
-
attr_reader :string, :synonyms
private
-
def to_ary; end
def to_a; end
diff --git a/actionpack/lib/action_dispatch/http/parameters.rb b/actionpack/lib/action_dispatch/http/parameters.rb
index 13d0963a33..3c16817af3 100644
--- a/actionpack/lib/action_dispatch/http/parameters.rb
+++ b/actionpack/lib/action_dispatch/http/parameters.rb
@@ -85,7 +85,6 @@ module ActionDispatch
end
private
-
def set_binary_encoding(params, controller, action)
return params unless controller && controller.valid_encoding?
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb
index 44f23940d3..4ac7c5c2bd 100644
--- a/actionpack/lib/action_dispatch/http/request.rb
+++ b/actionpack/lib/action_dispatch/http/request.rb
@@ -23,6 +23,7 @@ module ActionDispatch
include ActionDispatch::Http::FilterParameters
include ActionDispatch::Http::URL
include ActionDispatch::ContentSecurityPolicy::Request
+ include ActionDispatch::FeaturePolicy::Request
include Rack::Request::Env
autoload :Session, "action_dispatch/request/session"
diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb
index e5cffccf35..ea3692951f 100644
--- a/actionpack/lib/action_dispatch/http/response.rb
+++ b/actionpack/lib/action_dispatch/http/response.rb
@@ -86,6 +86,7 @@ module ActionDispatch # :nodoc:
cattr_accessor :default_charset, default: "utf-8"
cattr_accessor :default_headers
+ cattr_accessor :return_only_media_type_on_content_type, default: false
include Rack::Response::Helpers
# Aliasing these off because AD::Http::Cache::Response defines them.
@@ -143,7 +144,6 @@ module ActionDispatch # :nodoc:
end
private
-
def each_chunk(&block)
@buf.each(&block)
end
@@ -244,7 +244,17 @@ module ActionDispatch # :nodoc:
# Content type of response.
def content_type
- super.presence
+ if self.class.return_only_media_type_on_content_type
+ ActiveSupport::Deprecation.warn(
+ "Rails 6.1 will return Content-Type header without modification." \
+ " If you want just the MIME type, please use `#media_type` instead."
+ )
+
+ content_type = super
+ content_type ? content_type.split(/;\s*charset=/)[0].presence : content_type
+ else
+ super.presence
+ end
end
# Media type of response.
@@ -409,7 +419,6 @@ module ActionDispatch # :nodoc:
end
private
-
ContentTypeHeader = Struct.new :mime_type, :charset
NullContentTypeHeader = ContentTypeHeader.new nil, nil
diff --git a/actionpack/lib/action_dispatch/http/url.rb b/actionpack/lib/action_dispatch/http/url.rb
index 8227749986..3b0f6378ea 100644
--- a/actionpack/lib/action_dispatch/http/url.rb
+++ b/actionpack/lib/action_dispatch/http/url.rb
@@ -78,7 +78,6 @@ module ActionDispatch
end
private
-
def add_params(path, params)
params = { params: params } unless params.is_a?(Hash)
params.reject! { |_, v| v.to_param.nil? }
diff --git a/actionpack/lib/action_dispatch/journey/formatter.rb b/actionpack/lib/action_dispatch/journey/formatter.rb
index 53c404ee7c..a4861719f8 100644
--- a/actionpack/lib/action_dispatch/journey/formatter.rb
+++ b/actionpack/lib/action_dispatch/journey/formatter.rb
@@ -62,7 +62,6 @@ module ActionDispatch
end
private
-
def extract_parameterized_parts(route, options, recall, parameterize = nil)
parameterized_parts = recall.merge(options)
diff --git a/actionpack/lib/action_dispatch/journey/gtg/builder.rb b/actionpack/lib/action_dispatch/journey/gtg/builder.rb
index 44c31053cb..2600e7fb70 100644
--- a/actionpack/lib/action_dispatch/journey/gtg/builder.rb
+++ b/actionpack/lib/action_dispatch/journey/gtg/builder.rb
@@ -128,7 +128,6 @@ module ActionDispatch
end
private
-
def followpos_table
@followpos ||= build_followpos
end
diff --git a/actionpack/lib/action_dispatch/journey/gtg/transition_table.rb b/actionpack/lib/action_dispatch/journey/gtg/transition_table.rb
index ea647e051a..5003e92f43 100644
--- a/actionpack/lib/action_dispatch/journey/gtg/transition_table.rb
+++ b/actionpack/lib/action_dispatch/journey/gtg/transition_table.rb
@@ -141,7 +141,6 @@ module ActionDispatch
end
private
-
def states_hash_for(sym)
case sym
when String
diff --git a/actionpack/lib/action_dispatch/journey/nfa/transition_table.rb b/actionpack/lib/action_dispatch/journey/nfa/transition_table.rb
index fe55861507..b36003089d 100644
--- a/actionpack/lib/action_dispatch/journey/nfa/transition_table.rb
+++ b/actionpack/lib/action_dispatch/journey/nfa/transition_table.rb
@@ -94,7 +94,6 @@ module ActionDispatch
end
private
-
def inverted
return @inverted if @inverted
diff --git a/actionpack/lib/action_dispatch/journey/path/pattern.rb b/actionpack/lib/action_dispatch/journey/path/pattern.rb
index dee2980eb1..e4ba82ebdd 100644
--- a/actionpack/lib/action_dispatch/journey/path/pattern.rb
+++ b/actionpack/lib/action_dispatch/journey/path/pattern.rb
@@ -174,7 +174,6 @@ module ActionDispatch
end
private
-
def regexp_visitor
@anchored ? AnchoredRegexp : UnanchoredRegexp
end
diff --git a/actionpack/lib/action_dispatch/journey/router.rb b/actionpack/lib/action_dispatch/journey/router.rb
index 89a164f968..4a6639af74 100644
--- a/actionpack/lib/action_dispatch/journey/router.rb
+++ b/actionpack/lib/action_dispatch/journey/router.rb
@@ -81,7 +81,6 @@ module ActionDispatch
end
private
-
def partitioned_routes
routes.partition { |r|
r.path.anchored && r.ast.grep(Nodes::Symbol).all? { |n| n.default_regexp? }
diff --git a/actionpack/lib/action_dispatch/journey/routes.rb b/actionpack/lib/action_dispatch/journey/routes.rb
index 3ba8361d77..3f055db66d 100644
--- a/actionpack/lib/action_dispatch/journey/routes.rb
+++ b/actionpack/lib/action_dispatch/journey/routes.rb
@@ -71,7 +71,6 @@ module ActionDispatch
end
private
-
def clear_cache!
@ast = nil
@simulator = nil
diff --git a/actionpack/lib/action_dispatch/journey/scanner.rb b/actionpack/lib/action_dispatch/journey/scanner.rb
index 2a075862e9..eb6fd17aa7 100644
--- a/actionpack/lib/action_dispatch/journey/scanner.rb
+++ b/actionpack/lib/action_dispatch/journey/scanner.rb
@@ -33,7 +33,6 @@ module ActionDispatch
end
private
-
# takes advantage of String @- deduping capabilities in Ruby 2.5 upwards
# see: https://bugs.ruby-lang.org/issues/13077
def dedup_scan(regex)
diff --git a/actionpack/lib/action_dispatch/journey/visitors.rb b/actionpack/lib/action_dispatch/journey/visitors.rb
index d2619cbf3a..ff26c9a3b0 100644
--- a/actionpack/lib/action_dispatch/journey/visitors.rb
+++ b/actionpack/lib/action_dispatch/journey/visitors.rb
@@ -59,7 +59,6 @@ module ActionDispatch
end
private
-
def visit(node)
send(DISPATCH_CACHE[node.type], node)
end
@@ -168,7 +167,6 @@ module ActionDispatch
class String < FunctionalVisitor # :nodoc:
private
-
def binary(node, seed)
visit(node.right, visit(node.left, seed))
end
@@ -214,7 +212,6 @@ module ActionDispatch
end
private
-
def binary(node, seed)
seed.last.concat node.children.map { |c|
"#{node.object_id} -> #{c.object_id};"
diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb
index dac60a13c6..642f155085 100644
--- a/actionpack/lib/action_dispatch/middleware/cookies.rb
+++ b/actionpack/lib/action_dispatch/middleware/cookies.rb
@@ -252,7 +252,6 @@ module ActionDispatch
end
private
-
def upgrade_legacy_hmac_aes_cbc_cookies?
request.secret_key_base.present? &&
request.encrypted_signed_cookie_salt.present? &&
@@ -428,7 +427,6 @@ module ActionDispatch
mattr_accessor :always_write_cookie, default: false
private
-
def escape(string)
::Rack::Utils.escape(string)
end
diff --git a/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb b/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
index 59113e13f4..e546d1c11f 100644
--- a/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
+++ b/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
@@ -42,7 +42,6 @@ module ActionDispatch
end
private
-
def invoke_interceptors(request, exception)
backtrace_cleaner = request.get_header("action_dispatch.backtrace_cleaner")
wrapper = ExceptionWrapper.new(backtrace_cleaner, exception)
@@ -138,9 +137,7 @@ module ActionDispatch
return unless logger
exception = wrapper.exception
-
- trace = wrapper.application_trace
- trace = wrapper.framework_trace if trace.empty?
+ trace = wrapper.exception_trace
ActiveSupport::Deprecation.silence do
message = []
diff --git a/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb b/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
index 0cc56f5013..e4a2a51c57 100644
--- a/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
+++ b/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
@@ -36,18 +36,23 @@ module ActionDispatch
"ActionView::Template::Error"
]
+ cattr_accessor :silent_exceptions, default: [
+ "ActionController::RoutingError"
+ ]
+
attr_reader :backtrace_cleaner, :exception, :wrapped_causes, :line_number, :file
def initialize(backtrace_cleaner, exception)
@backtrace_cleaner = backtrace_cleaner
@exception = exception
+ @exception_class_name = @exception.class.name
@wrapped_causes = wrapped_causes_for(exception, backtrace_cleaner)
expand_backtrace if exception.is_a?(SyntaxError) || exception.cause.is_a?(SyntaxError)
end
def unwrapped_exception
- if wrapper_exceptions.include?(exception.class.to_s)
+ if wrapper_exceptions.include?(@exception_class_name)
exception.cause
else
exception
@@ -55,13 +60,19 @@ module ActionDispatch
end
def rescue_template
- @@rescue_templates[@exception.class.name]
+ @@rescue_templates[@exception_class_name]
end
def status_code
self.class.status_code_for_exception(unwrapped_exception.class.name)
end
+ def exception_trace
+ trace = application_trace
+ trace = framework_trace if trace.empty? && !silent_exceptions.include?(@exception_class_name)
+ trace
+ end
+
def application_trace
clean_backtrace(:silent)
end
@@ -130,7 +141,6 @@ module ActionDispatch
end
private
-
def backtrace
Array(@exception.backtrace)
end
diff --git a/actionpack/lib/action_dispatch/middleware/host_authorization.rb b/actionpack/lib/action_dispatch/middleware/host_authorization.rb
index b7dff1df41..de7739b9b6 100644
--- a/actionpack/lib/action_dispatch/middleware/host_authorization.rb
+++ b/actionpack/lib/action_dispatch/middleware/host_authorization.rb
@@ -30,7 +30,6 @@ module ActionDispatch
end
private
-
def sanitize_hosts(hosts)
Array(hosts).map do |host|
case host
@@ -87,7 +86,6 @@ module ActionDispatch
end
private
-
def authorized?(request)
origin_host = request.get_header("HTTP_HOST").to_s.sub(/:\d+\z/, "")
forwarded_host = request.x_forwarded_host.to_s.split(/,\s?/).last.to_s.sub(/:\d+\z/, "")
diff --git a/actionpack/lib/action_dispatch/middleware/public_exceptions.rb b/actionpack/lib/action_dispatch/middleware/public_exceptions.rb
index a88ad40f21..3a2a1d7334 100644
--- a/actionpack/lib/action_dispatch/middleware/public_exceptions.rb
+++ b/actionpack/lib/action_dispatch/middleware/public_exceptions.rb
@@ -32,7 +32,6 @@ module ActionDispatch
end
private
-
def render(status, content_type, body)
format = "to_#{content_type.to_sym}" if content_type
if format && body.respond_to?(format)
diff --git a/actionpack/lib/action_dispatch/middleware/remote_ip.rb b/actionpack/lib/action_dispatch/middleware/remote_ip.rb
index a5667573f4..c5d4a0bd31 100644
--- a/actionpack/lib/action_dispatch/middleware/remote_ip.rb
+++ b/actionpack/lib/action_dispatch/middleware/remote_ip.rb
@@ -156,7 +156,6 @@ module ActionDispatch
end
private
-
def ips_from(header) # :doc:
return [] unless header
# Split the comma-separated list into an array of strings.
diff --git a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb
index 5b0be96223..3815971acb 100644
--- a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb
+++ b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb
@@ -30,7 +30,6 @@ module ActionDispatch
end
private
-
def initialize_sid # :doc:
@default_options.delete(:sidbits)
@default_options.delete(:secure_random)
@@ -83,7 +82,6 @@ module ActionDispatch
include SessionObject
private
-
def set_cookie(request, session_id, cookie)
request.cookie_jar[key] = cookie
end
diff --git a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb
index 7c43c781c7..892d88803e 100644
--- a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb
+++ b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb
@@ -67,7 +67,6 @@ module ActionDispatch
end
private
-
def extract_session_id(req)
stale_session_check! do
unpacked_cookie_data(req)["session_id"]
diff --git a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb
index 767143a368..a35c0da3d9 100644
--- a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb
+++ b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb
@@ -40,7 +40,6 @@ module ActionDispatch
end
private
-
def render_exception(request, exception)
backtrace_cleaner = request.get_header "action_dispatch.backtrace_cleaner"
wrapper = ExceptionWrapper.new(backtrace_cleaner, exception)
diff --git a/actionpack/lib/action_dispatch/middleware/stack.rb b/actionpack/lib/action_dispatch/middleware/stack.rb
index 57e4adb457..775110d95e 100644
--- a/actionpack/lib/action_dispatch/middleware/stack.rb
+++ b/actionpack/lib/action_dispatch/middleware/stack.rb
@@ -134,7 +134,6 @@ module ActionDispatch
end
private
-
def assert_index(index, where)
i = index.is_a?(Integer) ? index : middlewares.index { |m| m.klass == index }
raise "No such middleware to insert #{where}: #{index.inspect}" unless i
diff --git a/actionpack/lib/action_dispatch/railtie.rb b/actionpack/lib/action_dispatch/railtie.rb
index 5f711c7348..2e09aed41d 100644
--- a/actionpack/lib/action_dispatch/railtie.rb
+++ b/actionpack/lib/action_dispatch/railtie.rb
@@ -23,6 +23,7 @@ module ActionDispatch
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.return_only_media_type_on_content_type = true
config.action_dispatch.default_headers = {
"X-Frame-Options" => "SAMEORIGIN",
@@ -43,6 +44,7 @@ module ActionDispatch
ActionDispatch::Request::Utils.perform_deep_munge = app.config.action_dispatch.perform_deep_munge
ActionDispatch::Response.default_charset = app.config.action_dispatch.default_charset || app.config.encoding
ActionDispatch::Response.default_headers = app.config.action_dispatch.default_headers
+ ActionDispatch::Response.return_only_media_type_on_content_type = app.config.action_dispatch.return_only_media_type_on_content_type
ActionDispatch::ExceptionWrapper.rescue_responses.merge!(config.action_dispatch.rescue_responses)
ActionDispatch::ExceptionWrapper.rescue_templates.merge!(config.action_dispatch.rescue_templates)
@@ -52,11 +54,5 @@ module ActionDispatch
ActionDispatch.test_app = app
end
-
- initializer "action_dispatch.system_tests" do |app|
- ActiveSupport.on_load(:action_dispatch_system_test_case) do
- include app.routes.url_helpers
- end
- end
end
end
diff --git a/actionpack/lib/action_dispatch/request/session.rb b/actionpack/lib/action_dispatch/request/session.rb
index bc5e0670e0..8faedf15b9 100644
--- a/actionpack/lib/action_dispatch/request/session.rb
+++ b/actionpack/lib/action_dispatch/request/session.rb
@@ -216,7 +216,6 @@ module ActionDispatch
end
private
-
def load_for_read!
load! if !loaded? && exists?
end
diff --git a/actionpack/lib/action_dispatch/routing/inspector.rb b/actionpack/lib/action_dispatch/routing/inspector.rb
index 413e524ef6..6e40a18009 100644
--- a/actionpack/lib/action_dispatch/routing/inspector.rb
+++ b/actionpack/lib/action_dispatch/routing/inspector.rb
@@ -177,7 +177,6 @@ module ActionDispatch
end
private
-
def draw_section(routes)
header_lengths = ["Prefix", "Verb", "URI Pattern"].map(&:length)
name_width, verb_width, path_width = widths(routes).zip(header_lengths).map(&:max)
@@ -210,7 +209,6 @@ module ActionDispatch
end
private
-
def draw_expanded_section(routes)
routes.map.each_with_index do |r, i|
<<~MESSAGE.chomp
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index 0aba484a45..d1100089b1 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -1673,7 +1673,6 @@ module ActionDispatch
end
private
-
def parent_resource
@scope[:scope_level_resource]
end
diff --git a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb
index 4de5f9e2f7..e3322e99ab 100644
--- a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb
+++ b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb
@@ -156,7 +156,6 @@ module ActionDispatch
end
private
-
def polymorphic_url_for_action(action, record_or_hash, options)
polymorphic_url(record_or_hash, options.merge(action: action))
end
@@ -323,7 +322,6 @@ module ActionDispatch
end
private
-
def polymorphic_mapping(target, record)
if record.respond_to?(:to_model)
target._routes.polymorphic_mappings[record.to_model.model_name.name]
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index bbb5762b3c..5b35b68c44 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -40,7 +40,6 @@ module ActionDispatch
end
private
-
def controller(req)
req.controller_class
rescue NameError => e
@@ -59,7 +58,6 @@ module ActionDispatch
end
private
-
def controller(_); @controller_class; end
end
@@ -215,7 +213,6 @@ module ActionDispatch
end
private
-
def optimized_helper(args)
params = parameterize_args(args) do
raise_generation_error(args)
diff --git a/actionpack/lib/action_dispatch/routing/url_for.rb b/actionpack/lib/action_dispatch/routing/url_for.rb
index fcb8ae296b..e02a6541c1 100644
--- a/actionpack/lib/action_dispatch/routing/url_for.rb
+++ b/actionpack/lib/action_dispatch/routing/url_for.rb
@@ -215,13 +215,11 @@ module ActionDispatch
end
protected
-
def optimize_routes_generation?
_routes.optimize_routes_generation? && default_url_options.empty?
end
private
-
def _with_routes(routes) # :doc:
old_routes, @_routes = @_routes, routes
yield
diff --git a/actionpack/lib/action_dispatch/system_test_case.rb b/actionpack/lib/action_dispatch/system_test_case.rb
index a7fb5fa330..9772beb8aa 100644
--- a/actionpack/lib/action_dispatch/system_test_case.rb
+++ b/actionpack/lib/action_dispatch/system_test_case.rb
@@ -4,6 +4,7 @@ gem "capybara", ">= 2.15"
require "capybara/dsl"
require "capybara/minitest"
+require "selenium/webdriver"
require "action_controller"
require "action_dispatch/system_testing/driver"
require "action_dispatch/system_testing/browser"
@@ -118,6 +119,11 @@ module ActionDispatch
def initialize(*) # :nodoc:
super
self.class.driver.use
+ @proxy_route = if ActionDispatch.test_app
+ Class.new { include ActionDispatch.test_app.routes.url_helpers }.new
+ else
+ nil
+ end
end
def self.start_application # :nodoc:
@@ -162,6 +168,14 @@ module ActionDispatch
default_url_options.merge(host: Capybara.app_host)
end
+ def method_missing(method, *args, &block)
+ if @proxy_route.respond_to?(method)
+ @proxy_route.send(method, *args, &block)
+ else
+ super
+ end
+ end
+
ActiveSupport.run_load_hooks(:action_dispatch_system_test_case, self)
end
diff --git a/actionpack/lib/action_dispatch/system_testing/browser.rb b/actionpack/lib/action_dispatch/system_testing/browser.rb
index c34907b6cb..e861e52f09 100644
--- a/actionpack/lib/action_dispatch/system_testing/browser.rb
+++ b/actionpack/lib/action_dispatch/system_testing/browser.rb
@@ -39,6 +39,29 @@ module ActionDispatch
end
end
+ # driver_path can be configured as a proc. The webdrivers gem uses this
+ # proc to update web drivers. Running this proc early allows us to only
+ # update the webdriver once and avoid race conditions when using
+ # parallel tests.
+ def preload
+ case type
+ when :chrome
+ if ::Selenium::WebDriver::Service.respond_to? :driver_path=
+ ::Selenium::WebDriver::Chrome::Service.driver_path.try(:call)
+ else
+ # Selenium <= v3.141.0
+ ::Selenium::WebDriver::Chrome.driver_path
+ end
+ when :firefox
+ if ::Selenium::WebDriver::Service.respond_to? :driver_path=
+ ::Selenium::WebDriver::Firefox::Service.driver_path.try(:call)
+ else
+ # Selenium <= v3.141.0
+ ::Selenium::WebDriver::Firefox.driver_path
+ end
+ end
+ end
+
private
def headless_chrome_browser_options
capabilities.args << "--headless"
diff --git a/actionpack/lib/action_dispatch/system_testing/driver.rb b/actionpack/lib/action_dispatch/system_testing/driver.rb
index 25a09dd918..15943a55ea 100644
--- a/actionpack/lib/action_dispatch/system_testing/driver.rb
+++ b/actionpack/lib/action_dispatch/system_testing/driver.rb
@@ -9,6 +9,8 @@ module ActionDispatch
@screen_size = options[:screen_size]
@options = options[:options]
@capabilities = capabilities
+
+ @browser.preload
end
def use
diff --git a/actionpack/lib/action_dispatch/testing/assertion_response.rb b/actionpack/lib/action_dispatch/testing/assertion_response.rb
index dc019db6ac..79af372cc1 100644
--- a/actionpack/lib/action_dispatch/testing/assertion_response.rb
+++ b/actionpack/lib/action_dispatch/testing/assertion_response.rb
@@ -35,7 +35,6 @@ module ActionDispatch
end
private
-
def code_from_name(name)
GENERIC_RESPONSE_CODES[name] || Rack::Utils::SYMBOL_TO_STATUS_CODE[name]
end
diff --git a/actionpack/lib/action_dispatch/testing/integration.rb b/actionpack/lib/action_dispatch/testing/integration.rb
index bb8b43ad4d..c5f8b816a4 100644
--- a/actionpack/lib/action_dispatch/testing/integration.rb
+++ b/actionpack/lib/action_dispatch/testing/integration.rb
@@ -3,7 +3,6 @@
require "stringio"
require "uri"
require "active_support/core_ext/kernel/singleton_class"
-require "active_support/core_ext/object/try"
require "rack/test"
require "minitest"