aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack')
-rw-r--r--actionpack/CHANGELOG.md32
-rw-r--r--actionpack/lib/action_controller/metal/etag_with_template_digest.rb2
-rw-r--r--actionpack/lib/action_controller/metal/request_forgery_protection.rb6
-rw-r--r--actionpack/lib/action_controller/metal/strong_parameters.rb19
-rw-r--r--actionpack/lib/action_dispatch/http/parameter_filter.rb2
-rw-r--r--actionpack/lib/action_dispatch/http/parameters.rb9
-rw-r--r--actionpack/lib/action_dispatch/http/request.rb12
-rw-r--r--actionpack/lib/action_dispatch/middleware/exception_wrapper.rb4
-rw-r--r--actionpack/lib/action_dispatch/middleware/static.rb6
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb9
-rw-r--r--actionpack/lib/action_dispatch/routing/redirection.rb1
-rw-r--r--actionpack/lib/action_dispatch/testing/integration.rb64
-rw-r--r--actionpack/lib/action_dispatch/testing/request_encoder.rb54
-rw-r--r--actionpack/lib/action_dispatch/testing/test_response.rb9
-rw-r--r--actionpack/test/abstract_unit.rb1
-rw-r--r--actionpack/test/controller/caching_test.rb12
-rw-r--r--actionpack/test/controller/parameters/dup_test.rb43
-rw-r--r--actionpack/test/controller/parameters/parameters_permit_test.rb5
-rw-r--r--actionpack/test/controller/render_test.rb54
-rw-r--r--actionpack/test/controller/request_forgery_protection_test.rb18
-rw-r--r--actionpack/test/dispatch/exception_wrapper_test.rb6
-rw-r--r--actionpack/test/dispatch/mime_type_test.rb4
-rw-r--r--actionpack/test/dispatch/request_test.rb10
-rw-r--r--actionpack/test/dispatch/response_test.rb20
-rw-r--r--actionpack/test/dispatch/routing_test.rb42
-rw-r--r--actionpack/test/dispatch/static_test.rb9
-rw-r--r--actionpack/test/dispatch/test_response_test.rb8
-rw-r--r--actionpack/test/fixtures/namespaced/implicit_render_test/hello_world.erb1
28 files changed, 322 insertions, 140 deletions
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index be911b147c..7bb9b62468 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -1,2 +1,34 @@
+* Fix 'defaults' option for root route.
+
+ A regression from some refactoring for the 5.0 release, this change
+ fixes the use of 'defaults' (default parameters) in the 'root' routing method.
+
+ *Chris Arcand*
+
+* Check `request.path_parameters` encoding at the point they're set.
+
+ Check for any non-UTF8 characters in path parameters at the point they're
+ set in `env`. Previously they were checked for when used to get a controller
+ class, but this meant routes that went directly to a Rack app, or skipped
+ controller instantiation for some other reason, had to defend against
+ non-UTF8 characters themselves.
+
+ *Grey Baker*
+
+* Don't raise ActionController::UnknownHttpMethod from ActionDispatch::Static
+
+ Pass `Rack::Request` objects to `ActionDispatch::FileHandler` to avoid it
+ raising `ActionController::UnknownHttpMethod`. If an unknown method is
+ passed, it should exception higher in the stack instead, once we've had a
+ chance to define exception handling behaviour.
+
+ *Grey Baker*
+
+* Handle `Rack::QueryParser` errors in `ActionDispatch::ExceptionWrapper`
+
+ Updated `ActionDispatch::ExceptionWrapper` to handle the Rack 2.0 namespace
+ for `ParameterTypeError` and `InvalidParameterError` errors.
+
+ *Grey Baker*
Please check [5-0-stable](https://github.com/rails/rails/blob/5-0-stable/actionpack/CHANGELOG.md) for previous changes.
diff --git a/actionpack/lib/action_controller/metal/etag_with_template_digest.rb b/actionpack/lib/action_controller/metal/etag_with_template_digest.rb
index 75ac996793..e3a7c3b166 100644
--- a/actionpack/lib/action_controller/metal/etag_with_template_digest.rb
+++ b/actionpack/lib/action_controller/metal/etag_with_template_digest.rb
@@ -45,7 +45,7 @@ module ActionController
# template digest from the ETag.
def pick_template_for_etag(options)
unless options[:template] == false
- options[:template] || "#{controller_name}/#{action_name}"
+ options[:template] || "#{controller_path}/#{action_name}"
end
end
diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
index 0559fbc6ce..fd7ffcfcd7 100644
--- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb
+++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
@@ -109,10 +109,10 @@ module ActionController #:nodoc:
# * <tt>:only/:except</tt> - Only apply forgery protection to a subset of actions. For example <tt>only: [ :create, :create_all ]</tt>.
# * <tt>:if/:unless</tt> - Turn off the forgery protection entirely depending on the passed Proc or method reference.
# * <tt>:prepend</tt> - By default, the verification of the authentication token will be added at the position of the
- # protect_from_forgery call in your application. This means any callbacks added before are run first. This is useful
- # when you want your forgery protection to depend on other callbacks, like authentication methods (Oauth vs Cookie auth).
+ # protect_from_forgery call in your application. This means any callbacks added before are run first. This is useful
+ # when you want your forgery protection to depend on other callbacks, like authentication methods (Oauth vs Cookie auth).
#
- # If you need to add verification to the beginning of the callback chain, use <tt>prepend: true</tt>.
+ # If you need to add verification to the beginning of the callback chain, use <tt>prepend: true</tt>.
# * <tt>:with</tt> - Set the method to handle unverified request.
#
# Valid unverified request handling methods are:
diff --git a/actionpack/lib/action_controller/metal/strong_parameters.rb b/actionpack/lib/action_controller/metal/strong_parameters.rb
index b326695ce2..26794c67b7 100644
--- a/actionpack/lib/action_controller/metal/strong_parameters.rb
+++ b/actionpack/lib/action_controller/metal/strong_parameters.rb
@@ -572,20 +572,6 @@ module ActionController
convert_value_to_parameters(@parameters.values_at(*keys))
end
- # Returns an exact copy of the <tt>ActionController::Parameters</tt>
- # instance. +permitted+ state is kept on the duped object.
- #
- # params = ActionController::Parameters.new(a: 1)
- # params.permit!
- # params.permitted? # => true
- # copy_params = params.dup # => <ActionController::Parameters {"a"=>1} permitted: true>
- # copy_params.permitted? # => true
- def dup
- super.tap do |duplicate|
- duplicate.permitted = @permitted
- end
- end
-
# Returns a new <tt>ActionController::Parameters</tt> with all keys from
# +other_hash+ merges into current hash.
def merge(other_hash)
@@ -783,6 +769,11 @@ module ActionController
end
end
end
+
+ def initialize_copy(source)
+ super
+ @parameters = @parameters.dup
+ end
end
# == Strong \Parameters
diff --git a/actionpack/lib/action_dispatch/http/parameter_filter.rb b/actionpack/lib/action_dispatch/http/parameter_filter.rb
index e826551f4b..01f1666b9b 100644
--- a/actionpack/lib/action_dispatch/http/parameter_filter.rb
+++ b/actionpack/lib/action_dispatch/http/parameter_filter.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/object/duplicable'
+
module ActionDispatch
module Http
class ParameterFilter
diff --git a/actionpack/lib/action_dispatch/http/parameters.rb b/actionpack/lib/action_dispatch/http/parameters.rb
index ff5031d7d5..ea0e2ee41f 100644
--- a/actionpack/lib/action_dispatch/http/parameters.rb
+++ b/actionpack/lib/action_dispatch/http/parameters.rb
@@ -44,7 +44,14 @@ module ActionDispatch
def path_parameters=(parameters) #:nodoc:
delete_header('action_dispatch.request.parameters')
+
+ # If any of the path parameters has an invalid encoding then
+ # raise since it's likely to trigger errors further on.
+ Request::Utils.check_param_encoding(parameters)
+
set_header PARAMETERS_KEY, parameters
+ rescue Rack::Utils::ParameterTypeError, Rack::Utils::InvalidParameterError => e
+ raise ActionController::BadRequest.new("Invalid path parameters: #{e.message}")
end
# Returns a hash with the \parameters used to form the \path of the request.
@@ -58,7 +65,7 @@ module ActionDispatch
private
def parse_formatted_parameters(parsers)
- return yield if content_length.zero?
+ return yield if content_length.zero? || content_mime_type.nil?
strategy = parsers.fetch(content_mime_type.symbol) { return yield }
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb
index b0ed681623..954dd4f354 100644
--- a/actionpack/lib/action_dispatch/http/request.rb
+++ b/actionpack/lib/action_dispatch/http/request.rb
@@ -66,24 +66,12 @@ module ActionDispatch
def commit_cookie_jar! # :nodoc:
end
- def check_path_parameters!
- # If any of the path parameters has an invalid encoding then
- # raise since it's likely to trigger errors further on.
- path_parameters.each do |key, value|
- next unless value.respond_to?(:valid_encoding?)
- unless value.valid_encoding?
- raise ActionController::BadRequest, "Invalid parameter encoding: #{key} => #{value.inspect}"
- end
- end
- end
-
PASS_NOT_FOUND = Class.new { # :nodoc:
def self.action(_); self; end
def self.call(_); [404, {'X-Cascade' => 'pass'}, []]; end
}
def controller_class
- check_path_parameters!
params = path_parameters
if params.key?(:controller)
diff --git a/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb b/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
index 59edc66086..b02f10c9ec 100644
--- a/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
+++ b/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
@@ -17,8 +17,8 @@ module ActionDispatch
'ActionDispatch::ParamsParser::ParseError' => :bad_request,
'ActionController::BadRequest' => :bad_request,
'ActionController::ParameterMissing' => :bad_request,
- 'Rack::Utils::ParameterTypeError' => :bad_request,
- 'Rack::Utils::InvalidParameterError' => :bad_request
+ 'Rack::QueryParser::ParameterTypeError' => :bad_request,
+ 'Rack::QueryParser::InvalidParameterError' => :bad_request
)
cattr_accessor :rescue_templates
diff --git a/actionpack/lib/action_dispatch/middleware/static.rb b/actionpack/lib/action_dispatch/middleware/static.rb
index 2c5721dc22..4161c1d110 100644
--- a/actionpack/lib/action_dispatch/middleware/static.rb
+++ b/actionpack/lib/action_dispatch/middleware/static.rb
@@ -46,7 +46,7 @@ module ActionDispatch
end
def call(env)
- serve ActionDispatch::Request.new env
+ serve(Rack::Request.new(env))
end
def serve(request)
@@ -82,7 +82,7 @@ module ActionDispatch
end
def gzip_encoding_accepted?(request)
- request.accept_encoding =~ /\bgzip\b/i
+ request.accept_encoding.any? { |enc, quality| enc =~ /\bgzip\b/i }
end
def gzip_file_path(path)
@@ -119,7 +119,7 @@ module ActionDispatch
end
def call(env)
- req = ActionDispatch::Request.new env
+ req = Rack::Request.new env
if req.get? || req.head?
path = req.path_info.chomp('/'.freeze)
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index 73b4864e45..12ddd0f148 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -1923,7 +1923,14 @@ to this:
def match_root_route(options)
name = has_named_route?(:root) ? nil : :root
- match '/', { :as => name, :via => :get }.merge!(options)
+ defaults_option = options.delete(:defaults)
+ args = ['/', { as: name, via: :get }.merge!(options)]
+
+ if defaults_option
+ defaults(defaults_option) { match(*args) }
+ else
+ match(*args)
+ end
end
end
diff --git a/actionpack/lib/action_dispatch/routing/redirection.rb b/actionpack/lib/action_dispatch/routing/redirection.rb
index d6987f4d09..3265caa00b 100644
--- a/actionpack/lib/action_dispatch/routing/redirection.rb
+++ b/actionpack/lib/action_dispatch/routing/redirection.rb
@@ -22,7 +22,6 @@ module ActionDispatch
end
def serve(req)
- req.check_path_parameters!
uri = URI.parse(path(req.path_parameters, req))
unless uri.host
diff --git a/actionpack/lib/action_dispatch/testing/integration.rb b/actionpack/lib/action_dispatch/testing/integration.rb
index 10cd1e5787..9a76b68ae1 100644
--- a/actionpack/lib/action_dispatch/testing/integration.rb
+++ b/actionpack/lib/action_dispatch/testing/integration.rb
@@ -6,6 +6,8 @@ require 'active_support/core_ext/string/strip'
require 'rack/test'
require 'minitest'
+require 'action_dispatch/testing/request_encoder'
+
module ActionDispatch
module Integration #:nodoc:
module RequestHelpers
@@ -383,7 +385,6 @@ module ActionDispatch
response = _mock_session.last_response
@response = ActionDispatch::TestResponse.from_response(response)
@response.request = @request
- @response.response_parser = RequestEncoder.parser(@response.content_type)
@html_document = nil
@url_options = nil
@@ -402,59 +403,6 @@ module ActionDispatch
path = request_encoder.append_format_to location.path
location.query ? "#{path}?#{location.query}" : path
end
-
- class RequestEncoder # :nodoc:
- @encoders = {}
-
- attr_reader :response_parser
-
- def initialize(mime_name, param_encoder, response_parser, url_encoded_form = false)
- @mime = Mime[mime_name]
-
- unless @mime
- raise ArgumentError, "Can't register a request encoder for " \
- "unregistered MIME Type: #{mime_name}. See `Mime::Type.register`."
- end
-
- @url_encoded_form = url_encoded_form
- @path_format = ".#{@mime.symbol}" unless @url_encoded_form
- @response_parser = response_parser || -> body { body }
- @param_encoder = param_encoder || :"to_#{@mime.symbol}".to_proc
- end
-
- def append_format_to(path)
- if @url_encoded_form
- path
- else
- path + @path_format
- end
- end
-
- def content_type
- @mime.to_s
- end
-
- def encode_params(params)
- @param_encoder.call(params)
- end
-
- def self.parser(content_type)
- mime = Mime::Type.lookup(content_type)
- encoder(mime ? mime.ref : nil).response_parser
- end
-
- def self.encoder(name)
- @encoders[name] || WWWFormEncoder
- end
-
- def self.register_encoder(mime_name, param_encoder: nil, response_parser: nil)
- @encoders[mime_name] = new(mime_name, param_encoder, response_parser)
- end
-
- register_encoder :json, response_parser: -> body { JSON.parse(body) }
-
- WWWFormEncoder = new(:url_encoded_form, -> params { params }, nil, true)
- end
end
module Runner
@@ -769,7 +717,11 @@ module ActionDispatch
module ClassMethods
def app
- defined?(@@app) ? @@app : ActionDispatch.test_app
+ if defined?(@@app) && @@app
+ @@app
+ else
+ ActionDispatch.test_app
+ end
end
def app=(app)
@@ -777,7 +729,7 @@ module ActionDispatch
end
def register_encoder(*args)
- Integration::Session::RequestEncoder.register_encoder(*args)
+ RequestEncoder.register_encoder(*args)
end
end
diff --git a/actionpack/lib/action_dispatch/testing/request_encoder.rb b/actionpack/lib/action_dispatch/testing/request_encoder.rb
new file mode 100644
index 0000000000..b0b994b2d0
--- /dev/null
+++ b/actionpack/lib/action_dispatch/testing/request_encoder.rb
@@ -0,0 +1,54 @@
+module ActionDispatch
+ class RequestEncoder # :nodoc:
+ @encoders = {}
+
+ attr_reader :response_parser
+
+ def initialize(mime_name, param_encoder, response_parser, url_encoded_form = false)
+ @mime = Mime[mime_name]
+
+ unless @mime
+ raise ArgumentError, "Can't register a request encoder for " \
+ "unregistered MIME Type: #{mime_name}. See `Mime::Type.register`."
+ end
+
+ @url_encoded_form = url_encoded_form
+ @path_format = ".#{@mime.symbol}" unless @url_encoded_form
+ @response_parser = response_parser || -> body { body }
+ @param_encoder = param_encoder || :"to_#{@mime.symbol}".to_proc
+ end
+
+ def append_format_to(path)
+ if @url_encoded_form
+ path
+ else
+ path + @path_format
+ end
+ end
+
+ def content_type
+ @mime.to_s
+ end
+
+ def encode_params(params)
+ @param_encoder.call(params)
+ end
+
+ def self.parser(content_type)
+ mime = Mime::Type.lookup(content_type)
+ encoder(mime ? mime.ref : nil).response_parser
+ end
+
+ def self.encoder(name)
+ @encoders[name] || WWWFormEncoder
+ end
+
+ def self.register_encoder(mime_name, param_encoder: nil, response_parser: nil)
+ @encoders[mime_name] = new(mime_name, param_encoder, response_parser)
+ end
+
+ register_encoder :json, response_parser: -> body { JSON.parse(body) }
+
+ WWWFormEncoder = new(:url_encoded_form, -> params { params }, nil, true)
+ end
+end
diff --git a/actionpack/lib/action_dispatch/testing/test_response.rb b/actionpack/lib/action_dispatch/testing/test_response.rb
index 9d4b73a43d..bedb7a5558 100644
--- a/actionpack/lib/action_dispatch/testing/test_response.rb
+++ b/actionpack/lib/action_dispatch/testing/test_response.rb
@@ -1,3 +1,5 @@
+require 'action_dispatch/testing/request_encoder'
+
module ActionDispatch
# Integration test methods such as ActionDispatch::Integration::Session#get
# and ActionDispatch::Integration::Session#post return objects of class
@@ -10,6 +12,11 @@ module ActionDispatch
new response.status, response.headers, response.body
end
+ def initialize(*) # :nodoc:
+ super
+ @response_parser = RequestEncoder.parser(content_type)
+ end
+
# Was the response successful?
alias_method :success?, :successful?
@@ -19,8 +26,6 @@ module ActionDispatch
# Was there a server-side error?
alias_method :error?, :server_error?
- attr_writer :response_parser # :nodoc:
-
def parsed_body
@parsed_body ||= @response_parser.call(body)
end
diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb
index 1e1d6f5429..c8a45a0851 100644
--- a/actionpack/test/abstract_unit.rb
+++ b/actionpack/test/abstract_unit.rb
@@ -33,7 +33,6 @@ require 'action_view/testing/resolvers'
require 'action_dispatch'
require 'active_support/dependencies'
require 'active_model'
-require 'active_record'
require 'pp' # require 'pp' early to prevent hidden_methods from not picking up the pretty-print methods until too late
diff --git a/actionpack/test/controller/caching_test.rb b/actionpack/test/controller/caching_test.rb
index 7faf3cd8c6..9c2619dc3d 100644
--- a/actionpack/test/controller/caching_test.rb
+++ b/actionpack/test/controller/caching_test.rb
@@ -393,9 +393,14 @@ class CollectionCacheController < ActionController::Base
@customers = [Customer.new('david', 1)]
render partial: 'customers/commented_customer', collection: @customers, as: :customer, cached: true
end
+
+ def index_with_callable_cache_key
+ @customers = [Customer.new('david', 1)]
+ render partial: 'customers/customer', collection: @customers, cached: -> customer { 'cached_david' }
+ end
end
-class AutomaticCollectionCacheTest < ActionController::TestCase
+class CollectionCacheTest < ActionController::TestCase
def setup
super
@controller = CollectionCacheController.new
@@ -438,6 +443,11 @@ class AutomaticCollectionCacheTest < ActionController::TestCase
assert_equal 1, @controller.partial_rendered_times
end
+ def test_caching_with_callable_cache_key
+ get :index_with_callable_cache_key
+ assert_customer_cached 'cached_david', 'david, 1'
+ end
+
private
def assert_customer_cached(key, content)
assert_match content,
diff --git a/actionpack/test/controller/parameters/dup_test.rb b/actionpack/test/controller/parameters/dup_test.rb
new file mode 100644
index 0000000000..66bc8155c8
--- /dev/null
+++ b/actionpack/test/controller/parameters/dup_test.rb
@@ -0,0 +1,43 @@
+require 'abstract_unit'
+require 'action_controller/metal/strong_parameters'
+
+class ParametersDupTest < ActiveSupport::TestCase
+ setup do
+ ActionController::Parameters.permit_all_parameters = false
+
+ @params = ActionController::Parameters.new(
+ person: {
+ age: '32',
+ name: {
+ first: 'David',
+ last: 'Heinemeier Hansson'
+ },
+ addresses: [{city: 'Chicago', state: 'Illinois'}]
+ }
+ )
+ end
+
+ test "a duplicate maintains the original's permitted status" do
+ @params.permit!
+ dupped_params = @params.dup
+ assert dupped_params.permitted?
+ end
+
+ test "a duplicate maintains the original's parameters" do
+ @params.permit!
+ dupped_params = @params.dup
+ assert_equal @params.to_h, dupped_params.to_h
+ end
+
+ test "changes to a duplicate's parameters do not affect the original" do
+ dupped_params = @params.dup
+ dupped_params.delete(:person)
+ assert_not_equal @params, dupped_params
+ end
+
+ test "changes to a duplicate's permitted status do not affect the original" do
+ dupped_params = @params.dup
+ dupped_params.permit!
+ assert_not_equal @params, dupped_params
+ end
+end
diff --git a/actionpack/test/controller/parameters/parameters_permit_test.rb b/actionpack/test/controller/parameters/parameters_permit_test.rb
index 2eed2996f6..2dd94c7230 100644
--- a/actionpack/test/controller/parameters/parameters_permit_test.rb
+++ b/actionpack/test/controller/parameters/parameters_permit_test.rb
@@ -245,11 +245,6 @@ class ParametersPermitTest < ActiveSupport::TestCase
assert_equal "Jonas", @params[:person][:family][:brother]
end
- test "permit state is kept on a dup" do
- @params.permit!
- assert_equal @params.permitted?, @params.dup.permitted?
- end
-
test "permit is recursive" do
@params.permit!
assert @params.permitted?
diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb
index 652c06af19..e56f6e840a 100644
--- a/actionpack/test/controller/render_test.rb
+++ b/actionpack/test/controller/render_test.rb
@@ -42,6 +42,14 @@ class ImplicitRenderTestController < ActionController::Base
end
end
+module Namespaced
+ class ImplicitRenderTestController < ActionController::Base
+ def hello_world
+ fresh_when(etag: 'abc')
+ end
+ end
+end
+
class TestController < ActionController::Base
protect_from_forgery
@@ -258,6 +266,19 @@ class TestController < ActionController::Base
end
end
+module TemplateModificationHelper
+ private
+ def modify_template(name)
+ path = File.expand_path("../../fixtures/#{name}.erb", __FILE__)
+ original = File.read(path)
+ File.write(path, "#{original} Modified!")
+ ActionView::LookupContext::DetailsKey.clear
+ yield
+ ensure
+ File.write(path, original)
+ end
+end
+
class MetalTestController < ActionController::Metal
include AbstractController::Rendering
include ActionView::Rendering
@@ -487,6 +508,7 @@ end
class EtagRenderTest < ActionController::TestCase
tests TestControllerWithExtraEtags
+ include TemplateModificationHelper
def test_strong_etag
@request.if_none_match = strong_etag(['strong', 'ab', :cde, [:f]])
@@ -535,7 +557,7 @@ class EtagRenderTest < ActionController::TestCase
get :with_template
assert_response :not_modified
- modify_template(:hello_world) do
+ modify_template("test/hello_world") do
request.if_none_match = etag
get :with_template
assert_response :ok
@@ -552,7 +574,7 @@ class EtagRenderTest < ActionController::TestCase
get :with_implicit_template
assert_response :not_modified
- modify_template(:with_implicit_template) do
+ modify_template("test/with_implicit_template") do
request.if_none_match = etag
get :with_implicit_template
assert_response :ok
@@ -568,16 +590,28 @@ class EtagRenderTest < ActionController::TestCase
def strong_etag(record)
%("#{Digest::MD5.hexdigest(ActiveSupport::Cache.expand_cache_key(record))}")
end
+end
- def modify_template(name)
- path = File.expand_path("../../fixtures/test/#{name}.erb", __FILE__)
- original = File.read(path)
- File.write(path, "#{original} Modified!")
- ActionView::LookupContext::DetailsKey.clear
- yield
- ensure
- File.write(path, original)
+class NamespacedEtagRenderTest < ActionController::TestCase
+ tests Namespaced::ImplicitRenderTestController
+ include TemplateModificationHelper
+
+ def test_etag_reflects_template_digest
+ get :hello_world
+ assert_response :ok
+ assert_not_nil etag = @response.etag
+
+ request.if_none_match = etag
+ get :hello_world
+ assert_response :not_modified
+
+ modify_template("namespaced/implicit_render_test/hello_world") do
+ request.if_none_match = etag
+ get :hello_world
+ assert_response :ok
+ assert_not_equal etag, @response.etag
end
+ end
end
class MetalRenderTest < ActionController::TestCase
diff --git a/actionpack/test/controller/request_forgery_protection_test.rb b/actionpack/test/controller/request_forgery_protection_test.rb
index d3f2ec6aa1..37a54e7878 100644
--- a/actionpack/test/controller/request_forgery_protection_test.rb
+++ b/actionpack/test/controller/request_forgery_protection_test.rb
@@ -509,15 +509,6 @@ end
class RequestForgeryProtectionControllerUsingResetSessionTest < ActionController::TestCase
include RequestForgeryProtectionTests
- setup do
- @old_request_forgery_protection_token = ActionController::Base.request_forgery_protection_token
- ActionController::Base.request_forgery_protection_token = :custom_authenticity_token
- end
-
- teardown do
- ActionController::Base.request_forgery_protection_token = @old_request_forgery_protection_token
- end
-
test 'should emit a csrf-param meta tag and a csrf-token meta tag' do
@controller.stub :form_authenticity_token, @token + '<=?' do
get :meta
@@ -677,6 +668,15 @@ class CustomAuthenticityParamControllerTest < ActionController::TestCase
end
class PerFormTokensControllerTest < ActionController::TestCase
+ def setup
+ @old_request_forgery_protection_token = ActionController::Base.request_forgery_protection_token
+ ActionController::Base.request_forgery_protection_token = :custom_authenticity_token
+ end
+
+ def teardown
+ ActionController::Base.request_forgery_protection_token = @old_request_forgery_protection_token
+ end
+
def test_per_form_token_is_same_size_as_global_token
get :index
expected = ActionController::RequestForgeryProtection::AUTHENTICITY_TOKEN_LENGTH
diff --git a/actionpack/test/dispatch/exception_wrapper_test.rb b/actionpack/test/dispatch/exception_wrapper_test.rb
index dfbb91c0ca..0959cf2805 100644
--- a/actionpack/test/dispatch/exception_wrapper_test.rb
+++ b/actionpack/test/dispatch/exception_wrapper_test.rb
@@ -57,6 +57,12 @@ module ActionDispatch
assert_equal [ "lib/file.rb:42:in `index'" ], wrapper.application_trace
end
+ test '#status_code returns 400 for Rack::Utils::ParameterTypeError' do
+ exception = Rack::Utils::ParameterTypeError.new
+ wrapper = ExceptionWrapper.new(@cleaner, exception)
+ assert_equal 400, wrapper.status_code
+ end
+
test '#application_trace cannot be nil' do
nil_backtrace_wrapper = ExceptionWrapper.new(@cleaner, BadlyDefinedError.new)
nil_cleaner_wrapper = ExceptionWrapper.new(nil, BadlyDefinedError.new)
diff --git a/actionpack/test/dispatch/mime_type_test.rb b/actionpack/test/dispatch/mime_type_test.rb
index 672b272590..e1d19c3520 100644
--- a/actionpack/test/dispatch/mime_type_test.rb
+++ b/actionpack/test/dispatch/mime_type_test.rb
@@ -44,14 +44,14 @@ class MimeTypeTest < ActiveSupport::TestCase
accept = "text/*"
expect = [Mime[:html], Mime[:text], Mime[:js], Mime[:css], Mime[:ics], Mime[:csv], Mime[:vcf], Mime[:xml], Mime[:yaml], Mime[:json]]
parsed = Mime::Type.parse(accept)
- assert_equal expect, parsed
+ assert_equal expect.map(&:to_s).sort!, parsed.map(&:to_s).sort!
end
test "parse application with trailing star" do
accept = "application/*"
expect = [Mime[:html], Mime[:js], Mime[:xml], Mime[:rss], Mime[:atom], Mime[:yaml], Mime[:url_encoded_form], Mime[:json], Mime[:pdf], Mime[:zip], Mime[:gzip]]
parsed = Mime::Type.parse(accept)
- assert_equal expect, parsed
+ assert_equal expect.map(&:to_s).sort!, parsed.map(&:to_s).sort!
end
test "parse without q" do
diff --git a/actionpack/test/dispatch/request_test.rb b/actionpack/test/dispatch/request_test.rb
index 8a5d85ab84..634f6d80c4 100644
--- a/actionpack/test/dispatch/request_test.rb
+++ b/actionpack/test/dispatch/request_test.rb
@@ -1018,17 +1018,13 @@ class RequestParameters < BaseRequestTest
end
test "path parameters with invalid UTF8 encoding" do
- request = stub_request(
- "action_dispatch.request.path_parameters" => { foo: "\xBE" }
- )
+ request = stub_request
err = assert_raises(ActionController::BadRequest) do
- request.check_path_parameters!
+ request.path_parameters = { foo: "\xBE" }
end
- assert_match "Invalid parameter encoding", err.message
- assert_match "foo", err.message
- assert_match "\\xBE", err.message
+ assert_equal "Invalid path parameters: Non UTF-8 value: \xBE", err.message
end
test "parameters not accessible after rack parse error of invalid UTF8 character" do
diff --git a/actionpack/test/dispatch/response_test.rb b/actionpack/test/dispatch/response_test.rb
index aa90433505..9eed796d3c 100644
--- a/actionpack/test/dispatch/response_test.rb
+++ b/actionpack/test/dispatch/response_test.rb
@@ -145,6 +145,26 @@ class ResponseTest < ActiveSupport::TestCase
}, headers)
end
+ test "content length" do
+ [100, 101, 102, 204].each do |c|
+ @response = ActionDispatch::Response.new
+ @response.status = c.to_s
+ @response.set_header "Content-Length", "0"
+ _, headers, _ = @response.to_a
+ assert !headers.has_key?("Content-Length"), "#{c} must not have a Content-Length header field"
+ end
+ end
+
+ test "does not contain a message-body" do
+ [100, 101, 102, 204, 304].each do |c|
+ @response = ActionDispatch::Response.new
+ @response.status = c.to_s
+ @response.body = "Body must not be included"
+ _, _, body = @response.to_a
+ assert_empty body, "#{c} must not have a message-body but actually contains #{body}"
+ end
+ end
+
test "content type" do
[204, 304].each do |c|
@response = ActionDispatch::Response.new
diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb
index d54cdf7247..cac89417a5 100644
--- a/actionpack/test/dispatch/routing_test.rb
+++ b/actionpack/test/dispatch/routing_test.rb
@@ -1759,6 +1759,24 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
assert_equal 1, @request.params[:page]
end
+ def test_keyed_default_string_params_with_root
+ draw do
+ root to: 'pages#show', defaults: { id: 'home' }
+ end
+
+ get '/'
+ assert_equal 'home', @request.params[:id]
+ end
+
+ def test_default_string_params_with_root
+ draw do
+ root to: 'pages#show', id: 'home'
+ end
+
+ get '/'
+ assert_equal 'home', @request.params[:id]
+ end
+
def test_resource_constraints
draw do
resources :products, :constraints => { :id => /\d{4}/ } do
@@ -4331,15 +4349,16 @@ class TestInvalidUrls < ActionDispatch::IntegrationTest
test "invalid UTF-8 encoding returns a 400 Bad Request" do
with_routing do |set|
- ActiveSupport::Deprecation.silence do
- set.draw do
- get "/bar/:id", :to => redirect("/foo/show/%{id}")
- get "/foo/show(/:id)", :to => "test_invalid_urls/foo#show"
+ set.draw do
+ get "/bar/:id", :to => redirect("/foo/show/%{id}")
+ get "/foo/show(/:id)", :to => "test_invalid_urls/foo#show"
- ActiveSupport::Deprecation.silence do
- get "/foo(/:action(/:id))", :controller => "test_invalid_urls/foo"
- get "/:controller(/:action(/:id))"
- end
+ ok = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, []] }
+ get '/foobar/:id', to: ok
+
+ ActiveSupport::Deprecation.silence do
+ get "/foo(/:action(/:id))", :controller => "test_invalid_urls/foo"
+ get "/:controller(/:action(/:id))"
end
end
@@ -4354,6 +4373,9 @@ class TestInvalidUrls < ActionDispatch::IntegrationTest
get "/bar/%E2%EF%BF%BD%A6"
assert_response :bad_request
+
+ get "/foobar/%E2%EF%BF%BD%A6"
+ assert_response :bad_request
end
end
end
@@ -4774,7 +4796,9 @@ class TestPathParameters < ActionDispatch::IntegrationTest
end
end
- get ':controller(/:action/(:id))'
+ ActiveSupport::Deprecation.silence do
+ get ':controller(/:action/(:id))'
+ end
end
end
diff --git a/actionpack/test/dispatch/static_test.rb b/actionpack/test/dispatch/static_test.rb
index ea8b5e904e..1036758f35 100644
--- a/actionpack/test/dispatch/static_test.rb
+++ b/actionpack/test/dispatch/static_test.rb
@@ -160,6 +160,9 @@ module StaticTests
response = get(file_name, 'HTTP_ACCEPT_ENCODING' => 'GZIP')
assert_gzip file_name, response
+ response = get(file_name, 'HTTP_ACCEPT_ENCODING' => 'compress;q=0.5, gzip;q=1.0')
+ assert_gzip file_name, response
+
response = get(file_name, 'HTTP_ACCEPT_ENCODING' => '')
assert_not_equal 'gzip', response.headers["Content-Encoding"]
end
@@ -205,6 +208,12 @@ module StaticTests
assert_equal "I'm a teapot", response.headers["X-Custom-Header"]
end
+ def test_ignores_unknown_http_methods
+ app = ActionDispatch::Static.new(DummyApp, @root)
+
+ assert_nothing_raised { Rack::MockRequest.new(app).request("BAD_METHOD", "/foo/bar.html") }
+ end
+
# Windows doesn't allow \ / : * ? " < > | in filenames
unless RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
def test_serves_static_file_with_colon
diff --git a/actionpack/test/dispatch/test_response_test.rb b/actionpack/test/dispatch/test_response_test.rb
index a4f9d56a6a..72e06b4590 100644
--- a/actionpack/test/dispatch/test_response_test.rb
+++ b/actionpack/test/dispatch/test_response_test.rb
@@ -17,4 +17,12 @@ class TestResponseTest < ActiveSupport::TestCase
assert_response_code_range 500..599, :server_error?
assert_response_code_range 400..499, :client_error?
end
+
+ test "response parsing" do
+ response = ActionDispatch::TestResponse.create(200, {}, '')
+ assert_equal response.body, response.parsed_body
+
+ response = ActionDispatch::TestResponse.create(200, { 'Content-Type' => 'application/json' }, '{ "foo": "fighters" }')
+ assert_equal({ 'foo' => 'fighters' }, response.parsed_body)
+ end
end
diff --git a/actionpack/test/fixtures/namespaced/implicit_render_test/hello_world.erb b/actionpack/test/fixtures/namespaced/implicit_render_test/hello_world.erb
new file mode 100644
index 0000000000..cd0875583a
--- /dev/null
+++ b/actionpack/test/fixtures/namespaced/implicit_render_test/hello_world.erb
@@ -0,0 +1 @@
+Hello world!