aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack')
-rw-r--r--actionpack/CHANGELOG.md16
-rw-r--r--actionpack/lib/abstract_controller/base.rb2
-rw-r--r--actionpack/lib/abstract_controller/helpers.rb2
-rw-r--r--actionpack/lib/abstract_controller/railties/routes_helpers.rb2
-rw-r--r--actionpack/lib/action_controller/caching.rb2
-rw-r--r--actionpack/lib/action_controller/log_subscriber.rb4
-rw-r--r--actionpack/lib/action_controller/metal/data_streaming.rb11
-rw-r--r--actionpack/lib/action_controller/metal/http_authentication.rb6
-rw-r--r--actionpack/lib/action_controller/metal/live.rb4
-rw-r--r--actionpack/lib/action_controller/metal/rendering.rb2
-rw-r--r--actionpack/lib/action_controller/metal/strong_parameters.rb8
-rw-r--r--actionpack/lib/action_controller/metal/url_for.rb2
-rw-r--r--actionpack/lib/action_controller/railties/helpers.rb2
-rw-r--r--actionpack/lib/action_dispatch/http/cache.rb18
-rw-r--r--actionpack/lib/action_dispatch/http/content_disposition.rb45
-rw-r--r--actionpack/lib/action_dispatch/http/content_security_policy.rb16
-rw-r--r--actionpack/lib/action_dispatch/http/filter_redirect.rb2
-rw-r--r--actionpack/lib/action_dispatch/http/mime_type.rb2
-rw-r--r--actionpack/lib/action_dispatch/http/parameter_filter.rb10
-rw-r--r--actionpack/lib/action_dispatch/http/request.rb20
-rw-r--r--actionpack/lib/action_dispatch/http/response.rb8
-rw-r--r--actionpack/lib/action_dispatch/http/url.rb6
-rw-r--r--actionpack/lib/action_dispatch/journey/formatter.rb2
-rw-r--r--actionpack/lib/action_dispatch/journey/router/utils.rb20
-rw-r--r--actionpack/lib/action_dispatch/journey/visitors.rb2
-rw-r--r--actionpack/lib/action_dispatch/middleware/cookies.rb38
-rw-r--r--actionpack/lib/action_dispatch/middleware/debug_exceptions.rb2
-rw-r--r--actionpack/lib/action_dispatch/middleware/debug_locks.rb10
-rw-r--r--actionpack/lib/action_dispatch/middleware/flash.rb2
-rw-r--r--actionpack/lib/action_dispatch/middleware/request_id.rb4
-rw-r--r--actionpack/lib/action_dispatch/middleware/ssl.rb14
-rw-r--r--actionpack/lib/action_dispatch/middleware/static.rb4
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb20
-rw-r--r--actionpack/lib/action_dispatch/routing/polymorphic_routes.rb4
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb31
-rw-r--r--actionpack/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb2
-rw-r--r--actionpack/lib/action_dispatch/testing/assertions/response.rb5
-rw-r--r--actionpack/lib/action_dispatch/testing/assertions/routing.rb5
-rw-r--r--actionpack/test/abstract_unit.rb19
-rw-r--r--actionpack/test/controller/base_test.rb4
-rw-r--r--actionpack/test/controller/http_token_authentication_test.rb2
-rw-r--r--actionpack/test/controller/live_stream_test.rb2
-rw-r--r--actionpack/test/controller/metal_test.rb2
-rw-r--r--actionpack/test/controller/mime/respond_to_test.rb2
-rw-r--r--actionpack/test/controller/new_base/bare_metal_test.rb2
-rw-r--r--actionpack/test/controller/new_base/render_context_test.rb9
-rw-r--r--actionpack/test/controller/parameters/accessors_test.rb18
-rw-r--r--actionpack/test/controller/redirect_test.rb7
-rw-r--r--actionpack/test/controller/routing_test.rb8
-rw-r--r--actionpack/test/controller/send_file_test.rb4
-rw-r--r--actionpack/test/controller/test_case_test.rb2
-rw-r--r--actionpack/test/dispatch/content_disposition_test.rb37
-rw-r--r--actionpack/test/dispatch/content_security_policy_test.rb15
-rw-r--r--actionpack/test/dispatch/debug_exceptions_test.rb2
-rw-r--r--actionpack/test/dispatch/middleware_stack_test.rb2
-rw-r--r--actionpack/test/dispatch/prefix_generation_test.rb2
-rw-r--r--actionpack/test/dispatch/request_test.rb2
-rw-r--r--actionpack/test/dispatch/routing/inspector_test.rb4
-rw-r--r--actionpack/test/dispatch/routing_test.rb31
-rw-r--r--actionpack/test/dispatch/static_test.rb4
-rw-r--r--actionpack/test/fixtures/alternate_helpers/foo_helper.rb2
-rw-r--r--actionpack/test/journey/router/utils_test.rb2
62 files changed, 376 insertions, 163 deletions
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index 7781980cab..c972c64766 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -1,3 +1,19 @@
+* Remove undocumented `params` option from `url_for` helper.
+
+ *Ilkka Oksanen*
+
+* Encode Content-Disposition filenames on `send_data` and `send_file`.
+ Previously, `send_data 'data', filename: "\u{3042}.txt"` sends
+ `"filename=\"\u{3042}.txt\""` as Content-Disposition and it can be
+ garbled.
+ Now it follows [RFC 2231](https://tools.ietf.org/html/rfc2231) and
+ [RFC 5987](https://tools.ietf.org/html/rfc5987) and sends
+ `"filename=\"%3F.txt\"; filename*=UTF-8''%E3%81%82.txt"`.
+ Most browsers can find filename correctly and old browsers fallback to ASCII
+ converted name.
+
+ *Fumiaki Matsushima*
+
* Expose `ActionController::Parameters#each_key` which allows iterating over
keys without allocating an array.
diff --git a/actionpack/lib/abstract_controller/base.rb b/actionpack/lib/abstract_controller/base.rb
index 6e6786d0be..bb42f2e119 100644
--- a/actionpack/lib/abstract_controller/base.rb
+++ b/actionpack/lib/abstract_controller/base.rb
@@ -104,7 +104,7 @@ module AbstractController
# ==== Returns
# * <tt>String</tt>
def controller_path
- @controller_path ||= name.sub(/Controller$/, "".freeze).underscore unless anonymous?
+ @controller_path ||= name.sub(/Controller$/, "").underscore unless anonymous?
end
# Refresh the cached action_methods when a new action_method is added.
diff --git a/actionpack/lib/abstract_controller/helpers.rb b/actionpack/lib/abstract_controller/helpers.rb
index 3191584770..3913259ecc 100644
--- a/actionpack/lib/abstract_controller/helpers.rb
+++ b/actionpack/lib/abstract_controller/helpers.rb
@@ -181,7 +181,7 @@ module AbstractController
end
def default_helper_module!
- module_name = name.sub(/Controller$/, "".freeze)
+ module_name = name.sub(/Controller$/, "")
module_path = module_name.underscore
helper module_path
rescue LoadError => e
diff --git a/actionpack/lib/abstract_controller/railties/routes_helpers.rb b/actionpack/lib/abstract_controller/railties/routes_helpers.rb
index b6e5631a4e..fbd93705ed 100644
--- a/actionpack/lib/abstract_controller/railties/routes_helpers.rb
+++ b/actionpack/lib/abstract_controller/railties/routes_helpers.rb
@@ -7,7 +7,7 @@ module AbstractController
Module.new do
define_method(:inherited) do |klass|
super(klass)
- if namespace = klass.parents.detect { |m| m.respond_to?(:railtie_routes_url_helpers) }
+ if namespace = klass.module_parents.detect { |m| m.respond_to?(:railtie_routes_url_helpers) }
klass.include(namespace.railtie_routes_url_helpers(include_path_helpers))
else
klass.include(routes.url_helpers(include_path_helpers))
diff --git a/actionpack/lib/action_controller/caching.rb b/actionpack/lib/action_controller/caching.rb
index 97775d1dc8..bf3b00a7b7 100644
--- a/actionpack/lib/action_controller/caching.rb
+++ b/actionpack/lib/action_controller/caching.rb
@@ -40,7 +40,7 @@ module ActionController
end
def instrument_name
- "action_controller".freeze
+ "action_controller"
end
end
end
diff --git a/actionpack/lib/action_controller/log_subscriber.rb b/actionpack/lib/action_controller/log_subscriber.rb
index 14f41eb55f..6de1fb2c19 100644
--- a/actionpack/lib/action_controller/log_subscriber.rb
+++ b/actionpack/lib/action_controller/log_subscriber.rb
@@ -26,8 +26,8 @@ module ActionController
exception_class_name = payload[:exception].first
status = ActionDispatch::ExceptionWrapper.status_code_for_exception(exception_class_name)
end
- message = "Completed #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]} in #{event.duration.round}ms".dup
- message << " (#{additions.join(" | ".freeze)})" unless additions.empty?
+ message = +"Completed #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]} in #{event.duration.round}ms"
+ message << " (#{additions.join(" | ")})" unless additions.empty?
message << "\n\n" if defined?(Rails.env) && Rails.env.development?
message
diff --git a/actionpack/lib/action_controller/metal/data_streaming.rb b/actionpack/lib/action_controller/metal/data_streaming.rb
index 5a82ccf668..9ef4f50df1 100644
--- a/actionpack/lib/action_controller/metal/data_streaming.rb
+++ b/actionpack/lib/action_controller/metal/data_streaming.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
require "action_controller/metal/exceptions"
+require "action_dispatch/http/content_disposition"
module ActionController #:nodoc:
# Methods for sending arbitrary data and for streaming files to the browser,
@@ -10,8 +11,8 @@ module ActionController #:nodoc:
include ActionController::Rendering
- DEFAULT_SEND_FILE_TYPE = "application/octet-stream".freeze #:nodoc:
- DEFAULT_SEND_FILE_DISPOSITION = "attachment".freeze #:nodoc:
+ DEFAULT_SEND_FILE_TYPE = "application/octet-stream" #:nodoc:
+ DEFAULT_SEND_FILE_DISPOSITION = "attachment" #:nodoc:
private
# Sends the file. This uses a server-appropriate method (such as X-Sendfile)
@@ -132,10 +133,8 @@ module ActionController #:nodoc:
end
disposition = options.fetch(:disposition, DEFAULT_SEND_FILE_DISPOSITION)
- unless disposition.nil?
- disposition = disposition.to_s
- disposition += %(; filename="#{options[:filename]}") if options[:filename]
- headers["Content-Disposition"] = disposition
+ if disposition
+ headers["Content-Disposition"] = ActionDispatch::Http::ContentDisposition.format(disposition: disposition, filename: options[:filename])
end
headers["Content-Transfer-Encoding"] = "binary"
diff --git a/actionpack/lib/action_controller/metal/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb
index a871ccd533..7036123d5d 100644
--- a/actionpack/lib/action_controller/metal/http_authentication.rb
+++ b/actionpack/lib/action_controller/metal/http_authentication.rb
@@ -127,7 +127,7 @@ module ActionController
def authentication_request(controller, realm, message)
message ||= "HTTP Basic: Access denied.\n"
- controller.headers["WWW-Authenticate"] = %(Basic realm="#{realm.tr('"'.freeze, "".freeze)}")
+ controller.headers["WWW-Authenticate"] = %(Basic realm="#{realm.tr('"', "")}")
controller.status = 401
controller.response_body = message
end
@@ -474,7 +474,7 @@ module ActionController
# This removes the <tt>"</tt> characters wrapping the value.
def rewrite_param_values(array_params)
- array_params.each { |param| (param[1] || "".dup).gsub! %r/^"|"$/, "" }
+ array_params.each { |param| (param[1] || +"").gsub! %r/^"|"$/, "" }
end
# This method takes an authorization body and splits up the key-value
@@ -511,7 +511,7 @@ module ActionController
# Returns nothing.
def authentication_request(controller, realm, message = nil)
message ||= "HTTP Token: Access denied.\n"
- controller.headers["WWW-Authenticate"] = %(Token realm="#{realm.tr('"'.freeze, "".freeze)}")
+ controller.headers["WWW-Authenticate"] = %(Token realm="#{realm.tr('"', "")}")
controller.__send__ :render, plain: message, status: :unauthorized
end
end
diff --git a/actionpack/lib/action_controller/metal/live.rb b/actionpack/lib/action_controller/metal/live.rb
index b1c2391afe..1482b2999a 100644
--- a/actionpack/lib/action_controller/metal/live.rb
+++ b/actionpack/lib/action_controller/metal/live.rb
@@ -117,7 +117,7 @@ module ActionController
end
end
- message = json.gsub("\n".freeze, "\ndata: ".freeze)
+ message = json.gsub("\n", "\ndata: ")
@stream.write "data: #{message}\n\n"
end
end
@@ -297,7 +297,7 @@ module ActionController
return unless logger
logger.fatal do
- message = "\n#{exception.class} (#{exception.message}):\n".dup
+ message = +"\n#{exception.class} (#{exception.message}):\n"
message << exception.annoted_source_code.to_s if exception.respond_to?(:annoted_source_code)
message << " " << exception.backtrace.join("\n ")
"#{message}\n\n"
diff --git a/actionpack/lib/action_controller/metal/rendering.rb b/actionpack/lib/action_controller/metal/rendering.rb
index 6d181e6456..7d0a944381 100644
--- a/actionpack/lib/action_controller/metal/rendering.rb
+++ b/actionpack/lib/action_controller/metal/rendering.rb
@@ -40,7 +40,7 @@ module ActionController
def render_to_string(*)
result = super
if result.respond_to?(:each)
- string = "".dup
+ string = +""
result.each { |r| string << r }
string
else
diff --git a/actionpack/lib/action_controller/metal/strong_parameters.rb b/actionpack/lib/action_controller/metal/strong_parameters.rb
index a37f08d944..c1272ce667 100644
--- a/actionpack/lib/action_controller/metal/strong_parameters.rb
+++ b/actionpack/lib/action_controller/metal/strong_parameters.rb
@@ -348,6 +348,14 @@ module ActionController
end
alias_method :each, :each_pair
+ # Convert all hashes in values into parameters, then yield each value in
+ # the same way as <tt>Hash#each_value</tt>.
+ def each_value(&block)
+ @parameters.each_pair do |key, value|
+ yield [convert_hashes_to_parameters(key, value)]
+ end
+ end
+
# Attribute that keeps track of converted arrays, if any, to avoid double
# looping in the common use case permit + mass-assignment. Defined in a
# method to instantiate it only if needed.
diff --git a/actionpack/lib/action_controller/metal/url_for.rb b/actionpack/lib/action_controller/metal/url_for.rb
index 84dbb59a63..f077e765ab 100644
--- a/actionpack/lib/action_controller/metal/url_for.rb
+++ b/actionpack/lib/action_controller/metal/url_for.rb
@@ -44,7 +44,7 @@ module ActionController
options[:original_script_name] = original_script_name
else
if same_origin
- options[:script_name] = request.script_name.empty? ? "".freeze : request.script_name.dup
+ options[:script_name] = request.script_name.empty? ? "" : request.script_name.dup
else
options[:script_name] = script_name
end
diff --git a/actionpack/lib/action_controller/railties/helpers.rb b/actionpack/lib/action_controller/railties/helpers.rb
index fa746fa9e8..75938108d6 100644
--- a/actionpack/lib/action_controller/railties/helpers.rb
+++ b/actionpack/lib/action_controller/railties/helpers.rb
@@ -7,7 +7,7 @@ module ActionController
super
return unless klass.respond_to?(:helpers_path=)
- if namespace = klass.parents.detect { |m| m.respond_to?(:railtie_helpers_paths) }
+ if namespace = klass.module_parents.detect { |m| m.respond_to?(:railtie_helpers_paths) }
paths = namespace.railtie_helpers_paths
else
paths = ActionController::Helpers.helpers_path
diff --git a/actionpack/lib/action_dispatch/http/cache.rb b/actionpack/lib/action_dispatch/http/cache.rb
index a7c7cfc1e5..f67b13f657 100644
--- a/actionpack/lib/action_dispatch/http/cache.rb
+++ b/actionpack/lib/action_dispatch/http/cache.rb
@@ -4,8 +4,8 @@ module ActionDispatch
module Http
module Cache
module Request
- HTTP_IF_MODIFIED_SINCE = "HTTP_IF_MODIFIED_SINCE".freeze
- HTTP_IF_NONE_MATCH = "HTTP_IF_NONE_MATCH".freeze
+ HTTP_IF_MODIFIED_SINCE = "HTTP_IF_MODIFIED_SINCE"
+ HTTP_IF_NONE_MATCH = "HTTP_IF_NONE_MATCH"
def if_modified_since
if since = get_header(HTTP_IF_MODIFIED_SINCE)
@@ -124,8 +124,8 @@ module ActionDispatch
private
- DATE = "Date".freeze
- LAST_MODIFIED = "Last-Modified".freeze
+ DATE = "Date"
+ LAST_MODIFIED = "Last-Modified"
SPECIAL_KEYS = Set.new(%w[extras no-cache max-age public private must-revalidate])
def generate_weak_etag(validators)
@@ -166,11 +166,11 @@ module ActionDispatch
@cache_control = cache_control_headers
end
- DEFAULT_CACHE_CONTROL = "max-age=0, private, must-revalidate".freeze
- NO_CACHE = "no-cache".freeze
- PUBLIC = "public".freeze
- PRIVATE = "private".freeze
- MUST_REVALIDATE = "must-revalidate".freeze
+ DEFAULT_CACHE_CONTROL = "max-age=0, private, must-revalidate"
+ NO_CACHE = "no-cache"
+ PUBLIC = "public"
+ PRIVATE = "private"
+ MUST_REVALIDATE = "must-revalidate"
def handle_conditional_get!
# Normally default cache control setting is handled by ETag
diff --git a/actionpack/lib/action_dispatch/http/content_disposition.rb b/actionpack/lib/action_dispatch/http/content_disposition.rb
new file mode 100644
index 0000000000..58164c1522
--- /dev/null
+++ b/actionpack/lib/action_dispatch/http/content_disposition.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+module ActionDispatch
+ module Http
+ class ContentDisposition # :nodoc:
+ def self.format(disposition:, filename:)
+ new(disposition: disposition, filename: filename).to_s
+ end
+
+ attr_reader :disposition, :filename
+
+ def initialize(disposition:, filename:)
+ @disposition = disposition
+ @filename = filename
+ end
+
+ TRADITIONAL_ESCAPED_CHAR = /[^ A-Za-z0-9!#$+.^_`|~-]/
+
+ def ascii_filename
+ 'filename="' + percent_escape(I18n.transliterate(filename), TRADITIONAL_ESCAPED_CHAR) + '"'
+ end
+
+ RFC_5987_ESCAPED_CHAR = /[^A-Za-z0-9!#$&+.^_`|~-]/
+
+ def utf8_filename
+ "filename*=UTF-8''" + percent_escape(filename, RFC_5987_ESCAPED_CHAR)
+ end
+
+ def to_s
+ if filename
+ "#{disposition}; #{ascii_filename}; #{utf8_filename}"
+ else
+ "#{disposition}"
+ end
+ end
+
+ private
+ def percent_escape(string, pattern)
+ string.gsub(pattern) do |char|
+ char.bytes.map { |byte| "%%%02X" % byte }.join
+ end
+ end
+ end
+ end
+end
diff --git a/actionpack/lib/action_dispatch/http/content_security_policy.rb b/actionpack/lib/action_dispatch/http/content_security_policy.rb
index 35041fd072..50953e32b5 100644
--- a/actionpack/lib/action_dispatch/http/content_security_policy.rb
+++ b/actionpack/lib/action_dispatch/http/content_security_policy.rb
@@ -5,9 +5,9 @@ require "active_support/core_ext/object/deep_dup"
module ActionDispatch #:nodoc:
class ContentSecurityPolicy
class Middleware
- CONTENT_TYPE = "Content-Type".freeze
- POLICY = "Content-Security-Policy".freeze
- POLICY_REPORT_ONLY = "Content-Security-Policy-Report-Only".freeze
+ CONTENT_TYPE = "Content-Type"
+ POLICY = "Content-Security-Policy"
+ POLICY_REPORT_ONLY = "Content-Security-Policy-Report-Only"
def initialize(app)
@app = app
@@ -50,10 +50,10 @@ module ActionDispatch #:nodoc:
end
module Request
- POLICY = "action_dispatch.content_security_policy".freeze
- POLICY_REPORT_ONLY = "action_dispatch.content_security_policy_report_only".freeze
- NONCE_GENERATOR = "action_dispatch.content_security_policy_nonce_generator".freeze
- NONCE = "action_dispatch.content_security_policy_nonce".freeze
+ POLICY = "action_dispatch.content_security_policy"
+ 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"
def content_security_policy
get_header(POLICY)
@@ -132,7 +132,7 @@ module ActionDispatch #:nodoc:
worker_src: "worker-src"
}.freeze
- NONCE_DIRECTIVES = %w[script-src].freeze
+ NONCE_DIRECTIVES = %w[script-src style-src].freeze
private_constant :MAPPINGS, :DIRECTIVES, :NONCE_DIRECTIVES
diff --git a/actionpack/lib/action_dispatch/http/filter_redirect.rb b/actionpack/lib/action_dispatch/http/filter_redirect.rb
index 25394fe5dd..8c4e852235 100644
--- a/actionpack/lib/action_dispatch/http/filter_redirect.rb
+++ b/actionpack/lib/action_dispatch/http/filter_redirect.rb
@@ -3,7 +3,7 @@
module ActionDispatch
module Http
module FilterRedirect
- FILTERED = "[FILTERED]".freeze # :nodoc:
+ FILTERED = "[FILTERED]" # :nodoc:
def filtered_location # :nodoc:
if location_filter_match?
diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb
index 295539281f..dd74695229 100644
--- a/actionpack/lib/action_dispatch/http/mime_type.rb
+++ b/actionpack/lib/action_dispatch/http/mime_type.rb
@@ -74,7 +74,7 @@ module Mime
def initialize(index, name, q = nil)
@index = index
@name = name
- q ||= 0.0 if @name == "*/*".freeze # Default wildcard match to end of list.
+ q ||= 0.0 if @name == "*/*" # Default wildcard match to end of list.
@q = ((q || 1.0).to_f * 100).to_i
end
diff --git a/actionpack/lib/action_dispatch/http/parameter_filter.rb b/actionpack/lib/action_dispatch/http/parameter_filter.rb
index 09aab631ed..6689092859 100644
--- a/actionpack/lib/action_dispatch/http/parameter_filter.rb
+++ b/actionpack/lib/action_dispatch/http/parameter_filter.rb
@@ -6,7 +6,7 @@ require "active_support/core_ext/array/extract"
module ActionDispatch
module Http
class ParameterFilter
- FILTERED = "[FILTERED]".freeze # :nodoc:
+ FILTERED = "[FILTERED]" # :nodoc:
def initialize(filters = [])
@filters = filters
@@ -39,11 +39,11 @@ module ActionDispatch
end
end
- deep_regexps = regexps.extract! { |r| r.to_s.include?("\\.".freeze) }
- deep_strings = strings.extract! { |s| s.include?("\\.".freeze) }
+ deep_regexps = regexps.extract! { |r| r.to_s.include?("\\.") }
+ deep_strings = strings.extract! { |s| s.include?("\\.") }
- regexps << Regexp.new(strings.join("|".freeze), true) unless strings.empty?
- deep_regexps << Regexp.new(deep_strings.join("|".freeze), true) unless deep_strings.empty?
+ regexps << Regexp.new(strings.join("|"), true) unless strings.empty?
+ deep_regexps << Regexp.new(deep_strings.join("|"), true) unless deep_strings.empty?
new regexps, deep_regexps, blocks
end
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb
index 3838b84a7a..7bc364d370 100644
--- a/actionpack/lib/action_dispatch/http/request.rb
+++ b/actionpack/lib/action_dispatch/http/request.rb
@@ -136,11 +136,11 @@ module ActionDispatch
end
def routes # :nodoc:
- get_header("action_dispatch.routes".freeze)
+ get_header("action_dispatch.routes")
end
def routes=(routes) # :nodoc:
- set_header("action_dispatch.routes".freeze, routes)
+ set_header("action_dispatch.routes", routes)
end
def engine_script_name(_routes) # :nodoc:
@@ -158,11 +158,11 @@ module ActionDispatch
end
def controller_instance # :nodoc:
- get_header("action_controller.instance".freeze)
+ get_header("action_controller.instance")
end
def controller_instance=(controller) # :nodoc:
- set_header("action_controller.instance".freeze, controller)
+ set_header("action_controller.instance", controller)
end
def http_auth_salt
@@ -173,7 +173,7 @@ module ActionDispatch
# We're treating `nil` as "unset", and we want the default setting to be
# `true`. This logic should be extracted to `env_config` and calculated
# once.
- !(get_header("action_dispatch.show_exceptions".freeze) == false)
+ !(get_header("action_dispatch.show_exceptions") == false)
end
# Returns a symbol form of the #request_method.
@@ -280,10 +280,10 @@ module ActionDispatch
end
def remote_ip=(remote_ip)
- set_header "action_dispatch.remote_ip".freeze, remote_ip
+ set_header "action_dispatch.remote_ip", remote_ip
end
- ACTION_DISPATCH_REQUEST_ID = "action_dispatch.request_id".freeze # :nodoc:
+ ACTION_DISPATCH_REQUEST_ID = "action_dispatch.request_id" # :nodoc:
# Returns the unique request id, which is based on either the X-Request-Id header that can
# be generated by a firewall, load balancer, or web server or by the RequestId middleware
@@ -407,18 +407,18 @@ module ActionDispatch
def request_parameters=(params)
raise if params.nil?
- set_header("action_dispatch.request.request_parameters".freeze, params)
+ set_header("action_dispatch.request.request_parameters", params)
end
def logger
- get_header("action_dispatch.logger".freeze)
+ get_header("action_dispatch.logger")
end
def commit_flash
end
def ssl?
- super || scheme == "wss".freeze
+ super || scheme == "wss"
end
private
diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb
index 885dc0ecba..1d38942a31 100644
--- a/actionpack/lib/action_dispatch/http/response.rb
+++ b/actionpack/lib/action_dispatch/http/response.rb
@@ -78,9 +78,9 @@ module ActionDispatch # :nodoc:
x
end
- CONTENT_TYPE = "Content-Type".freeze
- SET_COOKIE = "Set-Cookie".freeze
- LOCATION = "Location".freeze
+ CONTENT_TYPE = "Content-Type"
+ SET_COOKIE = "Set-Cookie"
+ LOCATION = "Location"
NO_CONTENT_CODES = [100, 101, 102, 204, 205, 304]
cattr_accessor :default_charset, default: "utf-8"
@@ -105,7 +105,7 @@ module ActionDispatch # :nodoc:
def body
@str_body ||= begin
- buf = "".dup
+ buf = +""
each { |chunk| buf << chunk }
buf
end
diff --git a/actionpack/lib/action_dispatch/http/url.rb b/actionpack/lib/action_dispatch/http/url.rb
index 35ba44005a..3af4c176a7 100644
--- a/actionpack/lib/action_dispatch/http/url.rb
+++ b/actionpack/lib/action_dispatch/http/url.rb
@@ -67,7 +67,7 @@ module ActionDispatch
end
def path_for(options)
- path = options[:script_name].to_s.chomp("/".freeze)
+ path = options[:script_name].to_s.chomp("/")
path << options[:path] if options.key?(:path)
add_trailing_slash(path) if options[:trailing_slash]
@@ -157,7 +157,7 @@ module ActionDispatch
subdomain = options.fetch :subdomain, true
domain = options[:domain]
- host = "".dup
+ host = +""
if subdomain == true
return _host if domain.nil?
@@ -231,7 +231,7 @@ module ActionDispatch
# req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080'
# req.host # => "example.com"
def host
- raw_host_with_port.sub(/:\d+$/, "".freeze)
+ raw_host_with_port.sub(/:\d+$/, "")
end
# Returns a \host:\port string for this request, such as "example.com" or
diff --git a/actionpack/lib/action_dispatch/journey/formatter.rb b/actionpack/lib/action_dispatch/journey/formatter.rb
index 0f04839d9b..52396ec901 100644
--- a/actionpack/lib/action_dispatch/journey/formatter.rb
+++ b/actionpack/lib/action_dispatch/journey/formatter.rb
@@ -50,7 +50,7 @@ module ActionDispatch
unmatched_keys = (missing_keys || []) & constraints.keys
missing_keys = (missing_keys || []) - unmatched_keys
- message = "No route matches #{Hash[constraints.sort_by { |k, v| k.to_s }].inspect}".dup
+ message = +"No route matches #{Hash[constraints.sort_by { |k, v| k.to_s }].inspect}"
message << ", missing required keys: #{missing_keys.sort.inspect}" if missing_keys && !missing_keys.empty?
message << ", possible unmatched constraints: #{unmatched_keys.sort.inspect}" if unmatched_keys && !unmatched_keys.empty?
diff --git a/actionpack/lib/action_dispatch/journey/router/utils.rb b/actionpack/lib/action_dispatch/journey/router/utils.rb
index df3f79a407..3c8b9a6eaa 100644
--- a/actionpack/lib/action_dispatch/journey/router/utils.rb
+++ b/actionpack/lib/action_dispatch/journey/router/utils.rb
@@ -17,11 +17,11 @@ module ActionDispatch
def self.normalize_path(path)
path ||= ""
encoding = path.encoding
- path = "/#{path}".dup
- path.squeeze!("/".freeze)
- path.sub!(%r{/+\Z}, "".freeze)
+ path = +"/#{path}"
+ path.squeeze!("/")
+ path.sub!(%r{/+\Z}, "")
path.gsub!(/(%[a-f0-9]{2})/) { $1.upcase }
- path = "/".dup if path == "".freeze
+ path = +"/" if path == ""
path.force_encoding(encoding)
path
end
@@ -29,16 +29,16 @@ module ActionDispatch
# URI path and fragment escaping
# https://tools.ietf.org/html/rfc3986
class UriEncoder # :nodoc:
- ENCODE = "%%%02X".freeze
+ ENCODE = "%%%02X"
US_ASCII = Encoding::US_ASCII
UTF_8 = Encoding::UTF_8
- EMPTY = "".dup.force_encoding(US_ASCII).freeze
+ EMPTY = (+"").force_encoding(US_ASCII).freeze
DEC2HEX = (0..255).to_a.map { |i| ENCODE % i }.map { |s| s.force_encoding(US_ASCII) }
- ALPHA = "a-zA-Z".freeze
- DIGIT = "0-9".freeze
- UNRESERVED = "#{ALPHA}#{DIGIT}\\-\\._~".freeze
- SUB_DELIMS = "!\\$&'\\(\\)\\*\\+,;=".freeze
+ ALPHA = "a-zA-Z"
+ DIGIT = "0-9"
+ UNRESERVED = "#{ALPHA}#{DIGIT}\\-\\._~"
+ SUB_DELIMS = "!\\$&'\\(\\)\\*\\+,;="
ESCAPED = /%[a-zA-Z0-9]{2}/.freeze
diff --git a/actionpack/lib/action_dispatch/journey/visitors.rb b/actionpack/lib/action_dispatch/journey/visitors.rb
index 3395471a85..d2619cbf3a 100644
--- a/actionpack/lib/action_dispatch/journey/visitors.rb
+++ b/actionpack/lib/action_dispatch/journey/visitors.rb
@@ -40,7 +40,7 @@ module ActionDispatch
@parameters.each do |index|
param = parts[index]
value = hash[param.name]
- return "".freeze unless value
+ return "" unless value
parts[index] = param.escape value
end
diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb
index 34331b7e4b..26d3fd936f 100644
--- a/actionpack/lib/action_dispatch/middleware/cookies.rb
+++ b/actionpack/lib/action_dispatch/middleware/cookies.rb
@@ -9,7 +9,7 @@ require "rack/utils"
module ActionDispatch
class Request
def cookie_jar
- fetch_header("action_dispatch.cookies".freeze) do
+ fetch_header("action_dispatch.cookies") do
self.cookie_jar = Cookies::CookieJar.build(self, cookies)
end
end
@@ -22,11 +22,11 @@ module ActionDispatch
}
def have_cookie_jar?
- has_header? "action_dispatch.cookies".freeze
+ has_header? "action_dispatch.cookies"
end
def cookie_jar=(jar)
- set_header "action_dispatch.cookies".freeze, jar
+ set_header "action_dispatch.cookies", jar
end
def key_generator
@@ -172,21 +172,21 @@ module ActionDispatch
# * <tt>:httponly</tt> - Whether this cookie is accessible via scripting or
# only HTTP. Defaults to +false+.
class Cookies
- HTTP_HEADER = "Set-Cookie".freeze
- GENERATOR_KEY = "action_dispatch.key_generator".freeze
- SIGNED_COOKIE_SALT = "action_dispatch.signed_cookie_salt".freeze
- ENCRYPTED_COOKIE_SALT = "action_dispatch.encrypted_cookie_salt".freeze
- ENCRYPTED_SIGNED_COOKIE_SALT = "action_dispatch.encrypted_signed_cookie_salt".freeze
- AUTHENTICATED_ENCRYPTED_COOKIE_SALT = "action_dispatch.authenticated_encrypted_cookie_salt".freeze
- USE_AUTHENTICATED_COOKIE_ENCRYPTION = "action_dispatch.use_authenticated_cookie_encryption".freeze
- ENCRYPTED_COOKIE_CIPHER = "action_dispatch.encrypted_cookie_cipher".freeze
- SIGNED_COOKIE_DIGEST = "action_dispatch.signed_cookie_digest".freeze
- SECRET_TOKEN = "action_dispatch.secret_token".freeze
- SECRET_KEY_BASE = "action_dispatch.secret_key_base".freeze
- COOKIES_SERIALIZER = "action_dispatch.cookies_serializer".freeze
- COOKIES_DIGEST = "action_dispatch.cookies_digest".freeze
- COOKIES_ROTATIONS = "action_dispatch.cookies_rotations".freeze
- USE_COOKIES_WITH_METADATA = "action_dispatch.use_cookies_with_metadata".freeze
+ HTTP_HEADER = "Set-Cookie"
+ GENERATOR_KEY = "action_dispatch.key_generator"
+ SIGNED_COOKIE_SALT = "action_dispatch.signed_cookie_salt"
+ ENCRYPTED_COOKIE_SALT = "action_dispatch.encrypted_cookie_salt"
+ ENCRYPTED_SIGNED_COOKIE_SALT = "action_dispatch.encrypted_signed_cookie_salt"
+ AUTHENTICATED_ENCRYPTED_COOKIE_SALT = "action_dispatch.authenticated_encrypted_cookie_salt"
+ USE_AUTHENTICATED_COOKIE_ENCRYPTION = "action_dispatch.use_authenticated_cookie_encryption"
+ ENCRYPTED_COOKIE_CIPHER = "action_dispatch.encrypted_cookie_cipher"
+ SIGNED_COOKIE_DIGEST = "action_dispatch.signed_cookie_digest"
+ SECRET_TOKEN = "action_dispatch.secret_token"
+ SECRET_KEY_BASE = "action_dispatch.secret_key_base"
+ COOKIES_SERIALIZER = "action_dispatch.cookies_serializer"
+ COOKIES_DIGEST = "action_dispatch.cookies_digest"
+ COOKIES_ROTATIONS = "action_dispatch.cookies_rotations"
+ USE_COOKIES_WITH_METADATA = "action_dispatch.use_cookies_with_metadata"
# Cookies can typically store 4096 bytes.
MAX_COOKIE_SIZE = 4096
@@ -535,7 +535,7 @@ module ActionDispatch
end
module SerializedCookieJars # :nodoc:
- MARSHAL_SIGNATURE = "\x04\x08".freeze
+ MARSHAL_SIGNATURE = "\x04\x08"
SERIALIZER = ActiveSupport::MessageEncryptor::NullSerializer
protected
diff --git a/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb b/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
index 077a83b112..5f5fdbc66a 100644
--- a/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
+++ b/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
@@ -23,7 +23,7 @@ module ActionDispatch
if clean_params.empty?
"None"
else
- PP.pp(clean_params, "".dup, 200)
+ PP.pp(clean_params, +"", 200)
end
end
diff --git a/actionpack/lib/action_dispatch/middleware/debug_locks.rb b/actionpack/lib/action_dispatch/middleware/debug_locks.rb
index 03760438f7..93c6c85a71 100644
--- a/actionpack/lib/action_dispatch/middleware/debug_locks.rb
+++ b/actionpack/lib/action_dispatch/middleware/debug_locks.rb
@@ -32,7 +32,7 @@ module ActionDispatch
req = ActionDispatch::Request.new env
if req.get?
- path = req.path_info.chomp("/".freeze)
+ path = req.path_info.chomp("/")
if path == @path
return render_details(req)
end
@@ -63,19 +63,19 @@ module ActionDispatch
str = threads.map do |thread, info|
if info[:exclusive]
- lock_state = "Exclusive".dup
+ lock_state = +"Exclusive"
elsif info[:sharing] > 0
- lock_state = "Sharing".dup
+ lock_state = +"Sharing"
lock_state << " x#{info[:sharing]}" if info[:sharing] > 1
else
- lock_state = "No lock".dup
+ lock_state = +"No lock"
end
if info[:waiting]
lock_state << " (yielded share)"
end
- msg = "Thread #{info[:index]} [0x#{thread.__id__.to_s(16)} #{thread.status || 'dead'}] #{lock_state}\n".dup
+ msg = +"Thread #{info[:index]} [0x#{thread.__id__.to_s(16)} #{thread.status || 'dead'}] #{lock_state}\n"
if info[:sleeper]
msg << " Waiting in #{info[:sleeper]}"
diff --git a/actionpack/lib/action_dispatch/middleware/flash.rb b/actionpack/lib/action_dispatch/middleware/flash.rb
index fd05eec172..cf9165d008 100644
--- a/actionpack/lib/action_dispatch/middleware/flash.rb
+++ b/actionpack/lib/action_dispatch/middleware/flash.rb
@@ -38,7 +38,7 @@ module ActionDispatch
#
# See docs on the FlashHash class for more details about the flash.
class Flash
- KEY = "action_dispatch.request.flash_hash".freeze
+ KEY = "action_dispatch.request.flash_hash"
module RequestMethods
# Access the contents of the flash. Use <tt>flash["notice"]</tt> to
diff --git a/actionpack/lib/action_dispatch/middleware/request_id.rb b/actionpack/lib/action_dispatch/middleware/request_id.rb
index da2871b551..fcc0c72240 100644
--- a/actionpack/lib/action_dispatch/middleware/request_id.rb
+++ b/actionpack/lib/action_dispatch/middleware/request_id.rb
@@ -15,7 +15,7 @@ module ActionDispatch
# The unique request id can be used to trace a request end-to-end and would typically end up being part of log files
# from multiple pieces of the stack.
class RequestId
- X_REQUEST_ID = "X-Request-Id".freeze #:nodoc:
+ X_REQUEST_ID = "X-Request-Id" #:nodoc:
def initialize(app)
@app = app
@@ -30,7 +30,7 @@ module ActionDispatch
private
def make_request_id(request_id)
if request_id.presence
- request_id.gsub(/[^\w\-@]/, "".freeze).first(255)
+ request_id.gsub(/[^\w\-@]/, "").first(255)
else
internal_request_id
end
diff --git a/actionpack/lib/action_dispatch/middleware/ssl.rb b/actionpack/lib/action_dispatch/middleware/ssl.rb
index 190e54223e..00902ede21 100644
--- a/actionpack/lib/action_dispatch/middleware/ssl.rb
+++ b/actionpack/lib/action_dispatch/middleware/ssl.rb
@@ -83,7 +83,7 @@ module ActionDispatch
private
def set_hsts_header!(headers)
- headers["Strict-Transport-Security".freeze] ||= @hsts_header
+ headers["Strict-Transport-Security"] ||= @hsts_header
end
def normalize_hsts_options(options)
@@ -102,23 +102,23 @@ module ActionDispatch
# https://tools.ietf.org/html/rfc6797#section-6.1
def build_hsts_header(hsts)
- value = "max-age=#{hsts[:expires].to_i}".dup
+ value = +"max-age=#{hsts[:expires].to_i}"
value << "; includeSubDomains" if hsts[:subdomains]
value << "; preload" if hsts[:preload]
value
end
def flag_cookies_as_secure!(headers)
- if cookies = headers["Set-Cookie".freeze]
- cookies = cookies.split("\n".freeze)
+ if cookies = headers["Set-Cookie"]
+ cookies = cookies.split("\n")
- headers["Set-Cookie".freeze] = cookies.map { |cookie|
+ headers["Set-Cookie"] = cookies.map { |cookie|
if !/;\s*secure\s*(;|$)/i.match?(cookie)
"#{cookie}; secure"
else
cookie
end
- }.join("\n".freeze)
+ }.join("\n")
end
end
@@ -141,7 +141,7 @@ module ActionDispatch
host = @redirect[:host] || request.host
port = @redirect[:port] || request.port
- location = "https://#{host}".dup
+ location = +"https://#{host}"
location << ":#{port}" if port != 80 && port != 443
location << request.fullpath
location
diff --git a/actionpack/lib/action_dispatch/middleware/static.rb b/actionpack/lib/action_dispatch/middleware/static.rb
index 277074f216..1f2f7757a3 100644
--- a/actionpack/lib/action_dispatch/middleware/static.rb
+++ b/actionpack/lib/action_dispatch/middleware/static.rb
@@ -79,7 +79,7 @@ module ActionDispatch
end
def content_type(path)
- ::Rack::Mime.mime_type(::File.extname(path), "text/plain".freeze)
+ ::Rack::Mime.mime_type(::File.extname(path), "text/plain")
end
def gzip_encoding_accepted?(request)
@@ -116,7 +116,7 @@ module ActionDispatch
req = Rack::Request.new env
if req.get? || req.head?
- path = req.path_info.chomp("/".freeze)
+ path = req.path_info.chomp("/")
if match = @file_handler.match?(path)
req.path_info = match
return @file_handler.serve(req)
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index 07e3be4db8..99f3b4c2cd 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -50,7 +50,19 @@ module ActionDispatch
private
def constraint_args(constraint, request)
- constraint.arity == 1 ? [request] : [request.path_parameters, request]
+ arity = if constraint.respond_to?(:arity)
+ constraint.arity
+ else
+ constraint.method(:call).arity
+ end
+
+ if arity < 1
+ []
+ elsif arity == 1
+ [request]
+ else
+ [request.path_parameters, request]
+ end
end
end
@@ -308,7 +320,7 @@ module ActionDispatch
def check_controller_and_action(path_params, controller, action)
hash = check_part(:controller, controller, path_params, {}) do |part|
translate_controller(part) {
- message = "'#{part}' is not a supported controller name. This can lead to potential routing problems.".dup
+ message = +"'#{part}' is not a supported controller name. This can lead to potential routing problems."
message << " See https://guides.rubyonrails.org/routing.html#specifying-a-controller-to-use"
raise ArgumentError, message
@@ -390,7 +402,7 @@ module ActionDispatch
# for root cases, where the latter is the correct one.
def self.normalize_path(path)
path = Journey::Router::Utils.normalize_path(path)
- path.gsub!(%r{/(\(+)/?}, '\1/') unless path =~ %r{^/\(+[^)]+\)$}
+ path.gsub!(%r{/(\(+)/?}, '\1/') unless path =~ %r{^/(\(+[^)]+\)){1,}$}
path
end
@@ -668,7 +680,7 @@ module ActionDispatch
script_namer = ->(options) do
prefix_options = options.slice(*_route.segment_keys)
- prefix_options[:relative_url_root] = "".freeze
+ prefix_options[:relative_url_root] = ""
if options[:_recall]
prefix_options.reverse_merge!(options[:_recall].slice(*_route.segment_keys))
diff --git a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb
index e17ccaf986..4de5f9e2f7 100644
--- a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb
+++ b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb
@@ -181,8 +181,8 @@ module ActionDispatch
CACHE[type].fetch(action) { build action, type }
end
- def self.url; CACHE["url".freeze][nil]; end
- def self.path; CACHE["path".freeze][nil]; end
+ def self.url; CACHE["url"][nil]; end
+ def self.path; CACHE["path"][nil]; end
def self.build(action, type)
prefix = action ? "#{action}_" : ""
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index 07d3a41173..fedf622e90 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -245,7 +245,7 @@ module ActionDispatch
missing_keys << missing_key
}
constraints = Hash[@route.requirements.merge(params).sort_by { |k, v| k.to_s }]
- message = "No route matches #{constraints.inspect}".dup
+ message = +"No route matches #{constraints.inspect}"
message << ", missing required keys: #{missing_keys.sort.inspect}"
raise ActionController::UrlGenerationError, message
@@ -377,7 +377,9 @@ module ActionDispatch
@prepend = []
@disable_clear_and_finalize = false
@finalized = false
- @env_key = "ROUTES_#{object_id}_SCRIPT_NAME".freeze
+ @env_key = "ROUTES_#{object_id}_SCRIPT_NAME"
+ @url_helpers = nil
+ @deferred_classes = []
@set = Journey::Routes.new
@router = Journey::Router.new @set
@@ -433,6 +435,25 @@ module ActionDispatch
end
private :eval_block
+ def include_helpers(klass, include_path_helpers)
+ if @finalized
+ include_helpers_now klass, include_path_helpers
+ else
+ @deferred_classes << [klass, include_path_helpers]
+ end
+ end
+
+ def include_helpers_now(klass, include_path_helpers)
+ namespace = klass.module_parents.detect { |m| m.respond_to?(:railtie_include_helpers) }
+
+ if namespace && namespace.railtie_namespace.routes != self
+ namespace.railtie_include_helpers(klass, include_path_helpers)
+ else
+ klass.include(url_helpers(include_path_helpers))
+ end
+ end
+ private :include_helpers_now
+
def finalize!
return if @finalized
@append.each { |blk| eval_block(blk) }
@@ -729,7 +750,7 @@ module ActionDispatch
# Remove leading slashes from controllers
def normalize_controller!
if controller
- if controller.start_with?("/".freeze)
+ if controller.start_with?("/")
@options[:controller] = controller[1..-1]
else
@options[:controller] = controller
@@ -820,10 +841,6 @@ module ActionDispatch
path, params = generate(route_name, path_options, recall)
- if options.key? :params
- params.merge! options[:params]
- end
-
options[:path] = path
options[:script_name] = script_name
options[:params] = params
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 d2685e0452..884fb51d18 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
@@ -65,7 +65,7 @@ module ActionDispatch
end
def display_image
- message = "[Screenshot]: #{image_path}\n".dup
+ message = +"[Screenshot]: #{image_path}\n"
case output_type
when "artifact"
diff --git a/actionpack/lib/action_dispatch/testing/assertions/response.rb b/actionpack/lib/action_dispatch/testing/assertions/response.rb
index 98b1965d22..8595ea03cf 100644
--- a/actionpack/lib/action_dispatch/testing/assertions/response.rb
+++ b/actionpack/lib/action_dispatch/testing/assertions/response.rb
@@ -79,9 +79,8 @@ module ActionDispatch
end
def generate_response_message(expected, actual = @response.response_code)
- "Expected response to be a <#{code_with_name(expected)}>,"\
- " but was a <#{code_with_name(actual)}>"
- .dup.concat(location_if_redirected).concat(response_body_if_short)
+ (+"Expected response to be a <#{code_with_name(expected)}>,"\
+ " but was a <#{code_with_name(actual)}>").concat(location_if_redirected).concat(response_body_if_short)
end
def response_body_if_short
diff --git a/actionpack/lib/action_dispatch/testing/assertions/routing.rb b/actionpack/lib/action_dispatch/testing/assertions/routing.rb
index 77cb311630..af41521c5c 100644
--- a/actionpack/lib/action_dispatch/testing/assertions/routing.rb
+++ b/actionpack/lib/action_dispatch/testing/assertions/routing.rb
@@ -9,6 +9,11 @@ module ActionDispatch
module Assertions
# Suite of assertions to test routes generated by \Rails and the handling of requests made to them.
module RoutingAssertions
+ def setup # :nodoc:
+ @routes ||= nil
+ super
+ end
+
# Asserts that the routing of the given +path+ was handled correctly and that the parsed options (given in the +expected_options+ hash)
# match +path+. Basically, it asserts that \Rails recognizes the route given by +expected_options+.
#
diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb
index f4787ed27a..65dd28b3d7 100644
--- a/actionpack/test/abstract_unit.rb
+++ b/actionpack/test/abstract_unit.rb
@@ -232,6 +232,7 @@ module ActionController
routes = ActionDispatch::Routing::RouteSet.new
routes.draw(&block)
include routes.url_helpers
+ routes
end
end
@@ -430,14 +431,16 @@ end
class ActiveSupport::TestCase
include ActiveSupport::Testing::MethodCallAssertions
- # Skips the current run on Rubinius using Minitest::Assertions#skip
- private def rubinius_skip(message = "")
- skip message if RUBY_ENGINE == "rbx"
- end
- # Skips the current run on JRuby using Minitest::Assertions#skip
- private def jruby_skip(message = "")
- skip message if defined?(JRUBY_VERSION)
- end
+ private
+ # Skips the current run on Rubinius using Minitest::Assertions#skip
+ def rubinius_skip(message = "")
+ skip message if RUBY_ENGINE == "rbx"
+ end
+
+ # Skips the current run on JRuby using Minitest::Assertions#skip
+ def jruby_skip(message = "")
+ skip message if defined?(JRUBY_VERSION)
+ end
end
class DrivenByRackTest < ActionDispatch::SystemTestCase
diff --git a/actionpack/test/controller/base_test.rb b/actionpack/test/controller/base_test.rb
index a672ede1a9..558e710df9 100644
--- a/actionpack/test/controller/base_test.rb
+++ b/actionpack/test/controller/base_test.rb
@@ -138,7 +138,7 @@ class ControllerInstanceTests < ActiveSupport::TestCase
response_headers = SimpleController.action("hello").call(
"REQUEST_METHOD" => "GET",
- "rack.input" => -> {}
+ "rack.input" => -> { }
)[1]
assert response_headers.key?("X-Frame-Options")
@@ -193,7 +193,7 @@ class UrlOptionsTest < ActionController::TestCase
action: "home",
controller: "pages",
only_path: true,
- params: { "token" => "secret" }
+ token: "secret"
}
assert_equal "/home?token=secret", rs.url_for(options)
diff --git a/actionpack/test/controller/http_token_authentication_test.rb b/actionpack/test/controller/http_token_authentication_test.rb
index 672aa1351c..103123f98c 100644
--- a/actionpack/test/controller/http_token_authentication_test.rb
+++ b/actionpack/test/controller/http_token_authentication_test.rb
@@ -150,7 +150,7 @@ class HttpTokenAuthenticationTest < ActionController::TestCase
end
test "token_and_options returns empty string with empty token" do
- token = "".dup
+ token = +""
actual = ActionController::HttpAuthentication::Token.token_and_options(sample_request(token)).first
expected = token
assert_equal(expected, actual)
diff --git a/actionpack/test/controller/live_stream_test.rb b/actionpack/test/controller/live_stream_test.rb
index 431fe90b23..d81c43b87d 100644
--- a/actionpack/test/controller/live_stream_test.rb
+++ b/actionpack/test/controller/live_stream_test.rb
@@ -304,7 +304,7 @@ module ActionController
# Simulate InterlockHook
ActiveSupport::Dependencies.interlock.start_running
res = get :write_sleep_autoload
- res.each {}
+ res.each { }
ActiveSupport::Dependencies.interlock.done_running
end
diff --git a/actionpack/test/controller/metal_test.rb b/actionpack/test/controller/metal_test.rb
index 248ef36b7c..7b53092266 100644
--- a/actionpack/test/controller/metal_test.rb
+++ b/actionpack/test/controller/metal_test.rb
@@ -20,7 +20,7 @@ class MetalControllerInstanceTests < ActiveSupport::TestCase
response_headers = SimpleController.action("hello").call(
"REQUEST_METHOD" => "GET",
- "rack.input" => -> {}
+ "rack.input" => -> { }
)[1]
assert_not response_headers.key?("X-Frame-Options")
diff --git a/actionpack/test/controller/mime/respond_to_test.rb b/actionpack/test/controller/mime/respond_to_test.rb
index 1163775d3c..00e1d5f3b3 100644
--- a/actionpack/test/controller/mime/respond_to_test.rb
+++ b/actionpack/test/controller/mime/respond_to_test.rb
@@ -78,7 +78,7 @@ class RespondToController < ActionController::Base
def missing_templates
respond_to do |type|
# This test requires a block that is empty
- type.json {}
+ type.json { }
type.xml
end
end
diff --git a/actionpack/test/controller/new_base/bare_metal_test.rb b/actionpack/test/controller/new_base/bare_metal_test.rb
index b049022a06..7572d514fb 100644
--- a/actionpack/test/controller/new_base/bare_metal_test.rb
+++ b/actionpack/test/controller/new_base/bare_metal_test.rb
@@ -13,7 +13,7 @@ module BareMetalTest
test "response body is a Rack-compatible response" do
status, headers, body = BareController.action(:index).call(Rack::MockRequest.env_for("/"))
assert_equal 200, status
- string = "".dup
+ string = +""
body.each do |part|
assert part.is_a?(String), "Each part of the body must be a String"
diff --git a/actionpack/test/controller/new_base/render_context_test.rb b/actionpack/test/controller/new_base/render_context_test.rb
index 07fbadae9f..5e570a1d79 100644
--- a/actionpack/test/controller/new_base/render_context_test.rb
+++ b/actionpack/test/controller/new_base/render_context_test.rb
@@ -32,10 +32,11 @@ module RenderContext
"controller context!"
end
- # 3) Set view_context to self
- private def view_context
- self
- end
+ private
+ # 3) Set view_context to self
+ def view_context
+ self
+ end
end
class RenderContextTest < Rack::TestCase
diff --git a/actionpack/test/controller/parameters/accessors_test.rb b/actionpack/test/controller/parameters/accessors_test.rb
index 68c7f2d9ea..9f1fb3d042 100644
--- a/actionpack/test/controller/parameters/accessors_test.rb
+++ b/actionpack/test/controller/parameters/accessors_test.rb
@@ -75,6 +75,24 @@ class ParametersAccessorsTest < ActiveSupport::TestCase
end
end
+ test "each_value carries permitted status" do
+ @params.permit!
+ @params["person"].each_value { |value| assert(value.permitted?) if value == 32 }
+ end
+
+ test "each_value carries unpermitted status" do
+ @params["person"].each_value { |value| assert_not(value.permitted?) if value == 32 }
+ end
+
+ test "each_key converts to hash for permitted" do
+ @params.permit!
+ @params.each_key { |key| assert_kind_of(String, key) if key == "person" }
+ end
+
+ test "each_key converts to hash for unpermitted" do
+ @params.each_key { |key| assert_kind_of(String, key) if key == "person" }
+ end
+
test "empty? returns true when params contains no key/value pairs" do
params = ActionController::Parameters.new
assert_empty params
diff --git a/actionpack/test/controller/redirect_test.rb b/actionpack/test/controller/redirect_test.rb
index 461e627154..998498e1b2 100644
--- a/actionpack/test/controller/redirect_test.rb
+++ b/actionpack/test/controller/redirect_test.rb
@@ -214,6 +214,13 @@ class RedirectTest < ActionController::TestCase
assert_equal "http://test.host/things/stuff", redirect_to_url
end
+ def test_relative_url_redirect_host_with_port
+ request.host = "test.host:1234"
+ get :relative_url_redirect_with_status
+ assert_response 302
+ assert_equal "http://test.host:1234/things/stuff", redirect_to_url
+ end
+
def test_simple_redirect_using_options
get :host_redirect
assert_response :redirect
diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb
index a7033b2d30..30f2a23b33 100644
--- a/actionpack/test/controller/routing_test.rb
+++ b/actionpack/test/controller/routing_test.rb
@@ -25,8 +25,8 @@ class UriReservedCharactersRoutingTest < ActiveSupport::TestCase
safe, unsafe = %w(: @ & = + $ , ;), %w(^ ? # [ ])
hex = unsafe.map { |char| "%" + char.unpack1("H2").upcase }
- @segment = "#{safe.join}#{unsafe.join}".freeze
- @escaped = "#{safe.join}#{hex.join}".freeze
+ @segment = "#{safe.join}#{unsafe.join}"
+ @escaped = "#{safe.join}#{hex.join}"
end
def test_route_generation_escapes_unsafe_path_characters
@@ -309,7 +309,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def test_specific_controller_action_failure
rs.draw do
- mount lambda {} => "/foo"
+ mount lambda { } => "/foo"
end
assert_raises(ActionController::UrlGenerationError) do
@@ -674,7 +674,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
assert_equal "/page/foo", url_for(rs, controller: "content", action: "show_page", id: "foo")
assert_equal({ controller: "content", action: "show_page", id: "foo" }, rs.recognize_path("/page/foo"))
- token = "\321\202\320\265\320\272\321\201\321\202".dup # 'text' in Russian
+ token = +"\321\202\320\265\320\272\321\201\321\202" # 'text' in Russian
token.force_encoding(Encoding::BINARY)
escaped_token = CGI.escape(token)
diff --git a/actionpack/test/controller/send_file_test.rb b/actionpack/test/controller/send_file_test.rb
index 7b1a52b277..c917cdf761 100644
--- a/actionpack/test/controller/send_file_test.rb
+++ b/actionpack/test/controller/send_file_test.rb
@@ -144,7 +144,7 @@ class SendFileTest < ActionController::TestCase
get :test_send_file_headers_bang
assert_equal "image/png", response.content_type
- assert_equal 'disposition; filename="filename"', response.get_header("Content-Disposition")
+ assert_equal %(disposition; filename="filename"; filename*=UTF-8''filename), response.get_header("Content-Disposition")
assert_equal "binary", response.get_header("Content-Transfer-Encoding")
assert_equal "private", response.get_header("Cache-Control")
end
@@ -153,7 +153,7 @@ class SendFileTest < ActionController::TestCase
def test_send_file_headers_with_disposition_as_a_symbol
get :test_send_file_headers_with_disposition_as_a_symbol
- assert_equal 'disposition; filename="filename"', response.get_header("Content-Disposition")
+ assert_equal %(disposition; filename="filename"; filename*=UTF-8''filename), response.get_header("Content-Disposition")
end
def test_send_file_headers_with_mime_lookup_with_symbol
diff --git a/actionpack/test/controller/test_case_test.rb b/actionpack/test/controller/test_case_test.rb
index dda2686a9b..6fc70d6248 100644
--- a/actionpack/test/controller/test_case_test.rb
+++ b/actionpack/test/controller/test_case_test.rb
@@ -542,7 +542,7 @@ XML
def test_params_passing_with_frozen_values
assert_nothing_raised do
get :test_params, params: {
- frozen: "icy".freeze, frozens: ["icy".freeze].freeze, deepfreeze: { frozen: "icy".freeze }.freeze
+ frozen: -"icy", frozens: [-"icy"].freeze, deepfreeze: { frozen: -"icy" }.freeze
}
end
parsed_params = ::JSON.parse(@response.body)
diff --git a/actionpack/test/dispatch/content_disposition_test.rb b/actionpack/test/dispatch/content_disposition_test.rb
new file mode 100644
index 0000000000..3f5959da6e
--- /dev/null
+++ b/actionpack/test/dispatch/content_disposition_test.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require "abstract_unit"
+
+module ActionDispatch
+ class ContentDispositionTest < ActiveSupport::TestCase
+ test "encoding a Latin filename" do
+ disposition = Http::ContentDisposition.new(disposition: :inline, filename: "racecar.jpg")
+
+ assert_equal %(filename="racecar.jpg"), disposition.ascii_filename
+ assert_equal "filename*=UTF-8''racecar.jpg", disposition.utf8_filename
+ assert_equal "inline; #{disposition.ascii_filename}; #{disposition.utf8_filename}", disposition.to_s
+ end
+
+ test "encoding a Latin filename with accented characters" do
+ disposition = Http::ContentDisposition.new(disposition: :inline, filename: "råcëçâr.jpg")
+
+ assert_equal %(filename="racecar.jpg"), disposition.ascii_filename
+ assert_equal "filename*=UTF-8''r%C3%A5c%C3%AB%C3%A7%C3%A2r.jpg", disposition.utf8_filename
+ assert_equal "inline; #{disposition.ascii_filename}; #{disposition.utf8_filename}", disposition.to_s
+ end
+
+ test "encoding a non-Latin filename" do
+ disposition = Http::ContentDisposition.new(disposition: :inline, filename: "автомобиль.jpg")
+
+ assert_equal %(filename="%3F%3F%3F%3F%3F%3F%3F%3F%3F%3F.jpg"), disposition.ascii_filename
+ assert_equal "filename*=UTF-8''%D0%B0%D0%B2%D1%82%D0%BE%D0%BC%D0%BE%D0%B1%D0%B8%D0%BB%D1%8C.jpg", disposition.utf8_filename
+ assert_equal "inline; #{disposition.ascii_filename}; #{disposition.utf8_filename}", disposition.to_s
+ end
+
+ test "without filename" do
+ disposition = Http::ContentDisposition.new(disposition: :inline, filename: nil)
+
+ assert_equal "inline", disposition.to_s
+ end
+ end
+end
diff --git a/actionpack/test/dispatch/content_security_policy_test.rb b/actionpack/test/dispatch/content_security_policy_test.rb
index 4f9a4ff2bd..13ad22b5c5 100644
--- a/actionpack/test/dispatch/content_security_policy_test.rb
+++ b/actionpack/test/dispatch/content_security_policy_test.rb
@@ -339,6 +339,11 @@ class ContentSecurityPolicyIntegrationTest < ActionDispatch::IntegrationTest
p.script_src :self
end
+ content_security_policy only: :style_src do |p|
+ p.default_src false
+ p.style_src :self
+ end
+
content_security_policy(false, only: :no_policy)
content_security_policy_report_only only: :report_only
@@ -363,6 +368,10 @@ class ContentSecurityPolicyIntegrationTest < ActionDispatch::IntegrationTest
head :ok
end
+ def style_src
+ head :ok
+ end
+
def no_policy
head :ok
end
@@ -381,6 +390,7 @@ class ContentSecurityPolicyIntegrationTest < ActionDispatch::IntegrationTest
get "/conditional", to: "policy#conditional"
get "/report-only", to: "policy#report_only"
get "/script-src", to: "policy#script_src"
+ get "/style-src", to: "policy#style_src"
get "/no-policy", to: "policy#no_policy"
end
end
@@ -441,6 +451,11 @@ class ContentSecurityPolicyIntegrationTest < ActionDispatch::IntegrationTest
assert_policy "script-src 'self' 'nonce-iyhD0Yc0W+c='"
end
+ def test_adds_nonce_to_style_src_content_security_policy
+ get "/style-src"
+ assert_policy "style-src 'self' 'nonce-iyhD0Yc0W+c='"
+ end
+
def test_generates_no_content_security_policy
get "/no-policy"
diff --git a/actionpack/test/dispatch/debug_exceptions_test.rb b/actionpack/test/dispatch/debug_exceptions_test.rb
index 44b79c0e5d..37399cfd07 100644
--- a/actionpack/test/dispatch/debug_exceptions_test.rb
+++ b/actionpack/test/dispatch/debug_exceptions_test.rb
@@ -368,7 +368,7 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest
})
assert_response 500
- assert_includes(body, CGI.escapeHTML(PP.pp(params, "".dup, 200)))
+ assert_includes(body, CGI.escapeHTML(PP.pp(params, +"", 200)))
end
test "sets the HTTP charset parameter" do
diff --git a/actionpack/test/dispatch/middleware_stack_test.rb b/actionpack/test/dispatch/middleware_stack_test.rb
index e9f7ad41dd..5f43e5a3c5 100644
--- a/actionpack/test/dispatch/middleware_stack_test.rb
+++ b/actionpack/test/dispatch/middleware_stack_test.rb
@@ -42,7 +42,7 @@ class MiddlewareStackTest < ActiveSupport::TestCase
end
test "use should push middleware class with block arguments onto the stack" do
- proc = Proc.new {}
+ proc = Proc.new { }
assert_difference "@stack.size" do
@stack.use(BlockMiddleware, &proc)
end
diff --git a/actionpack/test/dispatch/prefix_generation_test.rb b/actionpack/test/dispatch/prefix_generation_test.rb
index 85ea04356a..7a7a201b11 100644
--- a/actionpack/test/dispatch/prefix_generation_test.rb
+++ b/actionpack/test/dispatch/prefix_generation_test.rb
@@ -13,7 +13,7 @@ module TestGenerationPrefix
end
def self.model_name
- klass = "Post".dup
+ klass = +"Post"
def klass.name; self end
ActiveModel::Name.new(klass)
diff --git a/actionpack/test/dispatch/request_test.rb b/actionpack/test/dispatch/request_test.rb
index 0ac8713527..c7b68e5266 100644
--- a/actionpack/test/dispatch/request_test.rb
+++ b/actionpack/test/dispatch/request_test.rb
@@ -24,7 +24,7 @@ class BaseRequestTest < ActiveSupport::TestCase
def stub_request(env = {})
ip_spoofing_check = env.key?(:ip_spoofing_check) ? env.delete(:ip_spoofing_check) : true
@trusted_proxies ||= nil
- ip_app = ActionDispatch::RemoteIp.new(Proc.new {}, ip_spoofing_check, @trusted_proxies)
+ ip_app = ActionDispatch::RemoteIp.new(Proc.new { }, ip_spoofing_check, @trusted_proxies)
ActionDispatch::Http::URL.tld_length = env.delete(:tld_length) if env.key?(:tld_length)
ip_app.call(env)
diff --git a/actionpack/test/dispatch/routing/inspector_test.rb b/actionpack/test/dispatch/routing/inspector_test.rb
index f1f6547889..fe1f1995d8 100644
--- a/actionpack/test/dispatch/routing/inspector_test.rb
+++ b/actionpack/test/dispatch/routing/inspector_test.rb
@@ -373,7 +373,7 @@ module ActionDispatch
end
def test_not_routes_when_expanded
- output = draw(grep: "rails/dummy", formatter: ActionDispatch::Routing::ConsoleFormatter::Expanded.new) {}
+ output = draw(grep: "rails/dummy", formatter: ActionDispatch::Routing::ConsoleFormatter::Expanded.new) { }
assert_equal [
"You don't have any routes defined!",
@@ -450,7 +450,7 @@ module ActionDispatch
end
def test_no_routes_were_defined
- output = draw(grep: "Rails::DummyController") {}
+ output = draw(grep: "Rails::DummyController") { }
assert_equal [
"You don't have any routes defined!",
diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb
index 5efbe5b553..affc2d8497 100644
--- a/actionpack/test/dispatch/routing_test.rb
+++ b/actionpack/test/dispatch/routing_test.rb
@@ -115,6 +115,21 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
assert_equal 301, status
end
+ def test_accepts_a_constraint_object_responding_to_call
+ constraint = Class.new do
+ def call(*); true; end
+ def matches?(*); false; end
+ end
+
+ draw do
+ get "/", to: "home#show", constraints: constraint.new
+ end
+
+ assert_nothing_raised do
+ get "/"
+ end
+ end
+
def test_namespace_with_controller_segment
assert_raise(ArgumentError) do
draw do
@@ -1367,6 +1382,22 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
assert_equal "projects#index", @response.body
end
+ def test_optionally_scoped_root_unscoped_access
+ draw do
+ scope "(:locale)" do
+ scope "(:platform)" do
+ scope "(:browser)" do
+ root to: "projects#index"
+ end
+ end
+ end
+ end
+
+ assert_equal "/", root_path
+ get "/"
+ assert_equal "projects#index", @response.body
+ end
+
def test_scope_with_format_option
draw do
get "direct/index", as: :no_format_direct, format: false
diff --git a/actionpack/test/dispatch/static_test.rb b/actionpack/test/dispatch/static_test.rb
index 6b69cd9999..d44aa00122 100644
--- a/actionpack/test/dispatch/static_test.rb
+++ b/actionpack/test/dispatch/static_test.rb
@@ -31,7 +31,7 @@ module StaticTests
end
def test_handles_urls_with_ascii_8bit
- assert_equal "Hello, World!", get("/doorkeeper%E3E4".dup.force_encoding("ASCII-8BIT")).body
+ assert_equal "Hello, World!", get((+"/doorkeeper%E3E4").force_encoding("ASCII-8BIT")).body
end
def test_handles_urls_with_ascii_8bit_on_win_31j
@@ -39,7 +39,7 @@ module StaticTests
Encoding.default_internal = "Windows-31J"
Encoding.default_external = "Windows-31J"
end
- assert_equal "Hello, World!", get("/doorkeeper%E3E4".dup.force_encoding("ASCII-8BIT")).body
+ assert_equal "Hello, World!", get((+"/doorkeeper%E3E4").force_encoding("ASCII-8BIT")).body
end
def test_handles_urls_with_null_byte
diff --git a/actionpack/test/fixtures/alternate_helpers/foo_helper.rb b/actionpack/test/fixtures/alternate_helpers/foo_helper.rb
index 3aadb6145e..c1a995af5f 100644
--- a/actionpack/test/fixtures/alternate_helpers/foo_helper.rb
+++ b/actionpack/test/fixtures/alternate_helpers/foo_helper.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
module FooHelper
- redefine_method(:baz) {}
+ redefine_method(:baz) { }
end
diff --git a/actionpack/test/journey/router/utils_test.rb b/actionpack/test/journey/router/utils_test.rb
index 2d09098f11..472f1bf35e 100644
--- a/actionpack/test/journey/router/utils_test.rb
+++ b/actionpack/test/journey/router/utils_test.rb
@@ -23,7 +23,7 @@ module ActionDispatch
end
def test_uri_unescape_with_utf8_string
- assert_equal "Šašinková", Utils.unescape_uri("%C5%A0a%C5%A1inkov%C3%A1".dup.force_encoding(Encoding::US_ASCII))
+ assert_equal "Šašinková", Utils.unescape_uri((+"%C5%A0a%C5%A1inkov%C3%A1").force_encoding(Encoding::US_ASCII))
end
def test_normalize_path_not_greedy