aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack')
-rw-r--r--actionpack/CHANGELOG.md18
-rw-r--r--actionpack/README.rdoc2
-rw-r--r--actionpack/Rakefile14
-rw-r--r--actionpack/lib/action_controller/metal/conditional_get.rb4
-rw-r--r--actionpack/lib/action_controller/metal/helpers.rb2
-rw-r--r--actionpack/lib/action_controller/metal/params_wrapper.rb5
-rw-r--r--actionpack/lib/action_controller/metal/rendering.rb1
-rw-r--r--actionpack/lib/action_controller/metal/request_forgery_protection.rb4
-rw-r--r--actionpack/lib/action_controller/metal/streaming.rb6
-rw-r--r--actionpack/lib/action_controller/template_assertions.rb188
-rw-r--r--actionpack/lib/action_controller/test_case.rb216
-rw-r--r--actionpack/lib/action_dispatch/http/mime_types.rb2
-rw-r--r--actionpack/lib/action_dispatch/http/request.rb59
-rw-r--r--actionpack/lib/action_dispatch/http/response.rb2
-rw-r--r--actionpack/lib/action_dispatch/journey/routes.rb4
-rw-r--r--actionpack/lib/action_dispatch/middleware/request_id.rb13
-rw-r--r--actionpack/lib/action_dispatch/middleware/static.rb11
-rw-r--r--actionpack/lib/action_dispatch/testing/integration.rb4
-rw-r--r--actionpack/test/abstract_unit.rb2
-rw-r--r--actionpack/test/controller/action_pack_assertions_test.rb2
-rw-r--r--actionpack/test/controller/base_test.rb4
-rw-r--r--actionpack/test/controller/flash_test.rb2
-rw-r--r--actionpack/test/controller/log_subscriber_test.rb4
-rw-r--r--actionpack/test/controller/render_test.rb10
-rw-r--r--actionpack/test/controller/request_forgery_protection_test.rb6
-rw-r--r--actionpack/test/controller/test_case_test.rb31
-rw-r--r--actionpack/test/dispatch/request_test.rb1
-rw-r--r--actionpack/test/dispatch/routing/route_set_test.rb14
-rw-r--r--actionpack/test/dispatch/static_test.rb14
-rw-r--r--actionpack/test/fixtures/public/foo/other-index.html1
-rw-r--r--actionpack/test/fixtures/public/other-index.html1
-rw-r--r--actionpack/test/fixtures/公共/foo/other-index.html1
-rw-r--r--actionpack/test/fixtures/公共/other-index.html1
-rw-r--r--actionpack/test/journey/route_test.rb2
-rw-r--r--actionpack/test/journey/routes_test.rb2
35 files changed, 352 insertions, 301 deletions
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index e0076225ba..4e26a2a60e 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -1,4 +1,16 @@
-* Fix rake routes not showing the right format when
+* `FileHandler` and `Static` middleware initializers accept `index` argument
+ to configure the directory index file name. Defaults to `index` (as in
+ `index.html`).
+
+ See #20017.
+
+ *Eliot Sykes*
+
+* Deprecate `:nothing` option for `render` method.
+
+ *Mehmet Emin İNAÇ*
+
+* Fix `rake routes` not showing the right format when
nesting multiple routes.
See #18373.
@@ -281,7 +293,7 @@
* Ensure `append_info_to_payload` is called even if an exception is raised.
- Fixes an issue where when an exception is raised in the request the additonal
+ Fixes an issue where when an exception is raised in the request the additional
payload data is not available.
See:
@@ -312,7 +324,7 @@
* Stop converting empty arrays in `params` to `nil`.
- This behaviour was introduced in response to CVE-2012-2660, CVE-2012-2694
+ This behavior was introduced in response to CVE-2012-2660, CVE-2012-2694
and CVE-2013-0155
ActiveRecord now issues a safe query when passing an empty array into
diff --git a/actionpack/README.rdoc b/actionpack/README.rdoc
index 02a24a7412..44c980b070 100644
--- a/actionpack/README.rdoc
+++ b/actionpack/README.rdoc
@@ -28,7 +28,7 @@ can be used outside of Rails.
The latest version of Action Pack can be installed with RubyGems:
- % [sudo] gem install actionpack
+ % gem install actionpack
Source code can be downloaded as part of the Rails project on GitHub
diff --git a/actionpack/Rakefile b/actionpack/Rakefile
index 3bd27f8d64..601263bfac 100644
--- a/actionpack/Rakefile
+++ b/actionpack/Rakefile
@@ -1,5 +1,4 @@
require 'rake/testtask'
-require 'rubygems/package_task'
test_files = Dir.glob('test/**/*_test.rb')
@@ -24,19 +23,6 @@ namespace :test do
end
end
-spec = eval(File.read('actionpack.gemspec'))
-
-Gem::PackageTask.new(spec) do |p|
- p.gem_spec = spec
-end
-
-desc "Release to rubygems"
-task :release => :package do
- require 'rake/gemcutter'
- Rake::Gemcutter::Tasks.new(spec).define
- Rake::Task['gem:push'].invoke
-end
-
task :lines do
load File.expand_path('..', File.dirname(__FILE__)) + '/tools/line_statistics'
files = FileList["lib/**/*.rb"]
diff --git a/actionpack/lib/action_controller/metal/conditional_get.rb b/actionpack/lib/action_controller/metal/conditional_get.rb
index 47bcfdb1e9..bb3ad9b850 100644
--- a/actionpack/lib/action_controller/metal/conditional_get.rb
+++ b/actionpack/lib/action_controller/metal/conditional_get.rb
@@ -40,7 +40,7 @@ module ActionController
# * <tt>:etag</tt>.
# * <tt>:last_modified</tt>.
# * <tt>:public</tt> By default the Cache-Control header is private, set this to
- # +true+ if you want your application to be cachable by other devices (proxy caches).
+ # +true+ if you want your application to be cacheable by other devices (proxy caches).
# * <tt>:template</tt> By default, the template digest for the current
# controller/action is included in ETags. If the action renders a
# different template, you can include its digest instead. If the action
@@ -111,7 +111,7 @@ module ActionController
# * <tt>:etag</tt>.
# * <tt>:last_modified</tt>.
# * <tt>:public</tt> By default the Cache-Control header is private, set this to
- # +true+ if you want your application to be cachable by other devices (proxy caches).
+ # +true+ if you want your application to be cacheable by other devices (proxy caches).
# * <tt>:template</tt> By default, the template digest for the current
# controller/action is included in ETags. If the action renders a
# different template, you can include its digest instead. If the action
diff --git a/actionpack/lib/action_controller/metal/helpers.rb b/actionpack/lib/action_controller/metal/helpers.rb
index 4038101fe0..b4da381d26 100644
--- a/actionpack/lib/action_controller/metal/helpers.rb
+++ b/actionpack/lib/action_controller/metal/helpers.rb
@@ -44,7 +44,7 @@ module ActionController
# the output might look like this:
#
# 23 Aug 11:30 | Carolina Railhawks Soccer Match
- # N/A | Carolina Railhaws Training Workshop
+ # N/A | Carolina Railhawks Training Workshop
#
module Helpers
extend ActiveSupport::Concern
diff --git a/actionpack/lib/action_controller/metal/params_wrapper.rb b/actionpack/lib/action_controller/metal/params_wrapper.rb
index 0a04848eba..8a4ea70649 100644
--- a/actionpack/lib/action_controller/metal/params_wrapper.rb
+++ b/actionpack/lib/action_controller/metal/params_wrapper.rb
@@ -8,8 +8,7 @@ module ActionController
# POST requests without having to specify any root elements.
#
# This functionality is enabled in +config/initializers/wrap_parameters.rb+
- # and can be customized. If you are upgrading to \Rails 3.1, this file will
- # need to be created for the functionality to be enabled.
+ # and can be customized.
#
# You could also turn it on per controller by setting the format array to
# a non-empty array:
@@ -251,7 +250,7 @@ module ActionController
private
- # Returns the wrapper key which will be used to stored wrapped parameters.
+ # Returns the wrapper key which will be used to store wrapped parameters.
def _wrapper_key
_wrapper_options.name
end
diff --git a/actionpack/lib/action_controller/metal/rendering.rb b/actionpack/lib/action_controller/metal/rendering.rb
index 2d15c39d88..b9ae8dd5ea 100644
--- a/actionpack/lib/action_controller/metal/rendering.rb
+++ b/actionpack/lib/action_controller/metal/rendering.rb
@@ -79,6 +79,7 @@ module ActionController
end
if options.delete(:nothing)
+ ActiveSupport::Deprecation.warn("`:nothing` option is deprecated and will be removed in Rails 5.1. Use `head` method to respond with empty response body.")
options[:body] = nil
end
diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
index 31c8856437..a7bd3622ee 100644
--- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb
+++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
@@ -19,7 +19,7 @@ module ActionController #:nodoc:
#
# Since HTML and JavaScript requests are typically made from the browser, we
# need to ensure to verify request authenticity for the web browser. We can
- # use session-oriented authentication for these types requests, by using
+ # use session-oriented authentication for these types of requests, by using
# the `protect_form_forgery` method in our controllers.
#
# GET requests are not protected since they don't have side effects like writing
@@ -44,7 +44,7 @@ module ActionController #:nodoc:
# during request.
#
# We may want to disable CSRF protection for APIs since they are typically
- # designed to be state-less. That is, the requestion API client will handle
+ # designed to be state-less. That is, the request API client will handle
# the session for you instead of Rails.
#
# The token parameter is named <tt>authenticity_token</tt> by default. The name and
diff --git a/actionpack/lib/action_controller/metal/streaming.rb b/actionpack/lib/action_controller/metal/streaming.rb
index 04401cad7b..af31de1f3a 100644
--- a/actionpack/lib/action_controller/metal/streaming.rb
+++ b/actionpack/lib/action_controller/metal/streaming.rb
@@ -110,9 +110,9 @@ module ActionController #:nodoc:
# This means that, if you have <code>yield :title</code> in your layout
# and you want to use streaming, you would have to render the whole template
# (and eventually trigger all queries) before streaming the title and all
- # assets, which kills the purpose of streaming. For this reason Rails 3.1
- # introduces a new helper called +provide+ that does the same as +content_for+
- # but tells the layout to stop searching for other entries and continue rendering.
+ # assets, which kills the purpose of streaming. For this purpose, you can use
+ # a helper called +provide+ that does the same as +content_for+ but tells the
+ # layout to stop searching for other entries and continue rendering.
#
# For instance, the template above using +provide+ would be:
#
diff --git a/actionpack/lib/action_controller/template_assertions.rb b/actionpack/lib/action_controller/template_assertions.rb
new file mode 100644
index 0000000000..304012d24d
--- /dev/null
+++ b/actionpack/lib/action_controller/template_assertions.rb
@@ -0,0 +1,188 @@
+module ActionController
+ module TemplateAssertions
+ extend ActiveSupport::Concern
+
+ included do
+ setup :setup_subscriptions
+ teardown :teardown_subscriptions
+ end
+
+ RENDER_TEMPLATE_INSTANCE_VARIABLES = %w{partials templates layouts files}.freeze
+
+ def setup_subscriptions
+ RENDER_TEMPLATE_INSTANCE_VARIABLES.each do |instance_variable|
+ instance_variable_set("@_#{instance_variable}", Hash.new(0))
+ end
+
+ @_subscribers = []
+
+ @_subscribers << ActiveSupport::Notifications.subscribe("render_template.action_view") do |_name, _start, _finish, _id, payload|
+ path = payload[:layout]
+ if path
+ @_layouts[path] += 1
+ if path =~ /^layouts\/(.*)/
+ @_layouts[$1] += 1
+ end
+ end
+ end
+
+ @_subscribers << ActiveSupport::Notifications.subscribe("!render_template.action_view") do |_name, _start, _finish, _id, payload|
+ if virtual_path = payload[:virtual_path]
+ partial = virtual_path =~ /^.*\/_[^\/]*$/
+
+ if partial
+ @_partials[virtual_path] += 1
+ @_partials[virtual_path.split("/").last] += 1
+ end
+
+ @_templates[virtual_path] += 1
+ else
+ path = payload[:identifier]
+ if path
+ @_files[path] += 1
+ @_files[path.split("/").last] += 1
+ end
+ end
+ end
+ end
+
+ def teardown_subscriptions
+ @_subscribers.each do |subscriber|
+ ActiveSupport::Notifications.unsubscribe(subscriber)
+ end
+ end
+
+ def process(*args)
+ reset_template_assertion
+ super
+ end
+
+ def reset_template_assertion
+ RENDER_TEMPLATE_INSTANCE_VARIABLES.each do |instance_variable|
+ ivar_name = "@_#{instance_variable}"
+ if instance_variable_defined?(ivar_name)
+ instance_variable_get(ivar_name).clear
+ end
+ end
+ end
+
+ # Asserts that the request was rendered with the appropriate template file or partials.
+ #
+ # # assert that the "new" view template was rendered
+ # assert_template "new"
+ #
+ # # assert that the exact template "admin/posts/new" was rendered
+ # assert_template %r{\Aadmin/posts/new\Z}
+ #
+ # # assert that the layout 'admin' was rendered
+ # assert_template layout: 'admin'
+ # assert_template layout: 'layouts/admin'
+ # assert_template layout: :admin
+ #
+ # # assert that no layout was rendered
+ # assert_template layout: nil
+ # assert_template layout: false
+ #
+ # # assert that the "_customer" partial was rendered twice
+ # assert_template partial: '_customer', count: 2
+ #
+ # # assert that no partials were rendered
+ # assert_template partial: false
+ #
+ # # assert that a file was rendered
+ # assert_template file: "README.rdoc"
+ #
+ # # assert that no file was rendered
+ # assert_template file: nil
+ # assert_template file: false
+ #
+ # In a view test case, you can also assert that specific locals are passed
+ # to partials:
+ #
+ # # assert that the "_customer" partial was rendered with a specific object
+ # assert_template partial: '_customer', locals: { customer: @customer }
+ def assert_template(options = {}, message = nil)
+ # Force body to be read in case the template is being streamed.
+ response.body
+
+ case options
+ when NilClass, Regexp, String, Symbol
+ options = options.to_s if Symbol === options
+ rendered = @_templates
+ msg = message || sprintf("expecting <%s> but rendering with <%s>",
+ options.inspect, rendered.keys)
+ matches_template =
+ case options
+ when String
+ !options.empty? && rendered.any? do |t, num|
+ options_splited = options.split(File::SEPARATOR)
+ t_splited = t.split(File::SEPARATOR)
+ t_splited.last(options_splited.size) == options_splited
+ end
+ when Regexp
+ rendered.any? { |t,num| t.match(options) }
+ when NilClass
+ rendered.blank?
+ end
+ assert matches_template, msg
+ when Hash
+ options.assert_valid_keys(:layout, :partial, :locals, :count, :file)
+
+ if options.key?(:layout)
+ expected_layout = options[:layout]
+ msg = message || sprintf("expecting layout <%s> but action rendered <%s>",
+ expected_layout, @_layouts.keys)
+
+ case expected_layout
+ when String, Symbol
+ assert_includes @_layouts.keys, expected_layout.to_s, msg
+ when Regexp
+ assert(@_layouts.keys.any? {|l| l =~ expected_layout }, msg)
+ when nil, false
+ assert(@_layouts.empty?, msg)
+ else
+ raise ArgumentError, "assert_template only accepts a String, Symbol, Regexp, nil or false for :layout"
+ end
+ end
+
+ if options[:file]
+ assert_includes @_files.keys, options[:file]
+ elsif options.key?(:file)
+ assert @_files.blank?, "expected no files but #{@_files.keys} was rendered"
+ end
+
+ if expected_partial = options[:partial]
+ if expected_locals = options[:locals]
+ if defined?(@_rendered_views)
+ view = expected_partial.to_s.sub(/^_/, '').sub(/\/_(?=[^\/]+\z)/, '/')
+
+ partial_was_not_rendered_msg = "expected %s to be rendered but it was not." % view
+ assert_includes @_rendered_views.rendered_views, view, partial_was_not_rendered_msg
+
+ msg = 'expecting %s to be rendered with %s but was with %s' % [expected_partial,
+ expected_locals,
+ @_rendered_views.locals_for(view)]
+ assert(@_rendered_views.view_rendered?(view, options[:locals]), msg)
+ else
+ warn "the :locals option to #assert_template is only supported in a ActionView::TestCase"
+ end
+ elsif expected_count = options[:count]
+ actual_count = @_partials[expected_partial]
+ msg = message || sprintf("expecting %s to be rendered %s time(s) but rendered %s time(s)",
+ expected_partial, expected_count, actual_count)
+ assert(actual_count == expected_count.to_i, msg)
+ else
+ msg = message || sprintf("expecting partial <%s> but action rendered <%s>",
+ options[:partial], @_partials.keys)
+ assert_includes @_partials, expected_partial, msg
+ end
+ elsif options.key?(:partial)
+ assert @_partials.empty?,
+ "Expected no partials to be rendered"
+ end
+ else
+ raise ArgumentError, "assert_template only accepts a String, Symbol, Hash, Regexp, or nil"
+ end
+ end
+ end
+end
diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb
index ca7ba90c40..b29c5b23fc 100644
--- a/actionpack/lib/action_controller/test_case.rb
+++ b/actionpack/lib/action_controller/test_case.rb
@@ -2,197 +2,10 @@ require 'rack/session/abstract/id'
require 'active_support/core_ext/object/to_query'
require 'active_support/core_ext/module/anonymous'
require 'active_support/core_ext/hash/keys'
-
+require 'action_controller/template_assertions'
require 'rails-dom-testing'
module ActionController
- module TemplateAssertions
- extend ActiveSupport::Concern
-
- included do
- setup :setup_subscriptions
- teardown :teardown_subscriptions
- end
-
- RENDER_TEMPLATE_INSTANCE_VARIABLES = %w{partials templates layouts files}.freeze
-
- def setup_subscriptions
- RENDER_TEMPLATE_INSTANCE_VARIABLES.each do |instance_variable|
- instance_variable_set("@_#{instance_variable}", Hash.new(0))
- end
-
- @_subscribers = []
-
- @_subscribers << ActiveSupport::Notifications.subscribe("render_template.action_view") do |_name, _start, _finish, _id, payload|
- path = payload[:layout]
- if path
- @_layouts[path] += 1
- if path =~ /^layouts\/(.*)/
- @_layouts[$1] += 1
- end
- end
- end
-
- @_subscribers << ActiveSupport::Notifications.subscribe("!render_template.action_view") do |_name, _start, _finish, _id, payload|
- if virtual_path = payload[:virtual_path]
- partial = virtual_path =~ /^.*\/_[^\/]*$/
-
- if partial
- @_partials[virtual_path] += 1
- @_partials[virtual_path.split("/").last] += 1
- end
-
- @_templates[virtual_path] += 1
- else
- path = payload[:identifier]
- if path
- @_files[path] += 1
- @_files[path.split("/").last] += 1
- end
- end
- end
- end
-
- def teardown_subscriptions
- @_subscribers.each do |subscriber|
- ActiveSupport::Notifications.unsubscribe(subscriber)
- end
- end
-
- def process(*args)
- reset_template_assertion
- super
- end
-
- def reset_template_assertion
- RENDER_TEMPLATE_INSTANCE_VARIABLES.each do |instance_variable|
- ivar_name = "@_#{instance_variable}"
- if instance_variable_defined?(ivar_name)
- instance_variable_get(ivar_name).clear
- end
- end
- end
-
- # Asserts that the request was rendered with the appropriate template file or partials.
- #
- # # assert that the "new" view template was rendered
- # assert_template "new"
- #
- # # assert that the exact template "admin/posts/new" was rendered
- # assert_template %r{\Aadmin/posts/new\Z}
- #
- # # assert that the layout 'admin' was rendered
- # assert_template layout: 'admin'
- # assert_template layout: 'layouts/admin'
- # assert_template layout: :admin
- #
- # # assert that no layout was rendered
- # assert_template layout: nil
- # assert_template layout: false
- #
- # # assert that the "_customer" partial was rendered twice
- # assert_template partial: '_customer', count: 2
- #
- # # assert that no partials were rendered
- # assert_template partial: false
- #
- # # assert that a file was rendered
- # assert_template file: "README.rdoc"
- #
- # # assert that no file was rendered
- # assert_template file: nil
- # assert_template file: false
- #
- # In a view test case, you can also assert that specific locals are passed
- # to partials:
- #
- # # assert that the "_customer" partial was rendered with a specific object
- # assert_template partial: '_customer', locals: { customer: @customer }
- def assert_template(options = {}, message = nil)
- # Force body to be read in case the template is being streamed.
- response.body
-
- case options
- when NilClass, Regexp, String, Symbol
- options = options.to_s if Symbol === options
- rendered = @_templates
- msg = message || sprintf("expecting <%s> but rendering with <%s>",
- options.inspect, rendered.keys)
- matches_template =
- case options
- when String
- !options.empty? && rendered.any? do |t, num|
- options_splited = options.split(File::SEPARATOR)
- t_splited = t.split(File::SEPARATOR)
- t_splited.last(options_splited.size) == options_splited
- end
- when Regexp
- rendered.any? { |t,num| t.match(options) }
- when NilClass
- rendered.blank?
- end
- assert matches_template, msg
- when Hash
- options.assert_valid_keys(:layout, :partial, :locals, :count, :file)
-
- if options.key?(:layout)
- expected_layout = options[:layout]
- msg = message || sprintf("expecting layout <%s> but action rendered <%s>",
- expected_layout, @_layouts.keys)
-
- case expected_layout
- when String, Symbol
- assert_includes @_layouts.keys, expected_layout.to_s, msg
- when Regexp
- assert(@_layouts.keys.any? {|l| l =~ expected_layout }, msg)
- when nil, false
- assert(@_layouts.empty?, msg)
- else
- raise ArgumentError, "assert_template only accepts a String, Symbol, Regexp, nil or false for :layout"
- end
- end
-
- if options[:file]
- assert_includes @_files.keys, options[:file]
- elsif options.key?(:file)
- assert @_files.blank?, "expected no files but #{@_files.keys} was rendered"
- end
-
- if expected_partial = options[:partial]
- if expected_locals = options[:locals]
- if defined?(@_rendered_views)
- view = expected_partial.to_s.sub(/^_/, '').sub(/\/_(?=[^\/]+\z)/, '/')
-
- partial_was_not_rendered_msg = "expected %s to be rendered but it was not." % view
- assert_includes @_rendered_views.rendered_views, view, partial_was_not_rendered_msg
-
- msg = 'expecting %s to be rendered with %s but was with %s' % [expected_partial,
- expected_locals,
- @_rendered_views.locals_for(view)]
- assert(@_rendered_views.view_rendered?(view, options[:locals]), msg)
- else
- warn "the :locals option to #assert_template is only supported in a ActionView::TestCase"
- end
- elsif expected_count = options[:count]
- actual_count = @_partials[expected_partial]
- msg = message || sprintf("expecting %s to be rendered %s time(s) but rendered %s time(s)",
- expected_partial, expected_count, actual_count)
- assert(actual_count == expected_count.to_i, msg)
- else
- msg = message || sprintf("expecting partial <%s> but action rendered <%s>",
- options[:partial], @_partials.keys)
- assert_includes @_partials, expected_partial, msg
- end
- elsif options.key?(:partial)
- assert @_partials.empty?,
- "Expected no partials to be rendered"
- end
- else
- raise ArgumentError, "assert_template only accepts a String, Symbol, Hash, Regexp, or nil"
- end
- end
- end
-
class TestRequest < ActionDispatch::TestRequest #:nodoc:
DEFAULT_ENV = ActionDispatch::TestRequest::DEFAULT_ENV.dup
DEFAULT_ENV.delete 'PATH_INFO'
@@ -205,9 +18,10 @@ module ActionController
end
def assign_parameters(routes, controller_path, action, parameters = {})
- parameters = parameters.symbolize_keys.merge(:controller => controller_path, :action => action)
- extra_keys = routes.extra_keys(parameters)
+ parameters = parameters.symbolize_keys
+ extra_keys = routes.extra_keys(parameters.merge(:controller => controller_path, :action => action))
non_path_parameters = get? ? query_parameters : request_parameters
+
parameters.each do |key, value|
if value.is_a?(Array) && (value.frozen? || value.any?(&:frozen?))
value = value.map{ |v| v.duplicable? ? v.dup : v }
@@ -217,7 +31,7 @@ module ActionController
value = value.dup
end
- if extra_keys.include?(key)
+ if extra_keys.include?(key) || key == :action || key == :controller
non_path_parameters[key] = value
else
if value.is_a?(Array)
@@ -230,19 +44,16 @@ module ActionController
end
end
+ path_parameters[:controller] = controller_path
+ path_parameters[:action] = action
+
# Clear the combined params hash in case it was already referenced.
@env.delete("action_dispatch.request.parameters")
# Clear the filter cache variables so they're not stale
@filtered_parameters = @filtered_env = @filtered_path = nil
- params = self.request_parameters.dup
- %w(controller action only_path).each do |k|
- params.delete(k)
- params.delete(k.to_sym)
- end
- data = params.to_query
-
+ data = request_parameters.to_query
@env['CONTENT_LENGTH'] = data.length.to_s
@env['rack.input'] = StringIO.new(data)
end
@@ -669,12 +480,10 @@ module ActionController
@controller.request = @request
@controller.response = @response
- build_request_uri(action, parameters)
-
- name = @request.parameters[:action]
+ build_request_uri(controller_class_name, action, parameters)
@controller.recycle!
- @controller.process(name)
+ @controller.process(action)
if cookies = @request.env['action_dispatch.cookies']
unless @response.committed?
@@ -790,10 +599,11 @@ module ActionController
end
end
- def build_request_uri(action, parameters)
+ def build_request_uri(controller_class_name, action, parameters)
unless @request.env["PATH_INFO"]
options = @controller.respond_to?(:url_options) ? @controller.__send__(:url_options).merge(parameters) : parameters
options.update(
+ :controller => controller_class_name,
:action => action,
:relative_url_root => nil,
:_recall => @request.path_parameters)
diff --git a/actionpack/lib/action_dispatch/http/mime_types.rb b/actionpack/lib/action_dispatch/http/mime_types.rb
index 0e4da36038..01a10c693b 100644
--- a/actionpack/lib/action_dispatch/http/mime_types.rb
+++ b/actionpack/lib/action_dispatch/http/mime_types.rb
@@ -27,7 +27,7 @@ Mime::Type.register "application/x-www-form-urlencoded", :url_encoded_form
# http://www.ietf.org/rfc/rfc4627.txt
# http://www.json.org/JSONRequest.html
-Mime::Type.register "application/json", :json, %w( text/x-json application/jsonrequest )
+Mime::Type.register "application/json", :json, %w( text/x-json application/jsonrequest application/vnd.api+json )
Mime::Type.register "application/pdf", :pdf, [], %w(pdf)
Mime::Type.register "application/zip", :zip, [], %w(zip)
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb
index a1f84e5ace..fe83c01562 100644
--- a/actionpack/lib/action_dispatch/http/request.rb
+++ b/actionpack/lib/action_dispatch/http/request.rb
@@ -20,6 +20,8 @@ module ActionDispatch
include ActionDispatch::Http::FilterParameters
include ActionDispatch::Http::URL
+ HTTP_X_REQUEST_ID = "HTTP_X_REQUEST_ID".freeze # :nodoc:
+
autoload :Session, 'action_dispatch/request/session'
autoload :Utils, 'action_dispatch/request/utils'
@@ -50,7 +52,6 @@ module ActionDispatch
@original_fullpath = nil
@fullpath = nil
@ip = nil
- @request_id = nil
end
def check_path_parameters!
@@ -140,47 +141,11 @@ module ActionDispatch
HTTP_METHOD_LOOKUP[method]
end
- # Is this a GET (or HEAD) request?
- # Equivalent to <tt>request.request_method_symbol == :get</tt>.
- def get?
- HTTP_METHOD_LOOKUP[request_method] == :get
- end
-
- # Is this a POST request?
- # Equivalent to <tt>request.request_method_symbol == :post</tt>.
- def post?
- HTTP_METHOD_LOOKUP[request_method] == :post
- end
-
- # Is this a PATCH request?
- # Equivalent to <tt>request.request_method == :patch</tt>.
- def patch?
- HTTP_METHOD_LOOKUP[request_method] == :patch
- end
-
- # Is this a PUT request?
- # Equivalent to <tt>request.request_method_symbol == :put</tt>.
- def put?
- HTTP_METHOD_LOOKUP[request_method] == :put
- end
-
- # Is this a DELETE request?
- # Equivalent to <tt>request.request_method_symbol == :delete</tt>.
- def delete?
- HTTP_METHOD_LOOKUP[request_method] == :delete
- end
-
- # Is this a HEAD request?
- # Equivalent to <tt>request.request_method_symbol == :head</tt>.
- def head?
- HTTP_METHOD_LOOKUP[request_method] == :head
- end
-
# Provides access to the request's HTTP headers, for example:
#
# request.headers["Content-Type"] # => "text/plain"
def headers
- Http::Headers.new(@env)
+ @headers ||= Http::Headers.new(@env)
end
# Returns a +String+ with the last requested path including their params.
@@ -234,15 +199,19 @@ module ActionDispatch
end
alias :xhr? :xml_http_request?
+ # Returns the IP address of client as a +String+.
def ip
@ip ||= super
end
- # Originating IP address, usually set by the RemoteIp middleware.
+ # Returns the IP address of client as a +String+,
+ # usually set by the RemoteIp middleware.
def remote_ip
@remote_ip ||= (@env["action_dispatch.remote_ip"] || ip).to_s
end
+ ACTION_DISPATCH_REQUEST_ID = "action_dispatch.request_id".freeze # :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
# (which sets the action_dispatch.request_id environment variable).
@@ -250,11 +219,19 @@ module ActionDispatch
# This unique ID is useful for tracing a request from end-to-end as part of logging or debugging.
# This relies on the rack variable set by the ActionDispatch::RequestId middleware.
def request_id
- @request_id ||= env["action_dispatch.request_id"]
+ env[ACTION_DISPATCH_REQUEST_ID]
+ end
+
+ def request_id=(id) # :nodoc:
+ env[ACTION_DISPATCH_REQUEST_ID] = id
end
alias_method :uuid, :request_id
+ def x_request_id # :nodoc
+ @env[HTTP_X_REQUEST_ID]
+ end
+
# Returns the lowercase name of the HTTP server software.
def server_software
(@env['SERVER_SOFTWARE'] && /^([a-zA-Z]+)/ =~ @env['SERVER_SOFTWARE']) ? $1.downcase : nil
@@ -282,6 +259,8 @@ module ActionDispatch
end
end
+ # returns true if request content mime type is
+ # +application/x-www-form-urlencoded+ or +multipart/form-data+.
def form_data?
FORM_DATA_MEDIA_TYPES.include?(content_mime_type.to_s)
end
diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb
index a895d1ab18..9e53a0f08b 100644
--- a/actionpack/lib/action_dispatch/http/response.rb
+++ b/actionpack/lib/action_dispatch/http/response.rb
@@ -274,7 +274,7 @@ module ActionDispatch # :nodoc:
end
# Turns the Response into a Rack-compatible array of the status, headers,
- # and body. Allows explict splatting:
+ # and body. Allows explicit splatting:
#
# status, headers, body = *response
def to_a
diff --git a/actionpack/lib/action_dispatch/journey/routes.rb b/actionpack/lib/action_dispatch/journey/routes.rb
index a6d1980db2..6325dfa3dd 100644
--- a/actionpack/lib/action_dispatch/journey/routes.rb
+++ b/actionpack/lib/action_dispatch/journey/routes.rb
@@ -16,6 +16,10 @@ module ActionDispatch
@simulator = nil
end
+ def empty?
+ routes.empty?
+ end
+
def length
routes.length
end
diff --git a/actionpack/lib/action_dispatch/middleware/request_id.rb b/actionpack/lib/action_dispatch/middleware/request_id.rb
index b9ca524309..1555ff72af 100644
--- a/actionpack/lib/action_dispatch/middleware/request_id.rb
+++ b/actionpack/lib/action_dispatch/middleware/request_id.rb
@@ -13,22 +13,23 @@ module ActionDispatch
# from multiple pieces of the stack.
class RequestId
X_REQUEST_ID = "X-Request-Id".freeze # :nodoc:
- ACTION_DISPATCH_REQUEST_ID = "action_dispatch.request_id".freeze # :nodoc:
- HTTP_X_REQUEST_ID = "HTTP_X_REQUEST_ID".freeze # :nodoc:
def initialize(app)
@app = app
end
def call(env)
- env[ACTION_DISPATCH_REQUEST_ID] = external_request_id(env) || internal_request_id
- @app.call(env).tap { |_status, headers, _body| headers[X_REQUEST_ID] = env[ACTION_DISPATCH_REQUEST_ID] }
+ req = ActionDispatch::Request.new env
+ req.request_id = make_request_id(req.x_request_id)
+ @app.call(env).tap { |_status, headers, _body| headers[X_REQUEST_ID] = req.request_id }
end
private
- def external_request_id(env)
- if request_id = env[HTTP_X_REQUEST_ID].presence
+ def make_request_id(request_id)
+ if request_id.presence
request_id.gsub(/[^\w\-]/, "".freeze).first(255)
+ else
+ internal_request_id
end
end
diff --git a/actionpack/lib/action_dispatch/middleware/static.rb b/actionpack/lib/action_dispatch/middleware/static.rb
index c47e5d5245..f20f6ca865 100644
--- a/actionpack/lib/action_dispatch/middleware/static.rb
+++ b/actionpack/lib/action_dispatch/middleware/static.rb
@@ -13,11 +13,12 @@ module ActionDispatch
# located at `public/assets/application.js` if the file exists. If the file
# does not exist, a 404 "File not Found" response will be returned.
class FileHandler
- def initialize(root, cache_control)
+ def initialize(root, cache_control, index)
@root = root.chomp('/')
@compiled_root = /^#{Regexp.escape(root)}/
headers = cache_control && { 'Cache-Control' => cache_control }
@file_server = ::Rack::File.new(@root, headers)
+ @index = index
end
@@ -26,13 +27,13 @@ module ActionDispatch
# representing the filename. Otherwise, false is returned.
#
# Used by the `Static` class to check the existence of a valid file
- # in the server's `public/` directory. (See Static#call)
+ # in the server's `public/` directory (see Static#call).
def match?(path)
path = URI.parser.unescape(path)
return false unless path.valid_encoding?
path = Rack::Utils.clean_path_info path
- paths = [path, "#{path}#{ext}", "#{path}/index#{ext}"]
+ paths = [path, "#{path}#{ext}", "#{path}/#{@index}#{ext}"]
if match = paths.detect { |p|
path = File.join(@root, p.force_encoding('UTF-8'))
@@ -104,9 +105,9 @@ module ActionDispatch
# produce a directory traversal using this middleware. Only 'GET' and 'HEAD'
# requests will result in a file being returned.
class Static
- def initialize(app, path, cache_control=nil)
+ def initialize(app, path, cache_control=nil, index="index")
@app = app
- @file_handler = FileHandler.new(path, cache_control)
+ @file_handler = FileHandler.new(path, cache_control, index)
end
def call(env)
diff --git a/actionpack/lib/action_dispatch/testing/integration.rb b/actionpack/lib/action_dispatch/testing/integration.rb
index b1bd6ae6d5..f953429e96 100644
--- a/actionpack/lib/action_dispatch/testing/integration.rb
+++ b/actionpack/lib/action_dispatch/testing/integration.rb
@@ -584,7 +584,7 @@ module ActionDispatch
# https!(false)
# get "/articles/all"
# assert_response :success
- # assert assigns(:articles)
+ # assert_select 'h1', 'Articles'
# end
# end
#
@@ -623,7 +623,7 @@ module ActionDispatch
# def browses_site
# get "/products/all"
# assert_response :success
- # assert assigns(:products)
+ # assert_select 'h1', 'Products'
# end
# end
#
diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb
index c1be2c9afe..1690bdd542 100644
--- a/actionpack/test/abstract_unit.rb
+++ b/actionpack/test/abstract_unit.rb
@@ -380,7 +380,7 @@ module RoutingTestHelpers
end
class ResourcesController < ActionController::Base
- def index() render :nothing => true end
+ def index() head :ok end
alias_method :show, :index
end
diff --git a/actionpack/test/controller/action_pack_assertions_test.rb b/actionpack/test/controller/action_pack_assertions_test.rb
index 21586e2193..cbf333c772 100644
--- a/actionpack/test/controller/action_pack_assertions_test.rb
+++ b/actionpack/test/controller/action_pack_assertions_test.rb
@@ -123,7 +123,7 @@ end
module Admin
class InnerModuleController < ActionController::Base
def index
- render :nothing => true
+ head :ok
end
def redirect_to_index
diff --git a/actionpack/test/controller/base_test.rb b/actionpack/test/controller/base_test.rb
index f7ad8e5158..3240185414 100644
--- a/actionpack/test/controller/base_test.rb
+++ b/actionpack/test/controller/base_test.rb
@@ -13,7 +13,7 @@ end
class NonEmptyController < ActionController::Base
def public_action
- render :nothing => true
+ head :ok
end
end
@@ -29,7 +29,7 @@ end
class OptionalDefaultUrlOptionsController < ActionController::Base
def show
- render nothing: true
+ head :ok
end
def default_url_options
diff --git a/actionpack/test/controller/flash_test.rb b/actionpack/test/controller/flash_test.rb
index 0ff0a1ef61..60a000c160 100644
--- a/actionpack/test/controller/flash_test.rb
+++ b/actionpack/test/controller/flash_test.rb
@@ -57,7 +57,7 @@ class FlashTest < ActionController::TestCase
def std_action
@flash_copy = {}.update(flash)
- render :nothing => true
+ head :ok
end
def filter_halting_action
diff --git a/actionpack/test/controller/log_subscriber_test.rb b/actionpack/test/controller/log_subscriber_test.rb
index 03a4ad7823..4ae1b20d43 100644
--- a/actionpack/test/controller/log_subscriber_test.rb
+++ b/actionpack/test/controller/log_subscriber_test.rb
@@ -19,7 +19,7 @@ module Another
end
def show
- render :nothing => true
+ head :ok
end
def redirector
@@ -170,7 +170,7 @@ class ACLogSubscriberTest < ActionController::TestCase
def test_process_action_with_view_runtime
get :show
wait
- assert_match(/\(Views: [\d.]+ms\)/, logs[1])
+ assert_match /Completed 200 OK in [\d]ms/, logs[1]
end
def test_append_info_to_payload_is_called_even_with_exception
diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb
index 79e2104789..cabacad940 100644
--- a/actionpack/test/controller/render_test.rb
+++ b/actionpack/test/controller/render_test.rb
@@ -120,6 +120,10 @@ class TestController < ActionController::Base
render :action => 'hello_world'
end
+ def respond_with_empty_body
+ render nothing: true
+ end
+
def conditional_hello_with_bangs
render :action => 'hello_world'
end
@@ -270,6 +274,12 @@ class ExpiresInRenderTest < ActionController::TestCase
assert_match(/no-transform/, @response.headers["Cache-Control"])
end
+ def test_render_nothing_deprecated
+ assert_deprecated do
+ get :respond_with_empty_body
+ end
+ end
+
def test_date_header_when_expires_in
time = Time.mktime(2011,10,30)
Time.stubs(:now).returns(time)
diff --git a/actionpack/test/controller/request_forgery_protection_test.rb b/actionpack/test/controller/request_forgery_protection_test.rb
index f8cf79a257..82c808754c 100644
--- a/actionpack/test/controller/request_forgery_protection_test.rb
+++ b/actionpack/test/controller/request_forgery_protection_test.rb
@@ -72,17 +72,17 @@ class RequestForgeryProtectionControllerUsingNullSession < ActionController::Bas
def signed
cookies.signed[:foo] = 'bar'
- render :nothing => true
+ head :ok
end
def encrypted
cookies.encrypted[:foo] = 'bar'
- render :nothing => true
+ head :ok
end
def try_to_reset_session
reset_session
- render :nothing => true
+ head :ok
end
end
diff --git a/actionpack/test/controller/test_case_test.rb b/actionpack/test/controller/test_case_test.rb
index e348749f78..fbfc891d19 100644
--- a/actionpack/test/controller/test_case_test.rb
+++ b/actionpack/test/controller/test_case_test.rb
@@ -48,6 +48,14 @@ class TestCaseTest < ActionController::TestCase
render text: params.inspect
end
+ def test_query_parameters
+ render text: request.query_parameters.inspect
+ end
+
+ def test_request_parameters
+ render text: request.request_parameters.inspect
+ end
+
def test_uri
render text: request.fullpath
end
@@ -129,13 +137,13 @@ XML
def delete_cookie
cookies.delete("foo")
- render nothing: true
+ head :ok
end
def test_assigns
@foo = "foo"
@foo_hash = { foo: :bar }
- render nothing: true
+ head :ok
end
def test_without_body
@@ -169,7 +177,7 @@ XML
class ViewAssignsController < ActionController::Base
def test_assigns
@foo = "foo"
- render nothing: true
+ head :ok
end
def view_assigns
@@ -547,6 +555,18 @@ XML
)
end
+ def test_query_param_named_action
+ get :test_query_parameters, params: {action: 'foobar'}
+ parsed_params = eval(@response.body)
+ assert_equal({action: 'foobar'}, parsed_params)
+ end
+
+ def test_request_param_named_action
+ post :test_request_parameters, params: {action: 'foobar'}
+ parsed_params = eval(@response.body)
+ assert_equal({'action' => 'foobar'}, parsed_params)
+ end
+
def test_kwarg_params_passing_with_session_and_flash
get :test_params, params: {
page: {
@@ -908,6 +928,11 @@ XML
assert_equal File.open(path, READ_PLAIN).read, plain_file_upload.read
end
+ def test_fixture_file_upload_should_be_able_access_to_tempfile
+ file = fixture_file_upload(FILES_DIR + "/mona_lisa.jpg", "image/jpg")
+ assert file.respond_to?(:tempfile), "expected tempfile should respond on fixture file object, got nothing"
+ end
+
def test_fixture_file_upload
post :test_file_upload,
params: {
diff --git a/actionpack/test/dispatch/request_test.rb b/actionpack/test/dispatch/request_test.rb
index f208cfda89..27ee8603e4 100644
--- a/actionpack/test/dispatch/request_test.rb
+++ b/actionpack/test/dispatch/request_test.rb
@@ -663,6 +663,7 @@ class RequestMethod < BaseRequestTest
assert_equal 'GET', request.request_method
assert_equal 'GET', request.env["REQUEST_METHOD"]
+ assert request.get?
end
test "invalid http method raises exception" do
diff --git a/actionpack/test/dispatch/routing/route_set_test.rb b/actionpack/test/dispatch/routing/route_set_test.rb
index fe52c50336..9327fe12c6 100644
--- a/actionpack/test/dispatch/routing/route_set_test.rb
+++ b/actionpack/test/dispatch/routing/route_set_test.rb
@@ -17,6 +17,16 @@ module ActionDispatch
@set = RouteSet.new
end
+ test "not being empty when route is added" do
+ assert empty?
+
+ draw do
+ get 'foo', to: SimpleApp.new('foo#index')
+ end
+
+ assert_not empty?
+ end
+
test "url helpers are added when route is added" do
draw do
get 'foo', to: SimpleApp.new('foo#index')
@@ -136,6 +146,10 @@ module ActionDispatch
def url_helpers
@set.url_helpers
end
+
+ def empty?
+ @set.empty?
+ end
end
end
end
diff --git a/actionpack/test/dispatch/static_test.rb b/actionpack/test/dispatch/static_test.rb
index 93e5c85a97..e729cc44f9 100644
--- a/actionpack/test/dispatch/static_test.rb
+++ b/actionpack/test/dispatch/static_test.rb
@@ -57,6 +57,7 @@ module StaticTests
def test_serves_static_index_file_in_directory
assert_html "/foo/index.html", get("/foo/index.html")
+ assert_html "/foo/index.html", get("/foo/index")
assert_html "/foo/index.html", get("/foo/")
assert_html "/foo/index.html", get("/foo")
end
@@ -260,6 +261,19 @@ class StaticTest < ActiveSupport::TestCase
}
assert_equal(DummyApp.call(nil), @app.call(env))
end
+
+ def test_non_default_static_index
+ @app = ActionDispatch::Static.new(DummyApp, @root, "public, max-age=60", "other-index")
+ assert_html "/other-index.html", get("/other-index.html")
+ assert_html "/other-index.html", get("/other-index")
+ assert_html "/other-index.html", get("/")
+ assert_html "/other-index.html", get("")
+ assert_html "/foo/other-index.html", get("/foo/other-index.html")
+ assert_html "/foo/other-index.html", get("/foo/other-index")
+ assert_html "/foo/other-index.html", get("/foo/")
+ assert_html "/foo/other-index.html", get("/foo")
+ end
+
end
class StaticEncodingTest < StaticTest
diff --git a/actionpack/test/fixtures/public/foo/other-index.html b/actionpack/test/fixtures/public/foo/other-index.html
new file mode 100644
index 0000000000..51c90c26ea
--- /dev/null
+++ b/actionpack/test/fixtures/public/foo/other-index.html
@@ -0,0 +1 @@
+/foo/other-index.html \ No newline at end of file
diff --git a/actionpack/test/fixtures/public/other-index.html b/actionpack/test/fixtures/public/other-index.html
new file mode 100644
index 0000000000..0820dfcb6e
--- /dev/null
+++ b/actionpack/test/fixtures/public/other-index.html
@@ -0,0 +1 @@
+/other-index.html \ No newline at end of file
diff --git a/actionpack/test/fixtures/公共/foo/other-index.html b/actionpack/test/fixtures/公共/foo/other-index.html
new file mode 100644
index 0000000000..51c90c26ea
--- /dev/null
+++ b/actionpack/test/fixtures/公共/foo/other-index.html
@@ -0,0 +1 @@
+/foo/other-index.html \ No newline at end of file
diff --git a/actionpack/test/fixtures/公共/other-index.html b/actionpack/test/fixtures/公共/other-index.html
new file mode 100644
index 0000000000..0820dfcb6e
--- /dev/null
+++ b/actionpack/test/fixtures/公共/other-index.html
@@ -0,0 +1 @@
+/other-index.html \ No newline at end of file
diff --git a/actionpack/test/journey/route_test.rb b/actionpack/test/journey/route_test.rb
index 9616f036b3..0980df06e8 100644
--- a/actionpack/test/journey/route_test.rb
+++ b/actionpack/test/journey/route_test.rb
@@ -30,7 +30,7 @@ module ActionDispatch
path = Path::Pattern.new strexp
defaults = { name: 'tender' }
route = Route.new('name', nil, path, nil, defaults)
- assert_equal /love/, route.requirements[:name]
+ assert_equal(/love/, route.requirements[:name])
end
def test_ip_address
diff --git a/actionpack/test/journey/routes_test.rb b/actionpack/test/journey/routes_test.rb
index b54d961f66..2a1c1c337e 100644
--- a/actionpack/test/journey/routes_test.rb
+++ b/actionpack/test/journey/routes_test.rb
@@ -14,9 +14,11 @@ module ActionDispatch
requirements = { :hello => /world/ }
routes.add_route nil, path, requirements, {:id => nil}, {}
+ assert_not routes.empty?
assert_equal 1, routes.length
routes.clear
+ assert routes.empty?
assert_equal 0, routes.length
end