diff options
Diffstat (limited to 'actionpack')
-rw-r--r-- | actionpack/CHANGELOG.md | 19 | ||||
-rw-r--r-- | actionpack/lib/action_controller/metal/data_streaming.rb | 1 | ||||
-rw-r--r-- | actionpack/lib/action_controller/metal/implicit_render.rb | 2 | ||||
-rw-r--r-- | actionpack/lib/action_controller/test_case.rb | 1 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/http/headers.rb | 2 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/http/response.rb | 23 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/routing/mapper.rb | 2 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/testing/integration.rb | 6 | ||||
-rw-r--r-- | actionpack/test/controller/force_ssl_test.rb | 2 | ||||
-rw-r--r-- | actionpack/test/controller/send_file_test.rb | 14 | ||||
-rw-r--r-- | actionpack/test/dispatch/header_test.rb | 6 | ||||
-rw-r--r-- | actionpack/test/dispatch/routing_test.rb | 42 | ||||
-rw-r--r-- | actionpack/test/dispatch/runner_test.rb | 18 |
13 files changed, 123 insertions, 15 deletions
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index a66a1e8af3..999ac82d42 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,10 +1,27 @@ +* Fix nested multiple roots + + The PR #20940 enabled the use of multiple roots with different constraints + at the top level but unfortunately didn't work when those roots were inside + a namespace and also broke the use of root inside a namespace after a top + level root was defined because the check for the existence of the named route + used the global :root name and not the namespaced name. + + This is fixed by using the name_for_action method to expand the :root name to + the full namespaced name. We can pass nil for the second argument as we're not + dealing with resource definitions so don't need to handle the cases for edit + and new routes. + + Fixes #26148. + + *Ryo Hashimoto*, *Andrew White* + * Include the content of the flash in the auto-generated etag. This solves the following problem: 1. POST /messages 2. redirect_to messages_url, notice: 'Message was created' 3. GET /messages/1 4. GET /messages - + Step 4 would before still include the flash message, even though it's no longer relevant, because the etag cache was recorded with the flash in place and didn't change when it was gone. diff --git a/actionpack/lib/action_controller/metal/data_streaming.rb b/actionpack/lib/action_controller/metal/data_streaming.rb index b598dd4d77..6a1acb64f7 100644 --- a/actionpack/lib/action_controller/metal/data_streaming.rb +++ b/actionpack/lib/action_controller/metal/data_streaming.rb @@ -70,6 +70,7 @@ module ActionController #:nodoc: send_file_headers! options self.status = options[:status] || 200 + self.content_type = options[:type] if options.key?(:type) self.content_type = options[:content_type] if options.key?(:content_type) response.send_file path end diff --git a/actionpack/lib/action_controller/metal/implicit_render.rb b/actionpack/lib/action_controller/metal/implicit_render.rb index c414527d63..4137db99ea 100644 --- a/actionpack/lib/action_controller/metal/implicit_render.rb +++ b/actionpack/lib/action_controller/metal/implicit_render.rb @@ -48,7 +48,7 @@ module ActionController "NOTE! For XHR/Ajax or API requests, this action would normally " \ "respond with 204 No Content: an empty white screen. Since you're " \ "loading it in a web browser, we assume that you expected to " \ - "actually render a template, not… nothing, so we're showing an " \ + "actually render a template, not nothing, so we're showing an " \ "error to be extra-clear. If you expect 204 No Content, carry on. " \ "That's what you'll get from an XHR or API request. Give it a shot." diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb index 11a6cf8e15..d84320b713 100644 --- a/actionpack/lib/action_controller/test_case.rb +++ b/actionpack/lib/action_controller/test_case.rb @@ -627,6 +627,7 @@ module ActionController include ActionDispatch::Assertions class_attribute :_controller_class setup :setup_controller_request_and_response + ActiveSupport.run_load_hooks(:action_controller_test_case, self) end private diff --git a/actionpack/lib/action_dispatch/http/headers.rb b/actionpack/lib/action_dispatch/http/headers.rb index d5eef2987d..0528a6ad08 100644 --- a/actionpack/lib/action_dispatch/http/headers.rb +++ b/actionpack/lib/action_dispatch/http/headers.rb @@ -86,7 +86,7 @@ module ActionDispatch @req.fetch_header(env_name(key)) do return default unless default == DEFAULT return yield if block_given? - raise NameError, key + raise KeyError, key end end diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index 9788431943..e8173e2a99 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -224,8 +224,10 @@ module ActionDispatch # :nodoc: # Sets the HTTP content type. def content_type=(content_type) - header_info = parse_content_type - set_content_type content_type.to_s, header_info.charset || self.class.default_charset + return unless content_type + new_header_info = parse_content_type(content_type.to_s) + prev_header_info = parsed_content_type_header + set_content_type new_header_info.mime_type, new_header_info.charset || prev_header_info.charset || self.class.default_charset end # Sets the HTTP response's content MIME type. For example, in the controller @@ -238,7 +240,7 @@ module ActionDispatch # :nodoc: # information. def content_type - parse_content_type.mime_type + parsed_content_type_header.mime_type end def sending_file=(v) @@ -253,7 +255,7 @@ module ActionDispatch # :nodoc: # response.charset = 'utf-16' # => 'utf-16' # response.charset = nil # => 'utf-8' def charset=(charset) - header_info = parse_content_type + header_info = parsed_content_type_header if false == charset set_header CONTENT_TYPE, header_info.mime_type else @@ -265,7 +267,7 @@ module ActionDispatch # :nodoc: # The charset of the response. HTML wants to know the encoding of the # content you're giving them, so we need to send that along. def charset - header_info = parse_content_type + header_info = parsed_content_type_header header_info.charset || self.class.default_charset end @@ -403,8 +405,7 @@ module ActionDispatch # :nodoc: ContentTypeHeader = Struct.new :mime_type, :charset NullContentTypeHeader = ContentTypeHeader.new nil, nil - def parse_content_type - content_type = get_header CONTENT_TYPE + def parse_content_type(content_type) if content_type type, charset = content_type.split(/;\s*charset=/) type = nil if type.empty? @@ -414,6 +415,12 @@ module ActionDispatch # :nodoc: end end + # Small internal convenience method to get the parsed version of the current + # content type header. + def parsed_content_type_header + parse_content_type(get_header(CONTENT_TYPE)) + end + def set_content_type(content_type, charset) type = (content_type || "").dup type << "; charset=#{charset}" if charset @@ -450,7 +457,7 @@ module ActionDispatch # :nodoc: def assign_default_content_type_and_charset! return if content_type - ct = parse_content_type + ct = parsed_content_type_header set_content_type(ct.mime_type || Mime[:html].to_s, ct.charset || self.class.default_charset) end diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index b3acac42fc..67b9463a6a 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -1927,7 +1927,7 @@ to this: end def match_root_route(options) - name = has_named_route?(:root) ? nil : :root + name = has_named_route?(name_for_action(:root, nil)) ? nil : :root args = ["/", { as: name, via: :get }.merge!(options)] match(*args) diff --git a/actionpack/lib/action_dispatch/testing/integration.rb b/actionpack/lib/action_dispatch/testing/integration.rb index 13f7fc6fa6..f5ec28a9c2 100644 --- a/actionpack/lib/action_dispatch/testing/integration.rb +++ b/actionpack/lib/action_dispatch/testing/integration.rb @@ -420,9 +420,13 @@ module ActionDispatch attr_reader :app + def initialize(*args, &blk) + super(*args, &blk) + @integration_session = nil + end + def before_setup # :nodoc: @app = nil - @integration_session = nil super end diff --git a/actionpack/test/controller/force_ssl_test.rb b/actionpack/test/controller/force_ssl_test.rb index 8d5e3ce2fe..2b3859aa57 100644 --- a/actionpack/test/controller/force_ssl_test.rb +++ b/actionpack/test/controller/force_ssl_test.rb @@ -229,14 +229,12 @@ class ForceSSLFlashTest < ActionController::TestCase assert_response 302 assert_equal "http://test.host/force_ssl_flash/cheeseburger", redirect_to_url - # FIXME: AC::TestCase#build_request_uri doesn't build a new uri if PATH_INFO exists @request.env.delete("PATH_INFO") get :cheeseburger assert_response 301 assert_equal "https://test.host/force_ssl_flash/cheeseburger", redirect_to_url - # FIXME: AC::TestCase#build_request_uri doesn't build a new uri if PATH_INFO exists @request.env.delete("PATH_INFO") get :use_flash diff --git a/actionpack/test/controller/send_file_test.rb b/actionpack/test/controller/send_file_test.rb index 25420ead3b..8dc565ac8d 100644 --- a/actionpack/test/controller/send_file_test.rb +++ b/actionpack/test/controller/send_file_test.rb @@ -233,4 +233,18 @@ class SendFileTest < ActionController::TestCase response = process("file") assert_equal 200, response.status end + + def test_send_file_charset_with_type_options_key + @controller = SendFileWithActionControllerLive.new + @controller.options = { type: "text/calendar; charset=utf-8" } + response = process("file") + assert_equal "text/calendar; charset=utf-8", response.headers["Content-Type"] + end + + def test_send_file_charset_with_content_type_options_key + @controller = SendFileWithActionControllerLive.new + @controller.options = { content_type: "text/calendar" } + response = process("file") + assert_equal "text/calendar; charset=utf-8", response.headers["Content-Type"] + end end diff --git a/actionpack/test/dispatch/header_test.rb b/actionpack/test/dispatch/header_test.rb index 7a155d70cb..374e618b42 100644 --- a/actionpack/test/dispatch/header_test.rb +++ b/actionpack/test/dispatch/header_test.rb @@ -158,4 +158,10 @@ class HeaderTest < ActiveSupport::TestCase assert_equal({ "HTTP_REFERER"=>"http://example.com/", "CONTENT_TYPE"=>"text/plain" }, env) end + + test "fetch exception" do + assert_raises KeyError do + @headers.fetch(:some_key_that_doesnt_exist) + end + end end diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index ee5c30ef0e..0938460632 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -3669,6 +3669,48 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end end + def test_multiple_roots + draw do + namespace :foo do + root "pages#index", constraints: { host: 'www.example.com' } + root "admin/pages#index", constraints: { host: 'admin.example.com' } + end + + root "pages#index", constraints: { host: 'www.example.com' } + root "admin/pages#index", constraints: { host: 'admin.example.com' } + end + + get "http://www.example.com/foo" + assert_equal "foo/pages#index", @response.body + + get "http://admin.example.com/foo" + assert_equal "foo/admin/pages#index", @response.body + + get "http://www.example.com/" + assert_equal "pages#index", @response.body + + get "http://admin.example.com/" + assert_equal "admin/pages#index", @response.body + end + + def test_namespaced_roots + draw do + namespace :foo do + root "test#index" + end + + root "test#index" + + namespace :bar do + root "test#index" + end + end + + assert_equal "/foo", foo_root_path + assert_equal "/", root_path + assert_equal "/bar", bar_root_path + end + private def draw(&block) diff --git a/actionpack/test/dispatch/runner_test.rb b/actionpack/test/dispatch/runner_test.rb new file mode 100644 index 0000000000..969933c9ed --- /dev/null +++ b/actionpack/test/dispatch/runner_test.rb @@ -0,0 +1,18 @@ +require "abstract_unit" + +class RunnerTest < ActiveSupport::TestCase + test "runner preserves the setting of integration_session" do + runner = Class.new do + def before_setup + + end + end.new + + runner.extend(ActionDispatch::Integration::Runner) + runner.integration_session.host! "lvh.me" + + runner.before_setup + + assert_equal "lvh.me", runner.integration_session.host + end +end |