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/basic_implicit_render.rb2
-rw-r--r--actionpack/lib/action_controller/metal/implicit_render.rb91
-rw-r--r--actionpack/lib/action_controller/test_case.rb2
-rw-r--r--actionpack/lib/action_dispatch/journey/route.rb2
-rw-r--r--actionpack/lib/action_dispatch/middleware/ssl.rb15
-rw-r--r--actionpack/lib/action_dispatch/request/session.rb26
-rw-r--r--actionpack/lib/action_dispatch/routing/inspector.rb2
-rw-r--r--actionpack/test/controller/mime/respond_to_test.rb93
-rw-r--r--actionpack/test/controller/render_test.rb25
-rw-r--r--actionpack/test/dispatch/request/session_test.rb10
-rw-r--r--actionpack/test/dispatch/response_test.rb8
-rw-r--r--actionpack/test/dispatch/session/abstract_store_test.rb16
-rw-r--r--actionpack/test/dispatch/session/cache_store_test.rb29
-rw-r--r--actionpack/test/dispatch/session/cookie_store_test.rb34
-rw-r--r--actionpack/test/dispatch/session/mem_cache_store_test.rb31
-rw-r--r--actionpack/test/dispatch/session/test_session_test.rb7
-rw-r--r--actionpack/test/dispatch/ssl_test.rb23
-rw-r--r--actionpack/test/fixtures/implicit_render_test/empty_action_with_mobile_variant.html+mobile.erb1
-rw-r--r--actionpack/test/fixtures/implicit_render_test/empty_action_with_template.html.erb1
-rw-r--r--actionpack/test/fixtures/respond_to/variant_with_implicit_template_rendering.html+mobile.erb (renamed from actionpack/test/fixtures/respond_to/variant_with_implicit_rendering.html+mobile.erb)0
21 files changed, 242 insertions, 208 deletions
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index da96aef98b..6b73b29ace 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -1,13 +1,33 @@
-## Rails 5.0.0.beta3 (February 24, 2016) ##
+* Update default rendering policies when the controller action did
+ not explicitly indicate a response.
+
+ For API controllers, the implicit render always renders "204 No Content"
+ and does not account for any templates.
+
+ For other controllers, the following conditions are checked:
-* Update session to have indifferent access across multiple requests.
+ First, if a template exists for the controller action, it is rendered.
+ This template lookup takes into account the action name, locales, format,
+ variant, template handlers, etc. (see +render+ for details).
- session[:deep][:hash] = "Magic"
+ Second, if other templates exist for the controller action but is not in
+ the right format (or variant, etc.), an <tt>ActionController::UnknownFormat</tt>
+ is raised. The list of available templates is assumed to be a complete
+ enumeration of all the possible formats (or variants, etc.); that is,
+ having only HTML and JSON templates indicate that the controller action is
+ not meant to handle XML requests.
- session[:deep][:hash] == "Magic"
- session[:deep]["hash"] == "Magic"
+ Third, if the current request is an "interactive" browser request (the user
+ navigated here by entering the URL in the address bar, submiting a form,
+ clicking on a link, etc. as opposed to an XHR or non-browser API request),
+ <tt>ActionView::UnknownFormat</tt> is raised to display a helpful error
+ message.
- *Tom Prats*
+ Finally, it falls back to the same "204 No Content" behavior as API controllers.
+
+ *Godfrey Chan*, *Jon Moss*, *Kasper Timm Hansen*, *Mike Clark*, *Matthew Draper*
+
+## Rails 5.0.0.beta3 (February 24, 2016) ##
* Add application/gzip as a default mime type.
diff --git a/actionpack/lib/action_controller/metal/basic_implicit_render.rb b/actionpack/lib/action_controller/metal/basic_implicit_render.rb
index 6c6f8381ff..cef65a362c 100644
--- a/actionpack/lib/action_controller/metal/basic_implicit_render.rb
+++ b/actionpack/lib/action_controller/metal/basic_implicit_render.rb
@@ -1,5 +1,5 @@
module ActionController
- module BasicImplicitRender
+ module BasicImplicitRender # :nodoc:
def send_action(method, *args)
super.tap { default_render unless performed? }
end
diff --git a/actionpack/lib/action_controller/metal/implicit_render.rb b/actionpack/lib/action_controller/metal/implicit_render.rb
index 17fcc2fa02..6b540d42c7 100644
--- a/actionpack/lib/action_controller/metal/implicit_render.rb
+++ b/actionpack/lib/action_controller/metal/implicit_render.rb
@@ -1,29 +1,80 @@
+require 'active_support/core_ext/string/strip'
+
module ActionController
+ # Handles implicit rendering for a controller action when it did not
+ # explicitly indicate an appropiate response via methods such as +render+,
+ # +respond_to+, +redirect+ or +head+.
+ #
+ # For API controllers, the implicit render always renders "204 No Content"
+ # and does not account for any templates.
+ #
+ # For other controllers, the following conditions are checked:
+ #
+ # First, if a template exists for the controller action, it is rendered.
+ # This template lookup takes into account the action name, locales, format,
+ # variant, template handlers, etc. (see +render+ for details).
+ #
+ # Second, if other templates exist for the controller action but is not in
+ # the right format (or variant, etc.), an <tt>ActionController::UnknownFormat</tt>
+ # is raised. The list of available templates is assumed to be a complete
+ # enumeration of all the possible formats (or variants, etc.); that is,
+ # having only HTML and JSON templates indicate that the controller action is
+ # not meant to handle XML requests.
+ #
+ # Third, if the current request is an "interactive" browser request (the user
+ # navigated here by entering the URL in the address bar, submiting a form,
+ # clicking on a link, etc. as opposed to an XHR or non-browser API request),
+ # <tt>ActionView::UnknownFormat</tt> is raised to display a helpful error
+ # message.
+ #
+ # Finally, it falls back to the same "204 No Content" behavior as API controllers.
module ImplicitRender
+ # :stopdoc:
include BasicImplicitRender
- # Renders the template corresponding to the controller action, if it exists.
- # The action name, format, and variant are all taken into account.
- # For example, the "new" action with an HTML format and variant "phone"
- # would try to render the <tt>new.html+phone.erb</tt> template.
- #
- # If no template is found <tt>ActionController::BasicImplicitRender</tt>'s implementation is called, unless
- # a block is passed. In that case, it will override the super implementation.
- #
- # default_render do
- # head 404 # No template was found
- # end
def default_render(*args)
if template_exists?(action_name.to_s, _prefixes, variants: request.variant)
render(*args)
- else
- if block_given?
- yield(*args)
- else
- logger.info "No template found for #{self.class.name}\##{action_name}, rendering head :no_content" if logger
- super
+ elsif any_templates?(action_name.to_s, _prefixes)
+ message = "#{self.class.name}\##{action_name} does not know how to respond " \
+ "to this request. There are other templates available for this controller " \
+ "action but none of them were suitable for this request.\n\n" \
+ "This usually happens when the client requested an unsupported format " \
+ "(e.g. requesting HTML content from a JSON endpoint or vice versa), but " \
+ "it might also be failing due to other constraints, such as locales or" \
+ "variants.\n"
+
+ if request.formats.any?
+ message << "\nRequested format(s): #{request.formats.join(", ")}"
end
+
+ if request.variant.any?
+ message << "\nRequested variant(s): #{request.variant.join(", ")}"
+ end
+
+ raise ActionController::UnknownFormat, message
+ elsif interactive_browser_request?
+ message = "You did not define any templates for #{self.class.name}\##{action_name}. " \
+ "This is not necessarily a problem (e.g. you might be building an API endpoint " \
+ "that does not require any templates), and the controller would usually respond " \
+ "with `head :no_content` for your convenience.\n\n" \
+ "However, you appear to have navigated here from an interactive browser request – " \
+ "such as by navigating to this URL directly, clicking on a link or submitting a form. " \
+ "Rendering a `head :no_content` in this case could have resulted in unexpected UI " \
+ "behavior in the browser.\n\n" \
+ "If you expected the `head :no_content` response, you do not need to take any " \
+ "actions – requests coming from an XHR (AJAX) request or other non-browser clients " \
+ "will receive the \"204 No Content\" response as expected.\n\n" \
+ "If you did not expect this behavior, you can resolve this error by adding a " \
+ "template for this controller action (usually `#{action_name}.html.erb`) or " \
+ "otherwise indicate the appropriate response in the action using `render`, " \
+ "`redirect_to`, `head`, etc.\n"
+
+ raise ActionController::UnknownFormat, message
+ else
+ logger.info "No template found for #{self.class.name}\##{action_name}, rendering head :no_content" if logger
+ super
end
end
@@ -32,5 +83,11 @@ module ActionController
"default_render"
end
end
+
+ private
+
+ def interactive_browser_request?
+ request.format == Mime[:html] && !request.xhr?
+ end
end
end
diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb
index 6548ce326b..700317614f 100644
--- a/actionpack/lib/action_controller/test_case.rb
+++ b/actionpack/lib/action_controller/test_case.rb
@@ -176,7 +176,7 @@ module ActionController
def initialize(session = {})
super(nil, nil)
@id = SecureRandom.hex(16)
- @data = session.with_indifferent_access
+ @data = stringify_keys(session)
@loaded = true
end
diff --git a/actionpack/lib/action_dispatch/journey/route.rb b/actionpack/lib/action_dispatch/journey/route.rb
index fee08fc3db..cfd6681dd1 100644
--- a/actionpack/lib/action_dispatch/journey/route.rb
+++ b/actionpack/lib/action_dispatch/journey/route.rb
@@ -82,7 +82,7 @@ module ActionDispatch
end
def requirements # :nodoc:
- # needed for rails `rake routes`
+ # needed for rails `rails routes`
@defaults.merge(path.requirements).delete_if { |_,v|
/.+?/ == v
}
diff --git a/actionpack/lib/action_dispatch/middleware/ssl.rb b/actionpack/lib/action_dispatch/middleware/ssl.rb
index 735b5939dd..711d8b016a 100644
--- a/actionpack/lib/action_dispatch/middleware/ssl.rb
+++ b/actionpack/lib/action_dispatch/middleware/ssl.rb
@@ -23,7 +23,7 @@ module ActionDispatch
# preload lists is `18.weeks`.
# * `subdomains`: Set to `true` to tell the browser to apply these settings
# to all subdomains. This protects your cookies from interception by a
- # vulnerable site on a subdomain. Defaults to `false`.
+ # vulnerable site on a subdomain. Defaults to `true`.
# * `preload`: Advertise that this site may be included in browsers'
# preloaded HSTS lists. HSTS protects your site on every visit *except the
# first visit* since it hasn't seen your HSTS header yet. To close this
@@ -49,7 +49,7 @@ module ActionDispatch
if options[:host] || options[:port]
ActiveSupport::Deprecation.warn <<-end_warning.strip_heredoc
The `:host` and `:port` options are moving within `:redirect`:
- `config.ssl_options = { redirect: { host: …, port: … }}`.
+ `config.ssl_options = { redirect: { host: …, port: … } }`.
end_warning
@redirect = options.slice(:host, :port)
else
@@ -57,6 +57,17 @@ module ActionDispatch
end
@secure_cookies = secure_cookies
+
+ if hsts != true && hsts != false && hsts[:subdomains].nil?
+ hsts[:subdomains] = false
+
+ ActiveSupport::Deprecation.warn <<-end_warning.strip_heredoc
+ In Rails 5.1, The `:subdomains` option of HSTS config will be treated as true if
+ unspecified. Set `config.ssl_options = { hsts: { subdomains: false } }` to opt out
+ of this behavior.
+ end_warning
+ end
+
@hsts_header = build_hsts_header(normalize_hsts_options(hsts))
end
diff --git a/actionpack/lib/action_dispatch/request/session.rb b/actionpack/lib/action_dispatch/request/session.rb
index 38d0da3e67..42890225fa 100644
--- a/actionpack/lib/action_dispatch/request/session.rb
+++ b/actionpack/lib/action_dispatch/request/session.rb
@@ -9,7 +9,7 @@ module ActionDispatch
# Singleton object used to determine if an optional param wasn't specified
Unspecified = Object.new
-
+
# Creates a session hash, merging the properties of the previous session if any
def self.create(store, req, default_options)
session_was = find req
@@ -61,7 +61,7 @@ module ActionDispatch
def initialize(by, req)
@by = by
@req = req
- @delegate = {}.with_indifferent_access
+ @delegate = {}
@loaded = false
@exists = nil # we haven't checked yet
end
@@ -88,13 +88,13 @@ module ActionDispatch
# nil if the given key is not found in the session.
def [](key)
load_for_read!
- @delegate[key]
+ @delegate[key.to_s]
end
# Returns true if the session has the given key or false.
def has_key?(key)
load_for_read!
- @delegate.key?(key)
+ @delegate.key?(key.to_s)
end
alias :key? :has_key?
alias :include? :has_key?
@@ -112,7 +112,7 @@ module ActionDispatch
# Writes given value to given key of the session.
def []=(key, value)
load_for_write!
- @delegate[key] = value
+ @delegate[key.to_s] = value
end
# Clears the session.
@@ -139,13 +139,13 @@ module ActionDispatch
# # => {"session_id"=>"e29b9ea315edf98aad94cc78c34cc9b2", "foo" => "bar"}
def update(hash)
load_for_write!
- @delegate.update hash
+ @delegate.update stringify_keys(hash)
end
# Deletes given key from the session.
def delete(key)
load_for_write!
- @delegate.delete key
+ @delegate.delete key.to_s
end
# Returns value of the given key from the session, or raises +KeyError+
@@ -165,9 +165,9 @@ module ActionDispatch
def fetch(key, default=Unspecified, &block)
load_for_read!
if default == Unspecified
- @delegate.fetch(key, &block)
+ @delegate.fetch(key.to_s, &block)
else
- @delegate.fetch(key, default, &block)
+ @delegate.fetch(key.to_s, default, &block)
end
end
@@ -211,9 +211,15 @@ module ActionDispatch
def load!
id, session = @by.load_session @req
options[:id] = id
- @delegate.replace(session)
+ @delegate.replace(stringify_keys(session))
@loaded = true
end
+
+ def stringify_keys(other)
+ other.each_with_object({}) { |(key, value), hash|
+ hash[key.to_s] = value
+ }
+ end
end
end
end
diff --git a/actionpack/lib/action_dispatch/routing/inspector.rb b/actionpack/lib/action_dispatch/routing/inspector.rb
index 6f651a5689..5d30a545a2 100644
--- a/actionpack/lib/action_dispatch/routing/inspector.rb
+++ b/actionpack/lib/action_dispatch/routing/inspector.rb
@@ -51,7 +51,7 @@ module ActionDispatch
##
# This class is just used for displaying route information when someone
- # executes `rake routes` or looks at the RoutingError page.
+ # executes `rails routes` or looks at the RoutingError page.
# People should not use this class.
class RoutesInspector # :nodoc:
def initialize(routes)
diff --git a/actionpack/test/controller/mime/respond_to_test.rb b/actionpack/test/controller/mime/respond_to_test.rb
index 76e2d3ff43..d0c7b2e06a 100644
--- a/actionpack/test/controller/mime/respond_to_test.rb
+++ b/actionpack/test/controller/mime/respond_to_test.rb
@@ -160,7 +160,14 @@ class RespondToController < ActionController::Base
end
end
- def variant_with_implicit_rendering
+ def variant_with_implicit_template_rendering
+ # This has exactly one variant template defined in the file system (+mobile.html.erb),
+ # which raises the regular MissingTemplate error for other variants.
+ end
+
+ def variant_without_implicit_template_rendering
+ # This differs from the above in that it does not have any templates defined in the file
+ # system, which triggers the ImplicitRender (204 No Content) behavior.
end
def variant_with_format_and_custom_render
@@ -272,6 +279,8 @@ class RespondToController < ActionController::Base
end
class RespondToControllerTest < ActionController::TestCase
+ NO_CONTENT_WARNING = "No template found for RespondToController#variant_without_implicit_template_rendering, rendering head :no_content"
+
def setup
super
@request.host = "www.example.com"
@@ -616,30 +625,69 @@ class RespondToControllerTest < ActionController::TestCase
end
def test_invalid_variant
+ assert_raises(ActionController::UnknownFormat) do
+ get :variant_with_implicit_template_rendering, params: { v: :invalid }
+ end
+ end
+
+ def test_variant_not_set_regular_unknown_format
+ assert_raises(ActionController::UnknownFormat) do
+ get :variant_with_implicit_template_rendering
+ end
+ end
+
+ def test_variant_with_implicit_template_rendering
+ get :variant_with_implicit_template_rendering, params: { v: :mobile }
+ assert_equal "text/html", @response.content_type
+ assert_equal "mobile", @response.body
+ end
+
+ def test_variant_without_implicit_rendering_from_browser
+ assert_raises(ActionController::UnknownFormat) do
+ get :variant_without_implicit_template_rendering, params: { v: :does_not_matter }
+ end
+ end
+
+ def test_variant_variant_not_set_and_without_implicit_rendering_from_browser
+ assert_raises(ActionController::UnknownFormat) do
+ get :variant_without_implicit_template_rendering
+ end
+ end
+
+ def test_variant_without_implicit_rendering_from_xhr
logger = ActiveSupport::LogSubscriber::TestHelper::MockLogger.new
old_logger, ActionController::Base.logger = ActionController::Base.logger, logger
- get :variant_with_implicit_rendering, params: { v: :invalid }
+ get :variant_without_implicit_template_rendering, xhr: true, params: { v: :does_not_matter }
assert_response :no_content
- assert_equal 1, logger.logged(:info).select{ |s| s =~ /No template found/ }.size, "Implicit head :no_content not logged"
+
+ assert_equal 1, logger.logged(:info).select{ |s| s == NO_CONTENT_WARNING }.size, "Implicit head :no_content not logged"
ensure
ActionController::Base.logger = old_logger
end
- def test_variant_not_set_regular_template_missing
- get :variant_with_implicit_rendering
+ def test_variant_without_implicit_rendering_from_api
+ logger = ActiveSupport::LogSubscriber::TestHelper::MockLogger.new
+ old_logger, ActionController::Base.logger = ActionController::Base.logger, logger
+
+ get :variant_without_implicit_template_rendering, format: 'json', params: { v: :does_not_matter }
assert_response :no_content
+
+ assert_equal 1, logger.logged(:info).select{ |s| s == NO_CONTENT_WARNING }.size, "Implicit head :no_content not logged"
+ ensure
+ ActionController::Base.logger = old_logger
end
- def test_variant_with_implicit_rendering
- get :variant_with_implicit_rendering, params: { v: :implicit }
+ def test_variant_variant_not_set_and_without_implicit_rendering_from_xhr
+ logger = ActiveSupport::LogSubscriber::TestHelper::MockLogger.new
+ old_logger, ActionController::Base.logger = ActionController::Base.logger, logger
+
+ get :variant_without_implicit_template_rendering, xhr: true
assert_response :no_content
- end
- def test_variant_with_implicit_template_rendering
- get :variant_with_implicit_rendering, params: { v: :mobile }
- assert_equal "text/html", @response.content_type
- assert_equal "mobile", @response.body
+ assert_equal 1, logger.logged(:info).select { |s| s == NO_CONTENT_WARNING }.size, "Implicit head :no_content not logged"
+ ensure
+ ActionController::Base.logger = old_logger
end
def test_variant_with_format_and_custom_render
@@ -778,24 +826,3 @@ class RespondToControllerTest < ActionController::TestCase
assert_equal "phone", @response.body
end
end
-
-class RespondToWithBlockOnDefaultRenderController < ActionController::Base
- def show
- default_render do
- render body: 'default_render yielded'
- end
- end
-end
-
-class RespondToWithBlockOnDefaultRenderControllerTest < ActionController::TestCase
- def setup
- super
- @request.host = "www.example.com"
- end
-
- def test_default_render_uses_block_when_no_template_exists
- get :show
- assert_equal "default_render yielded", @response.body
- assert_equal "text/plain", @response.content_type
- end
-end
diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb
index 60c6518c62..83d7405e4d 100644
--- a/actionpack/test/controller/render_test.rb
+++ b/actionpack/test/controller/render_test.rb
@@ -26,6 +26,9 @@ end
class ImplicitRenderTestController < ActionController::Base
def empty_action
end
+
+ def empty_action_with_template
+ end
end
class TestController < ActionController::Base
@@ -537,10 +540,28 @@ end
class ImplicitRenderTest < ActionController::TestCase
tests ImplicitRenderTestController
- def test_implicit_no_content_response
- get :empty_action
+ def test_implicit_no_content_response_as_browser
+ assert_raises(ActionController::UnknownFormat) do
+ get :empty_action
+ end
+ end
+
+ def test_implicit_no_content_response_as_xhr
+ get :empty_action, xhr: true
assert_response :no_content
end
+
+ def test_implicit_success_response_with_right_format
+ get :empty_action_with_template
+ assert_equal "<h1>Empty action rendered this implicitly.</h1>\n", @response.body
+ assert_response :success
+ end
+
+ def test_implicit_unknown_format_response
+ assert_raises(ActionController::UnknownFormat) do
+ get :empty_action_with_template, format: 'json'
+ end
+ end
end
class HeadRenderTest < ActionController::TestCase
diff --git a/actionpack/test/dispatch/request/session_test.rb b/actionpack/test/dispatch/request/session_test.rb
index 3433d82791..7dcbcc5c21 100644
--- a/actionpack/test/dispatch/request/session_test.rb
+++ b/actionpack/test/dispatch/request/session_test.rb
@@ -105,16 +105,6 @@ module ActionDispatch
end
end
- def test_indifferent_access
- s = Session.create(store, req, {})
-
- s[:one] = { test: "deep" }
- s[:two] = { "test" => "deep" }
-
- assert_equal 'deep', s[:one]["test"]
- assert_equal 'deep', s[:two][:test]
- end
-
private
def store
Class.new {
diff --git a/actionpack/test/dispatch/response_test.rb b/actionpack/test/dispatch/response_test.rb
index 8b3849cb7a..cd385982d9 100644
--- a/actionpack/test/dispatch/response_test.rb
+++ b/actionpack/test/dispatch/response_test.rb
@@ -445,4 +445,12 @@ class ResponseIntegrationTest < ActionDispatch::IntegrationTest
assert_equal('application/xml; charset=utf-16', @response.headers['Content-Type'])
end
+
+ test "we can set strong ETag by directly adding it as header" do
+ @response = ActionDispatch::Response.create
+ @response.add_header "ETag", '"202cb962ac59075b964b07152d234b70"'
+
+ assert_equal('"202cb962ac59075b964b07152d234b70"', @response.etag)
+ assert_equal('"202cb962ac59075b964b07152d234b70"', @response.headers['ETag'])
+ end
end
diff --git a/actionpack/test/dispatch/session/abstract_store_test.rb b/actionpack/test/dispatch/session/abstract_store_test.rb
index c9ce5cad42..d38d1bbce6 100644
--- a/actionpack/test/dispatch/session/abstract_store_test.rb
+++ b/actionpack/test/dispatch/session/abstract_store_test.rb
@@ -46,22 +46,6 @@ module ActionDispatch
assert_equal session.to_hash, session1.to_hash
end
- def test_previous_session_has_indifferent_access
- env = {}
- as = MemoryStore.new app
- as.call(env)
-
- assert @env
- session = Request::Session.find ActionDispatch::Request.new @env
- session[:foo] = { bar: "baz" }
-
- as.call(@env)
- session = Request::Session.find ActionDispatch::Request.new @env
-
- assert_equal session[:foo][:bar], "baz"
- assert_equal session[:foo]["bar"], "baz"
- end
-
private
def app(&block)
@env = nil
diff --git a/actionpack/test/dispatch/session/cache_store_test.rb b/actionpack/test/dispatch/session/cache_store_test.rb
index b911392cf1..dbb996973d 100644
--- a/actionpack/test/dispatch/session/cache_store_test.rb
+++ b/actionpack/test/dispatch/session/cache_store_test.rb
@@ -12,11 +12,6 @@ class CacheStoreTest < ActionDispatch::IntegrationTest
head :ok
end
- def set_deep_session_value
- session[:foo] = { bar: "baz" }
- head :ok
- end
-
def set_serialized_session_value
session[:foo] = SessionAutoloadTest::Foo.new
head :ok
@@ -26,14 +21,6 @@ class CacheStoreTest < ActionDispatch::IntegrationTest
render plain: "foo: #{session[:foo].inspect}"
end
- def get_deep_session_value_with_symbol
- render plain: "foo: { bar: #{session[:foo][:bar].inspect} }"
- end
-
- def get_deep_session_value_with_string
- render plain: "foo: { \"bar\" => #{session[:foo]["bar"].inspect} }"
- end
-
def get_session_id
render plain: "#{request.session.id}"
end
@@ -173,22 +160,6 @@ class CacheStoreTest < ActionDispatch::IntegrationTest
end
end
- def test_previous_session_has_indifferent_access
- with_test_route_set do
- get '/set_deep_session_value'
- assert_response :success
- assert cookies['_session_id']
-
- get '/get_deep_session_value_with_symbol'
- assert_response :success
- assert_equal 'foo: { bar: "baz" }', response.body
-
- get '/get_deep_session_value_with_string'
- assert_response :success
- assert_equal 'foo: { "bar" => "baz" }', response.body
- end
- end
-
private
def with_test_route_set
with_routing do |set|
diff --git a/actionpack/test/dispatch/session/cookie_store_test.rb b/actionpack/test/dispatch/session/cookie_store_test.rb
index 71402b021a..f07e215e3a 100644
--- a/actionpack/test/dispatch/session/cookie_store_test.rb
+++ b/actionpack/test/dispatch/session/cookie_store_test.rb
@@ -24,23 +24,10 @@ class CookieStoreTest < ActionDispatch::IntegrationTest
render plain: Rack::Utils.escape(Verifier.generate(session.to_hash))
end
- def set_deep_session_value
- session[:foo] = { bar: "baz" }
- render plain: Rack::Utils.escape(Verifier.generate(session.to_hash))
- end
-
def get_session_value
render plain: "foo: #{session[:foo].inspect}"
end
- def get_deep_session_value_with_symbol
- render plain: "foo: { bar: #{session[:foo][:bar].inspect} }"
- end
-
- def get_deep_session_value_with_string
- render plain: "foo: { \"bar\" => #{session[:foo]["bar"].inspect} }"
- end
-
def get_session_id
render plain: "id: #{request.session.id}"
end
@@ -94,15 +81,6 @@ class CookieStoreTest < ActionDispatch::IntegrationTest
end
end
- def test_session_indifferent_access
- with_test_route_set do
- cookies[SessionKey] = SignedBar
- get '/get_session_value'
- assert_response :success
- assert_equal 'foo: "bar"', response.body
- end
- end
-
def test_getting_session_id
with_test_route_set do
cookies[SessionKey] = SignedBar
@@ -354,18 +332,6 @@ class CookieStoreTest < ActionDispatch::IntegrationTest
end
end
- def test_previous_session_has_indifferent_access
- with_test_route_set do
- get '/set_deep_session_value'
-
- get '/get_deep_session_value_with_symbol'
- assert_equal 'foo: { bar: "baz" }', response.body
-
- get '/get_deep_session_value_with_string'
- assert_equal 'foo: { "bar" => "baz" }', response.body
- end
- end
-
private
# Overwrite get to send SessionSecret in env hash
diff --git a/actionpack/test/dispatch/session/mem_cache_store_test.rb b/actionpack/test/dispatch/session/mem_cache_store_test.rb
index 2e6b42856f..3fed9bad4f 100644
--- a/actionpack/test/dispatch/session/mem_cache_store_test.rb
+++ b/actionpack/test/dispatch/session/mem_cache_store_test.rb
@@ -13,11 +13,6 @@ class MemCacheStoreTest < ActionDispatch::IntegrationTest
head :ok
end
- def set_deep_session_value
- session[:foo] = { bar: "baz" }
- head :ok
- end
-
def set_serialized_session_value
session[:foo] = SessionAutoloadTest::Foo.new
head :ok
@@ -27,14 +22,6 @@ class MemCacheStoreTest < ActionDispatch::IntegrationTest
render plain: "foo: #{session[:foo].inspect}"
end
- def get_deep_session_value_with_symbol
- render plain: "foo: { bar: #{session[:foo][:bar].inspect} }"
- end
-
- def get_deep_session_value_with_string
- render plain: "foo: { \"bar\" => #{session[:foo]["bar"].inspect} }"
- end
-
def get_session_id
render plain: "#{request.session.id}"
end
@@ -192,24 +179,6 @@ class MemCacheStoreTest < ActionDispatch::IntegrationTest
rescue Dalli::RingError => ex
skip ex.message, ex.backtrace
end
-
- def test_previous_session_has_indifferent_access
- with_test_route_set do
- get '/set_deep_session_value'
- assert_response :success
- assert cookies['_session_id']
-
- get '/get_deep_session_value_with_symbol'
- assert_response :success
- assert_equal 'foo: { bar: "baz" }', response.body
-
- get '/get_deep_session_value_with_string'
- assert_response :success
- assert_equal 'foo: { "bar" => "baz" }', response.body
- end
- rescue Dalli::RingError => ex
- skip ex.message, ex.backtrace
- end
rescue LoadError, RuntimeError, Dalli::DalliError
$stderr.puts "Skipping MemCacheStoreTest tests. Start memcached and try again."
end
diff --git a/actionpack/test/dispatch/session/test_session_test.rb b/actionpack/test/dispatch/session/test_session_test.rb
index 332c2ae3c8..3e61d123e3 100644
--- a/actionpack/test/dispatch/session/test_session_test.rb
+++ b/actionpack/test/dispatch/session/test_session_test.rb
@@ -60,11 +60,4 @@ class ActionController::TestSessionTest < ActiveSupport::TestCase
session = ActionController::TestSession.new(one: '1')
assert_equal(2, session.fetch('2') { |key| key.to_i })
end
-
- def test_fetch_returns_indifferent_access
- session = ActionController::TestSession.new(three: { two: '1' })
- three = session.fetch(:three)
- assert_equal('1', three[:two])
- assert_equal('1', three["two"])
- end
end
diff --git a/actionpack/test/dispatch/ssl_test.rb b/actionpack/test/dispatch/ssl_test.rb
index c66a0e6a7a..18ff894b31 100644
--- a/actionpack/test/dispatch/ssl_test.rb
+++ b/actionpack/test/dispatch/ssl_test.rb
@@ -7,7 +7,7 @@ class SSLTest < ActionDispatch::IntegrationTest
def build_app(headers: {}, ssl_options: {})
headers = HEADERS.merge(headers)
- ActionDispatch::SSL.new lambda { |env| [200, headers, []] }, ssl_options
+ ActionDispatch::SSL.new lambda { |env| [200, headers, []] }, ssl_options.reverse_merge(hsts: { subdomains: true })
end
end
@@ -98,15 +98,16 @@ end
class StrictTransportSecurityTest < SSLTest
EXPECTED = 'max-age=15552000'
+ EXPECTED_WITH_SUBDOMAINS = 'max-age=15552000; includeSubDomains'
- def assert_hsts(expected, url: 'https://example.org', hsts: {}, headers: {})
+ def assert_hsts(expected, url: 'https://example.org', hsts: { subdomains: true }, headers: {})
self.app = build_app ssl_options: { hsts: hsts }, headers: headers
get url
assert_equal expected, response.headers['Strict-Transport-Security']
end
test 'enabled by default' do
- assert_hsts EXPECTED
+ assert_hsts EXPECTED_WITH_SUBDOMAINS
end
test 'not sent with http:// responses' do
@@ -126,11 +127,15 @@ class StrictTransportSecurityTest < SSLTest
end
test ':expires sets max-age' do
- assert_hsts 'max-age=500', hsts: { expires: 500 }
+ assert_deprecated do
+ assert_hsts 'max-age=500', hsts: { expires: 500 }
+ end
end
test ':expires supports AS::Duration arguments' do
- assert_hsts 'max-age=31557600', hsts: { expires: 1.year }
+ assert_deprecated do
+ assert_hsts 'max-age=31557600', hsts: { expires: 1.year }
+ end
end
test 'include subdomains' do
@@ -142,11 +147,15 @@ class StrictTransportSecurityTest < SSLTest
end
test 'opt in to browser preload lists' do
- assert_hsts "#{EXPECTED}; preload", hsts: { preload: true }
+ assert_deprecated do
+ assert_hsts "#{EXPECTED}; preload", hsts: { preload: true }
+ end
end
test 'opt out of browser preload lists' do
- assert_hsts EXPECTED, hsts: { preload: false }
+ assert_deprecated do
+ assert_hsts EXPECTED, hsts: { preload: false }
+ end
end
end
diff --git a/actionpack/test/fixtures/implicit_render_test/empty_action_with_mobile_variant.html+mobile.erb b/actionpack/test/fixtures/implicit_render_test/empty_action_with_mobile_variant.html+mobile.erb
new file mode 100644
index 0000000000..ded99ba52d
--- /dev/null
+++ b/actionpack/test/fixtures/implicit_render_test/empty_action_with_mobile_variant.html+mobile.erb
@@ -0,0 +1 @@
+mobile
diff --git a/actionpack/test/fixtures/implicit_render_test/empty_action_with_template.html.erb b/actionpack/test/fixtures/implicit_render_test/empty_action_with_template.html.erb
new file mode 100644
index 0000000000..dd294f8cf6
--- /dev/null
+++ b/actionpack/test/fixtures/implicit_render_test/empty_action_with_template.html.erb
@@ -0,0 +1 @@
+<h1>Empty action rendered this implicitly.</h1>
diff --git a/actionpack/test/fixtures/respond_to/variant_with_implicit_rendering.html+mobile.erb b/actionpack/test/fixtures/respond_to/variant_with_implicit_template_rendering.html+mobile.erb
index 317801ad30..317801ad30 100644
--- a/actionpack/test/fixtures/respond_to/variant_with_implicit_rendering.html+mobile.erb
+++ b/actionpack/test/fixtures/respond_to/variant_with_implicit_template_rendering.html+mobile.erb