diff options
Diffstat (limited to 'actionpack/lib/action_dispatch')
25 files changed, 185 insertions, 107 deletions
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+. # |