From 024bed387b067519de64af5b89ce2b534c99155f Mon Sep 17 00:00:00 2001 From: Chris Eppstein Date: Mon, 27 Jun 2011 13:58:51 -0700 Subject: Added a configuration setting: config.action_controller.default_asset_host_protocol It's best to leave this unset. When unset the :request protocol is used whenever it can be and :relative is used in the other situations. When set to :request then assets hosts will be disabled when there is no request in scope and will use the request protocol whenever a request is in scope. If set to :relative, then a relative protocol is always used except for stylesheet link tags which must use the :request protocol to avoid double downloads in IE6&7. Conflicts: actionpack/lib/sprockets/helpers/rails_helper.rb actionpack/test/template/sprockets_helper_test.rb --- actionpack/lib/action_view/asset_paths.rb | 18 ++++++++++++++---- .../helpers/asset_tag_helpers/asset_include_tag.rb | 4 ++-- .../asset_tag_helpers/stylesheet_tag_helpers.rb | 3 ++- actionpack/lib/sprockets/helpers/rails_helper.rb | 6 +++--- actionpack/test/template/asset_tag_helper_test.rb | 22 ++++++++++++++++------ actionpack/test/template/sprockets_helper_test.rb | 19 ++++++++++++++++++- 6 files changed, 55 insertions(+), 17 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_view/asset_paths.rb b/actionpack/lib/action_view/asset_paths.rb index a768a0b882..4dd02755d3 100644 --- a/actionpack/lib/action_view/asset_paths.rb +++ b/actionpack/lib/action_view/asset_paths.rb @@ -19,7 +19,7 @@ module ActionView # When :relative (default), the protocol will be determined by the client using current protocol # When :request, the protocol will be the request protocol # Otherwise, the protocol is used (E.g. :http, :https, etc) - def compute_public_path(source, dir, ext = nil, include_host = true, protocol = :relative) + def compute_public_path(source, dir, ext = nil, include_host = true, protocol = nil) source = source.to_s return source if is_uri?(source) @@ -58,16 +58,20 @@ module ActionView controller.respond_to?(:request) end - def rewrite_host_and_protocol(source, protocol = :relative) + def rewrite_host_and_protocol(source, protocol = nil) host = compute_asset_host(source) if host && !is_uri?(host) - host = "#{compute_protocol(protocol)}#{host}" + if (protocol || default_protocol) == :request && !has_request? + host = nil + else + host = "#{compute_protocol(protocol)}#{host}" + end end host.nil? ? source : "#{host}#{source}" end def compute_protocol(protocol) - protocol ||= :relative + protocol ||= default_protocol case protocol when :relative "//" @@ -81,6 +85,12 @@ module ActionView end end + def default_protocol + protocol = @config.action_controller.default_asset_host_protocol if @config.action_controller.present? + protocol ||= @config.default_asset_host_protocol + protocol || (has_request? ? :request : :relative) + end + def invalid_asset_host!(help_message) raise ActionController::RoutingError, "This asset host cannot be computed without a request in scope. #{help_message}" end diff --git a/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb b/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb index 621f7aaa0a..3c05173a1b 100644 --- a/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb +++ b/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb @@ -60,8 +60,8 @@ module ActionView private - def path_to_asset(source, protocol = :relative) - asset_paths.compute_public_path(source, asset_name.to_s.pluralize, extension, true, protocol) + def path_to_asset(source, include_host = true, protocol = nil) + asset_paths.compute_public_path(source, asset_name.to_s.pluralize, extension, include_host, protocol) end def path_to_asset_source(source) diff --git a/actionpack/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb b/actionpack/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb index e829588e94..8c25d38bbd 100644 --- a/actionpack/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb +++ b/actionpack/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb @@ -16,7 +16,8 @@ module ActionView end def asset_tag(source, options) - tag("link", { "rel" => "stylesheet", "type" => Mime::CSS, "media" => "screen", "href" => ERB::Util.html_escape(path_to_asset(source, :request)) }.merge(options), false, false) + # We force the :request protocol here to avoid a double-download bug in IE7 and IE8 + tag("link", { "rel" => "stylesheet", "type" => Mime::CSS, "media" => "screen", "href" => ERB::Util.html_escape(path_to_asset(source, true, :request)) }.merge(options), false, false) end def custom_dir diff --git a/actionpack/lib/sprockets/helpers/rails_helper.rb b/actionpack/lib/sprockets/helpers/rails_helper.rb index cf185749ea..63820cc76c 100644 --- a/actionpack/lib/sprockets/helpers/rails_helper.rb +++ b/actionpack/lib/sprockets/helpers/rails_helper.rb @@ -64,9 +64,9 @@ module Sprockets end.join("\n").html_safe end - def asset_path(source, default_ext = nil, body = false, protocol = :relative) + def asset_path(source, default_ext = nil, body = false, protocol = nil) source = source.logical_path if source.respond_to?(:logical_path) - path = asset_paths.compute_public_path(source, 'assets', default_ext, protocol) + path = asset_paths.compute_public_path(source, 'assets', default_ext, true, protocol) body ? "#{path}?body=1" : path end @@ -77,7 +77,7 @@ module Sprockets end class AssetPaths < ::ActionView::AssetPaths #:nodoc: - def compute_public_path(source, dir, ext=nil, include_host=true, protocol = :relative) + def compute_public_path(source, dir, ext=nil, include_host=true, protocol = nil) super(source, Rails.application.config.assets.prefix, ext, include_host, protocol) end diff --git a/actionpack/test/template/asset_tag_helper_test.rb b/actionpack/test/template/asset_tag_helper_test.rb index cb7ab2572e..1c4f30a2bc 100644 --- a/actionpack/test/template/asset_tag_helper_test.rb +++ b/actionpack/test/template/asset_tag_helper_test.rb @@ -1093,11 +1093,21 @@ class AssetTagHelperNonVhostTest < ActionView::TestCase def test_should_compute_proper_path_with_asset_host @controller.config.asset_host = "assets.example.com" assert_dom_equal(%(), auto_discovery_link_tag) - assert_dom_equal(%(//assets.example.com/collaboration/hieraki/javascripts/xmlhr.js), javascript_path("xmlhr")) + assert_dom_equal(%(gopher://assets.example.com/collaboration/hieraki/javascripts/xmlhr.js), javascript_path("xmlhr")) assert_dom_equal(%(gopher://assets.example.com/collaboration/hieraki/stylesheets/style.css), stylesheet_path("style")) - assert_dom_equal(%(//assets.example.com/collaboration/hieraki/images/xml.png), image_path("xml.png")) - assert_dom_equal(%(Mouse), image_tag("mouse.png", :mouseover => "/images/mouse_over.png")) - assert_dom_equal(%(Mouse2), image_tag("mouse2.png", :mouseover => image_path("mouse_over2.png"))) + assert_dom_equal(%(gopher://assets.example.com/collaboration/hieraki/images/xml.png), image_path("xml.png")) + assert_dom_equal(%(Mouse), image_tag("mouse.png", :mouseover => "/images/mouse_over.png")) + assert_dom_equal(%(Mouse2), image_tag("mouse2.png", :mouseover => image_path("mouse_over2.png"))) + end + + def test_should_compute_proper_path_with_asset_host_and_default_protocol + @controller.config.asset_host = "assets.example.com" + @controller.config.default_asset_host_protocol = :request + assert_dom_equal(%(gopher://assets.example.com/collaboration/hieraki/javascripts/xmlhr.js), javascript_path("xmlhr")) + assert_dom_equal(%(gopher://assets.example.com/collaboration/hieraki/stylesheets/style.css), stylesheet_path("style")) + assert_dom_equal(%(gopher://assets.example.com/collaboration/hieraki/images/xml.png), image_path("xml.png")) + assert_dom_equal(%(Mouse), image_tag("mouse.png", :mouseover => "/images/mouse_over.png")) + assert_dom_equal(%(Mouse2), image_tag("mouse2.png", :mouseover => image_path("mouse_over2.png"))) end def test_should_ignore_asset_host_on_complete_url @@ -1117,12 +1127,12 @@ class AssetTagHelperNonVhostTest < ActionView::TestCase def test_asset_host_without_protocol_should_be_protocol_relative @controller.config.asset_host = 'a.example.com' - assert_equal '//a.example.com/collaboration/hieraki/images/xml.png', image_path('xml.png') + assert_equal 'gopher://a.example.com/collaboration/hieraki/images/xml.png', image_path('xml.png') end def test_asset_host_without_protocol_should_be_protocol_relative_even_if_path_present @controller.config.asset_host = 'a.example.com/files/go/here' - assert_equal '//a.example.com/files/go/here/collaboration/hieraki/images/xml.png', image_path('xml.png') + assert_equal 'gopher://a.example.com/files/go/here/collaboration/hieraki/images/xml.png', image_path('xml.png') end def test_assert_css_and_js_of_the_same_name_return_correct_extension diff --git a/actionpack/test/template/sprockets_helper_test.rb b/actionpack/test/template/sprockets_helper_test.rb index 7197a23480..6dc9a2a743 100644 --- a/actionpack/test/template/sprockets_helper_test.rb +++ b/actionpack/test/template/sprockets_helper_test.rb @@ -62,11 +62,18 @@ class SprocketsHelperTest < ActionView::TestCase asset_path("http://www.example.com/video/play.mp4") end - test "with a simple asset host the url should be protocol relative" do + test "with a simple asset host the url should default to protocol relative" do @controller.config.asset_host = "assets-%d.example.com" assert_match %r{//assets-\d.example.com/assets/logo-[0-9a-f]+.png}, asset_path("logo.png") end + + test "with a simple asset host the url can be changed to use the request protocol" do + @controller.config.asset_host = "assets-%d.example.com" + @controller.config.default_asset_host_protocol = :request + assert_match %r{http://assets-\d.example.com/assets/logo-[0-9a-f]+.png}, + asset_path("logo.png") + end test "With a proc asset host that returns no protocol the url should be protocol relative" do @controller.config.asset_host = Proc.new do |asset| @@ -103,6 +110,16 @@ class SprocketsHelperTest < ActionView::TestCase end end + test "stylesheets served without a controller in do not use asset hosts when the default protocol is :request" do + remove_instance_variable("@controller") + @config.action_controller.asset_host = "assets-%d.example.com" + @config.action_controller.default_asset_host_protocol = :request + @config.action_controller.perform_caching = true + + assert_equal "/assets/logo-9c0a079bdd7701d7e729bd956823d153.png", + asset_path("logo.png") + end + test "asset path with relative url root" do @controller.config.relative_url_root = "/collaboration/hieraki" assert_equal "/collaboration/hieraki/images/logo.gif", -- cgit v1.2.3