aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_dispatch
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib/action_dispatch')
-rw-r--r--actionpack/lib/action_dispatch/http/cache.rb2
-rw-r--r--actionpack/lib/action_dispatch/http/mime_negotiation.rb12
-rw-r--r--actionpack/lib/action_dispatch/http/parameters.rb18
-rw-r--r--actionpack/lib/action_dispatch/http/request.rb4
-rw-r--r--actionpack/lib/action_dispatch/http/url.rb105
-rw-r--r--actionpack/lib/action_dispatch/journey/router.rb4
-rw-r--r--actionpack/lib/action_dispatch/journey/router/utils.rb12
-rw-r--r--actionpack/lib/action_dispatch/middleware/cookies.rb4
-rw-r--r--actionpack/lib/action_dispatch/middleware/flash.rb9
-rw-r--r--actionpack/lib/action_dispatch/middleware/session/cookie_store.rb2
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb4
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb4
-rw-r--r--actionpack/lib/action_dispatch/testing/integration.rb6
-rw-r--r--actionpack/lib/action_dispatch/testing/test_request.rb2
14 files changed, 103 insertions, 85 deletions
diff --git a/actionpack/lib/action_dispatch/http/cache.rb b/actionpack/lib/action_dispatch/http/cache.rb
index f9b278349e..63a3cbc90b 100644
--- a/actionpack/lib/action_dispatch/http/cache.rb
+++ b/actionpack/lib/action_dispatch/http/cache.rb
@@ -92,7 +92,7 @@ module ActionDispatch
LAST_MODIFIED = "Last-Modified".freeze
ETAG = "ETag".freeze
CACHE_CONTROL = "Cache-Control".freeze
- SPECIAL_KEYS = %w[extras no-cache max-age public must-revalidate]
+ SPECIAL_KEYS = Set.new(%w[extras no-cache max-age public must-revalidate])
def cache_control_segments
if cache_control = self[CACHE_CONTROL]
diff --git a/actionpack/lib/action_dispatch/http/mime_negotiation.rb b/actionpack/lib/action_dispatch/http/mime_negotiation.rb
index 0b2b60d2e4..9c8f65deac 100644
--- a/actionpack/lib/action_dispatch/http/mime_negotiation.rb
+++ b/actionpack/lib/action_dispatch/http/mime_negotiation.rb
@@ -54,8 +54,14 @@ module ActionDispatch
end
def formats
- @env["action_dispatch.request.formats"] ||=
- if parameters[:format]
+ @env["action_dispatch.request.formats"] ||= begin
+ params_readable = begin
+ parameters[:format]
+ rescue ActionController::BadRequest
+ false
+ end
+
+ if params_readable
Array(Mime[parameters[:format]])
elsif use_accept_header && valid_accept_header
accepts
@@ -64,8 +70,8 @@ module ActionDispatch
else
[Mime::HTML]
end
+ end
end
-
# Sets the \variant for template.
def variant=(variant)
if variant.is_a?(Symbol)
diff --git a/actionpack/lib/action_dispatch/http/parameters.rb b/actionpack/lib/action_dispatch/http/parameters.rb
index 5f7627cf96..20ae48d458 100644
--- a/actionpack/lib/action_dispatch/http/parameters.rb
+++ b/actionpack/lib/action_dispatch/http/parameters.rb
@@ -1,5 +1,6 @@
require 'active_support/core_ext/hash/keys'
require 'active_support/core_ext/hash/indifferent_access'
+require 'active_support/deprecation'
module ActionDispatch
module Http
@@ -24,8 +25,10 @@ module ActionDispatch
@env[PARAMETERS_KEY] = parameters
end
- # The same as <tt>path_parameters</tt> with explicitly symbolized keys.
def symbolized_path_parameters
+ ActiveSupport::Deprecation.warn(
+ "`symbolized_path_parameters` is deprecated. Please use `path_parameters`"
+ )
path_parameters
end
@@ -33,31 +36,22 @@ module ActionDispatch
# Returned hash keys are strings:
#
# {'action' => 'my_action', 'controller' => 'my_controller'}
- #
- # See <tt>symbolized_path_parameters</tt> for symbolized keys.
def path_parameters
@env[PARAMETERS_KEY] ||= {}
end
private
- # Convert nested Hash to HashWithIndifferentAccess
- # and UTF-8 encode both keys and values in nested Hash.
+ # Convert nested Hash to HashWithIndifferentAccess.
#
- # TODO: Validate that the characters are UTF-8. If they aren't,
- # you'll get a weird error down the road, but our form handling
- # should really prevent that from happening
def normalize_encode_params(params)
case params
- when String
- params.force_encoding(Encoding::UTF_8).encode!
when Hash
if params.has_key?(:tempfile)
UploadedFile.new(params)
else
params.each_with_object({}) do |(key, val), new_hash|
- new_key = key.is_a?(String) ? key.dup.force_encoding(Encoding::UTF_8).encode! : key
- new_hash[new_key] = if val.is_a?(Array)
+ new_hash[key] = if val.is_a?(Array)
val.map! { |el| normalize_encode_params(el) }
else
normalize_encode_params(val)
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb
index 4d4b443fb4..01f117be99 100644
--- a/actionpack/lib/action_dispatch/http/request.rb
+++ b/actionpack/lib/action_dispatch/http/request.rb
@@ -209,8 +209,8 @@ module ActionDispatch
end
# Returns true if the "X-Requested-With" header contains "XMLHttpRequest"
- # (case-insensitive). All major JavaScript libraries send this header with
- # every Ajax request.
+ # (case-insensitive), which may need to be manually added depending on the
+ # choice of JavaScript libraries and frameworks.
def xml_http_request?
@env['HTTP_X_REQUESTED_WITH'] =~ /XMLHttpRequest/i
end
diff --git a/actionpack/lib/action_dispatch/http/url.rb b/actionpack/lib/action_dispatch/http/url.rb
index 4cba4f5f37..6ba2820d09 100644
--- a/actionpack/lib/action_dispatch/http/url.rb
+++ b/actionpack/lib/action_dispatch/http/url.rb
@@ -5,45 +5,47 @@ module ActionDispatch
module Http
module URL
IP_HOST_REGEXP = /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/
- HOST_REGEXP = /(^.*:\/\/)?([^:]+)(?::(\d+$))?/
+ HOST_REGEXP = /(^[^:]+:\/\/)?([^:]+)(?::(\d+$))?/
PROTOCOL_REGEXP = /^([^:]+)(:)?(\/\/)?$/
mattr_accessor :tld_length
self.tld_length = 1
class << self
- def extract_domain(host, tld_length = @@tld_length)
- host.split('.').last(1 + tld_length).join('.') if named_host?(host)
+ def extract_domain(host, tld_length)
+ extract_domain_from(host, tld_length) if named_host?(host)
end
- def extract_subdomains(host, tld_length = @@tld_length)
+ def extract_subdomains(host, tld_length)
if named_host?(host)
- parts = host.split('.')
- parts[0..-(tld_length + 2)]
+ extract_subdomains_from(host, tld_length)
else
[]
end
end
- def extract_subdomain(host, tld_length = @@tld_length)
+ def extract_subdomain(host, tld_length)
extract_subdomains(host, tld_length).join('.')
end
def url_for(options)
- unless options[:host] || options[:only_path]
+ host = options[:host]
+ unless host || options[:only_path]
raise ArgumentError, 'Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true'
end
path = options[:script_name].to_s.chomp("/")
path << options[:path].to_s
- add_trailing_slash(path) if options[:trailing_slash]
+ path = add_trailing_slash(path) if options[:trailing_slash]
- result = path
-
- unless options[:only_path]
- result.prepend build_host_url(options)
- end
+ result = if options[:only_path]
+ path
+ else
+ protocol = options[:protocol]
+ port = options[:port]
+ build_host_url(host, port, protocol, options).concat path
+ end
if options.key? :params
params = options[:params].is_a?(Hash) ?
@@ -60,6 +62,15 @@ module ActionDispatch
private
+ def extract_domain_from(host, tld_length)
+ host.split('.').last(1 + tld_length).join('.')
+ end
+
+ def extract_subdomains_from(host, tld_length)
+ parts = host.split('.')
+ parts[0..-(tld_length + 2)]
+ end
+
def add_trailing_slash(path)
# includes querysting
if path.include?('?')
@@ -72,39 +83,36 @@ module ActionDispatch
path
end
- def build_host_url(options)
- if match = options[:host].match(HOST_REGEXP)
- options[:protocol] ||= match[1] unless options[:protocol] == false
- options[:host] = match[2]
- options[:port] = match[3] unless options.key?(:port)
+ def build_host_url(host, port, protocol, options)
+ if match = host.match(HOST_REGEXP)
+ protocol ||= match[1] unless protocol == false
+ host = match[2]
+ port = match[3] unless options.key? :port
end
- options[:protocol] = normalize_protocol(options)
- options[:host] = normalize_host(options)
- options[:port] = normalize_port(options)
+ protocol = normalize_protocol protocol
+ host = normalize_host(host, options)
- result = options[:protocol]
+ result = protocol.dup
if options[:user] && options[:password]
result << "#{Rack::Utils.escape(options[:user])}:#{Rack::Utils.escape(options[:password])}@"
end
- result << options[:host]
- result << ":#{options[:port]}" if options[:port]
+ result << host
+ normalize_port(port, protocol) { |normalized_port|
+ result << ":#{normalized_port}"
+ }
result
end
def named_host?(host)
- host && IP_HOST_REGEXP !~ host
- end
-
- def same_host?(options)
- (options[:subdomain] == true || !options.key?(:subdomain)) && options[:domain].nil?
+ IP_HOST_REGEXP !~ host
end
- def normalize_protocol(options)
- case options[:protocol]
+ def normalize_protocol(protocol)
+ case protocol
when nil
"http://"
when false, "//"
@@ -112,36 +120,39 @@ module ActionDispatch
when PROTOCOL_REGEXP
"#{$1}://"
else
- raise ArgumentError, "Invalid :protocol option: #{options[:protocol].inspect}"
+ raise ArgumentError, "Invalid :protocol option: #{protocol.inspect}"
end
end
- def normalize_host(options)
- return options[:host] if !named_host?(options[:host]) || same_host?(options)
+ def normalize_host(_host, options)
+ return _host unless named_host?(_host)
tld_length = options[:tld_length] || @@tld_length
+ subdomain = options.fetch :subdomain, true
+ domain = options[:domain]
host = ""
- if options[:subdomain] == true || !options.key?(:subdomain)
- host << extract_subdomain(options[:host], tld_length).to_param
- elsif options[:subdomain].present?
- host << options[:subdomain].to_param
+ if subdomain == true
+ return _host if domain.nil?
+
+ host << extract_subdomains_from(_host, tld_length).join('.')
+ elsif subdomain
+ host << subdomain.to_param
end
host << "." unless host.empty?
- host << (options[:domain] || extract_domain(options[:host], tld_length))
+ host << (domain || extract_domain_from(_host, tld_length))
host
end
- def normalize_port(options)
- return nil if options[:port].nil? || options[:port] == false
+ def normalize_port(port, protocol)
+ return unless port
- case options[:protocol]
- when "//"
- options[:port]
+ case protocol
+ when "//" then yield port
when "https://"
- options[:port].to_i == 443 ? nil : options[:port]
+ yield port unless port.to_i == 443
else
- options[:port].to_i == 80 ? nil : options[:port]
+ yield port unless port.to_i == 80
end
end
end
diff --git a/actionpack/lib/action_dispatch/journey/router.rb b/actionpack/lib/action_dispatch/journey/router.rb
index 74fa9ee3a2..21817b374c 100644
--- a/actionpack/lib/action_dispatch/journey/router.rb
+++ b/actionpack/lib/action_dispatch/journey/router.rb
@@ -35,6 +35,7 @@ module ActionDispatch
unless route.path.anchored
req.script_name = (script_name.to_s + match.to_s).chomp('/')
req.path_info = match.post_match
+ req.path_info = "/" + req.path_info unless req.path_info.start_with? "/"
end
req.path_parameters = set_params.merge parameters
@@ -104,7 +105,8 @@ module ActionDispatch
routes.concat get_routes_as_head(routes)
end
- routes.sort_by!(&:precedence).select! { |r| r.matches?(req) }
+ routes.select! { |r| r.matches?(req) }
+ routes.sort_by!(&:precedence)
routes.map! { |r|
match_data = r.path.match(req.path_info)
diff --git a/actionpack/lib/action_dispatch/journey/router/utils.rb b/actionpack/lib/action_dispatch/journey/router/utils.rb
index ac4ecb1e65..2b0a6575d4 100644
--- a/actionpack/lib/action_dispatch/journey/router/utils.rb
+++ b/actionpack/lib/action_dispatch/journey/router/utils.rb
@@ -25,9 +25,10 @@ module ActionDispatch
# http://tools.ietf.org/html/rfc3986
class UriEncoder # :nodoc:
ENCODE = "%%%02X".freeze
- ENCODING = Encoding::US_ASCII
- EMPTY = "".force_encoding(ENCODING).freeze
- DEC2HEX = (0..255).to_a.map{ |i| ENCODE % i }.map{ |s| s.force_encoding(ENCODING) }
+ US_ASCII = Encoding::US_ASCII
+ UTF_8 = Encoding::UTF_8
+ 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
@@ -53,12 +54,13 @@ module ActionDispatch
end
def unescape_uri(uri)
- uri.gsub(ESCAPED) { [$&[1, 2].hex].pack('C') }.force_encoding(uri.encoding)
+ encoding = uri.encoding == US_ASCII ? UTF_8 : uri.encoding
+ uri.gsub(ESCAPED) { [$&[1, 2].hex].pack('C') }.force_encoding(encoding)
end
protected
def escape(component, pattern)
- component.gsub(pattern){ |unsafe| percent_encode(unsafe) }.force_encoding(ENCODING)
+ component.gsub(pattern){ |unsafe| percent_encode(unsafe) }.force_encoding(US_ASCII)
end
def percent_encode(unsafe)
diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb
index 22b16b628d..e069840b8e 100644
--- a/actionpack/lib/action_dispatch/middleware/cookies.rb
+++ b/actionpack/lib/action_dispatch/middleware/cookies.rb
@@ -289,8 +289,8 @@ module ActionDispatch
end
end
- # Sets the cookie named +name+. The second argument may be the very cookie
- # value, or a hash of options as documented above.
+ # Sets the cookie named +name+. The second argument may be the cookie's
+ # value or a hash of options as documented above.
def []=(name, options)
if options.is_a?(Hash)
options.symbolize_keys!
diff --git a/actionpack/lib/action_dispatch/middleware/flash.rb b/actionpack/lib/action_dispatch/middleware/flash.rb
index 4821d2a899..e90f8b9ce6 100644
--- a/actionpack/lib/action_dispatch/middleware/flash.rb
+++ b/actionpack/lib/action_dispatch/middleware/flash.rb
@@ -10,7 +10,7 @@ module ActionDispatch
end
end
- # The flash provides a way to pass temporary objects between actions. Anything you place in the flash will be exposed
+ # The flash provides a way to pass temporary primitive-types (String, Array, Hash) between actions. Anything you place in the flash will be exposed
# to the very next action and then cleared out. This is a great way of doing notices and alerts, such as a create
# action that sets <tt>flash[:notice] = "Post successfully created"</tt> before redirecting to a display action that can
# then expose the flash to its template. Actually, that exposure is automatically done.
@@ -37,8 +37,11 @@ module ActionDispatch
# flash.alert = "You must be logged in"
# flash.notice = "Post successfully created"
#
- # This example just places a string in the flash, but you can put any object in there. And of course, you can put as
- # many as you like at a time too. Just remember: They'll be gone by the time the next action has been performed.
+ # This example places a string in the flash. And of course, you can put as many as you like at a time too. If you want to pass
+ # non-primitive types, you will have to handle that in your application. Example: To show messages with links, you will have to
+ # use sanitize helper.
+ #
+ # Just remember: They'll be gone by the time the next action has been performed.
#
# See docs on the FlashHash class for more details about the flash.
class Flash
diff --git a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb
index 0864e7ef2a..ed25c67ae5 100644
--- a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb
+++ b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb
@@ -49,7 +49,7 @@ module ActionDispatch
# reasonably sure that your upgrade is otherwise complete. Additionally,
# you should take care to make sure you are not relying on the ability to
# decode signed cookies generated by your app in external applications or
- # Javascript before upgrading.
+ # JavaScript before upgrading.
#
# Note that changing the secret key will invalidate all existing sessions!
class CookieStore < Rack::Session::Abstract::ID
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index aac5546aa1..235a840682 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -717,7 +717,7 @@ module ActionDispatch
# resources :posts, module: "admin"
#
# If you want to route /admin/posts to +PostsController+
- # (without the Admin:: module prefix), you could use
+ # (without the <tt>Admin::</tt> module prefix), you could use
#
# scope "/admin" do
# resources :posts
@@ -1434,7 +1434,7 @@ module ActionDispatch
end
with_scope_level(:nested) do
- if shallow? && shallow_nesting_depth > 1
+ if shallow? && shallow_nesting_depth >= 1
shallow_scope(parent_resource.nested_scope, nested_options) { yield }
else
scope(parent_resource.nested_scope, nested_options) { yield }
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index bdda802195..69535faabd 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -420,7 +420,7 @@ module ActionDispatch
path = conditions.delete :path_info
ast = conditions.delete :parsed_path_info
- path = build_path(path, ast, requirements, SEPARATORS, anchor)
+ path = build_path(path, ast, requirements, anchor)
conditions = build_conditions(conditions, path.names.map { |x| x.to_sym })
route = @set.add_route(app, path, conditions, defaults, name)
@@ -428,7 +428,7 @@ module ActionDispatch
route
end
- def build_path(path, ast, requirements, separators, anchor)
+ def build_path(path, ast, requirements, anchor)
strexp = Journey::Router::Strexp.new(
ast,
path,
diff --git a/actionpack/lib/action_dispatch/testing/integration.rb b/actionpack/lib/action_dispatch/testing/integration.rb
index 05d74e6a27..e326776bbc 100644
--- a/actionpack/lib/action_dispatch/testing/integration.rb
+++ b/actionpack/lib/action_dispatch/testing/integration.rb
@@ -188,8 +188,8 @@ module ActionDispatch
# This makes app.url_for and app.foo_path available in the console
if app.respond_to?(:routes)
singleton_class.class_eval do
- include app.routes.url_helpers if app.routes.respond_to?(:url_helpers)
- include app.routes.mounted_helpers if app.routes.respond_to?(:mounted_helpers)
+ include app.routes.url_helpers
+ include app.routes.mounted_helpers
end
end
@@ -347,7 +347,7 @@ module ActionDispatch
# By default, a single session is automatically created for you, but you
# can use this method to open multiple sessions that ought to be tested
# simultaneously.
- def open_session(app = nil)
+ def open_session
dup.tap do |session|
yield session if block_given?
end
diff --git a/actionpack/lib/action_dispatch/testing/test_request.rb b/actionpack/lib/action_dispatch/testing/test_request.rb
index 57c678843b..de3dc5f924 100644
--- a/actionpack/lib/action_dispatch/testing/test_request.rb
+++ b/actionpack/lib/action_dispatch/testing/test_request.rb
@@ -39,7 +39,7 @@ module ActionDispatch
end
def action=(action_name)
- path_parameters["action"] = action_name.to_s
+ path_parameters[:action] = action_name.to_s
end
def if_modified_since=(last_modified)