can't precompile assets when action_controller.asset_host accepts a 2nd argument #2947

Closed
josh-m-sharpe opened this Issue Sep 8, 2011 · 36 comments

Comments

Projects
None yet
6 participants
@josh-m-sharpe
Contributor

josh-m-sharpe commented Sep 8, 2011

So this, is basically straight from the docs:

config.action_controller.asset_host = Proc.new { |source, request|
if request.ssl?
"#{request.protocol}#{request.host_with_port}"
else
"#{request.protocol}assets#{(source.length % 4) + 1}.example.com"
end
}

http://api.rubyonrails.org/classes/ActionView/Helpers/AssetTagHelper.html (about 1/4 the way down, can't link, sorry.)

Anyways, deploying:

  * executing "date && cd /rails/current && RAILS_ENV=production bundle exec rake assets:precompile"
 ** [out :: prod-app1] rake aborted!
 ** [out :: prod-app1] This asset host cannot be computed without a request in scope. Remove the second argument to your asset_host Proc if you do not need the request.
 ** [out :: prod-app1] (in /rails/releases/20110908200102/vendor/assets/stylesheets/jquery-ui-1.8.16.custom.css.erb)
 ** [out :: prod-app1] 
 ** [out :: prod-app1] 
 ** [out :: prod-app1] Tasks: TOP => assets:precompile
 ** [out :: prod-app1] (See full trace by running task with --trace)
@guilleiguaran

This comment has been minimized.

Show comment
Hide comment
@guilleiguaran

guilleiguaran Sep 11, 2011

Member

Can you upload to a Git repo a minimal sample app to reproduce the issue? Thanks!!!

Member

guilleiguaran commented Sep 11, 2011

Can you upload to a Git repo a minimal sample app to reproduce the issue? Thanks!!!

@kennyj

This comment has been minimized.

Show comment
Hide comment
@kennyj

kennyj Sep 11, 2011

Contributor

@guilleiguaran, I reproduced the issue.

frist, write above code in config/production.rb
second, use "asset_path" in foo.css.scss.erb

and
$ bundle exec rake assets:precompile

Sprockets::Helpers::RailsHelper#asset_path
=> Sprockets::Helpers::RailsHelper::AssetPaths#compute_public_path
=> ActionView::AssetPaths#compute_public_path
=> ActionView::AssetPaths#rewrite_host_and_protocol
=> ActionView::AssetPaths#compute_asset_host <-- error happen!

Contributor

kennyj commented Sep 11, 2011

@guilleiguaran, I reproduced the issue.

frist, write above code in config/production.rb
second, use "asset_path" in foo.css.scss.erb

and
$ bundle exec rake assets:precompile

Sprockets::Helpers::RailsHelper#asset_path
=> Sprockets::Helpers::RailsHelper::AssetPaths#compute_public_path
=> ActionView::AssetPaths#compute_public_path
=> ActionView::AssetPaths#rewrite_host_and_protocol
=> ActionView::AssetPaths#compute_asset_host <-- error happen!

@guilleiguaran

This comment has been minimized.

Show comment
Hide comment
@guilleiguaran

guilleiguaran Sep 11, 2011

Member

The problem is that when the assets are precompiled the request isn't available and the helpers couldn't know calculate the host that need to be used for assets. I guess this bug will be difficult to solve

Member

guilleiguaran commented Sep 11, 2011

The problem is that when the assets are precompiled the request isn't available and the helpers couldn't know calculate the host that need to be used for assets. I guess this bug will be difficult to solve

@josh-m-sharpe

This comment has been minimized.

Show comment
Hide comment
@josh-m-sharpe

josh-m-sharpe Sep 11, 2011

Contributor

I don't think so. Don't you just want assets:precompile to ignore the protocol?

You definitely don't want "http" or "https" in your stylesheets, right? That is, all references should be relative to the domain: url(/assets/foo.png) - that way they work on both protocols.

Contributor

josh-m-sharpe commented Sep 11, 2011

I don't think so. Don't you just want assets:precompile to ignore the protocol?

You definitely don't want "http" or "https" in your stylesheets, right? That is, all references should be relative to the domain: url(/assets/foo.png) - that way they work on both protocols.

@kennyj

This comment has been minimized.

Show comment
Hide comment
@kennyj

kennyj Sep 11, 2011

Contributor

@crankharder, I think so.

In actionpack/lib/sprockets/assets.rake
task :precompile do
...

Always ignore host

Rails.application.config.action_controller.asset_host = nil
...
end

It's work.

Contributor

kennyj commented Sep 11, 2011

@crankharder, I think so.

In actionpack/lib/sprockets/assets.rake
task :precompile do
...

Always ignore host

Rails.application.config.action_controller.asset_host = nil
...
end

It's work.

@guilleiguaran

This comment has been minimized.

Show comment
Hide comment
@guilleiguaran

guilleiguaran Sep 11, 2011

Member

@crankharder, Yes, the protocol is ignored but the host isn't ignored and in your example the host depends on the protocol.

The assets are using protocol relative url, then if your hosts are http://assets.example.org and https://assets.example.org you can set host to assets.example.org and it will be used in the assets as //assets.example.org. This works as expected but this don't work when the assets are depending on the request protocol:

config.action_controller.asset_host = Proc.new { |source, request|  request.ssl? ? "ssl.assets.example.org" : "assets.example.org" }

Maybe a better idea use only the ssl.assets.example.org in this case?

Member

guilleiguaran commented Sep 11, 2011

@crankharder, Yes, the protocol is ignored but the host isn't ignored and in your example the host depends on the protocol.

The assets are using protocol relative url, then if your hosts are http://assets.example.org and https://assets.example.org you can set host to assets.example.org and it will be used in the assets as //assets.example.org. This works as expected but this don't work when the assets are depending on the request protocol:

config.action_controller.asset_host = Proc.new { |source, request|  request.ssl? ? "ssl.assets.example.org" : "assets.example.org" }

Maybe a better idea use only the ssl.assets.example.org in this case?

@guilleiguaran

This comment has been minimized.

Show comment
Hide comment
@guilleiguaran

guilleiguaran Sep 11, 2011

Member

@kennyj, If I have in my app site example.org a reference to an CSS in other host, for example:

<link href="http://assets.example.org/application.css" rel="stylesheet" type="text/css" />

and I have inside the CSS a reference to an image:

.logo { background: url(/assets/logo.png); }

The image will be find in same domain of css (assets.example.org) or in my app domain (example.org) ?

Member

guilleiguaran commented Sep 11, 2011

@kennyj, If I have in my app site example.org a reference to an CSS in other host, for example:

<link href="http://assets.example.org/application.css" rel="stylesheet" type="text/css" />

and I have inside the CSS a reference to an image:

.logo { background: url(/assets/logo.png); }

The image will be find in same domain of css (assets.example.org) or in my app domain (example.org) ?

@guilleiguaran

This comment has been minimized.

Show comment
Hide comment
@guilleiguaran

guilleiguaran Sep 11, 2011

Member

@crankharder, @kennyj You are right, just ignore the asset_host in the context of the erb files during precompile will work fine.

Member

guilleiguaran commented Sep 11, 2011

@crankharder, @kennyj You are right, just ignore the asset_host in the context of the erb files during precompile will work fine.

@kennyj

This comment has been minimized.

Show comment
Hide comment
@kennyj

kennyj Sep 11, 2011

Contributor

@guilleiguaran,
same domain of css ? (I checked with chrome developer tool)

Contributor

kennyj commented Sep 11, 2011

@guilleiguaran,
same domain of css ? (I checked with chrome developer tool)

@guilleiguaran

This comment has been minimized.

Show comment
Hide comment
@guilleiguaran

guilleiguaran Sep 11, 2011

Member

@kennyj, yes, just confirmed same, then I think ignoring asset_host is fine during precompile

Member

guilleiguaran commented Sep 11, 2011

@kennyj, yes, just confirmed same, then I think ignoring asset_host is fine during precompile

@josh-m-sharpe

This comment has been minimized.

Show comment
Hide comment
@josh-m-sharpe

josh-m-sharpe Sep 11, 2011

Contributor

@guilleiguaran - the link and script tags don't contain the host/protocol, they're relative - as they should be:

  <link href="/assets/application-aea14f68042284f50eb1c0d3154737e5.css" media="screen" rel="stylesheet" type="text/css" /> 
  <script src="/assets/application-ab0fb1a755ec718df528309a6b0e8be6.js" type="text/javascript"></script> 
Contributor

josh-m-sharpe commented Sep 11, 2011

@guilleiguaran - the link and script tags don't contain the host/protocol, they're relative - as they should be:

  <link href="/assets/application-aea14f68042284f50eb1c0d3154737e5.css" media="screen" rel="stylesheet" type="text/css" /> 
  <script src="/assets/application-ab0fb1a755ec718df528309a6b0e8be6.js" type="text/javascript"></script> 
@josh-m-sharpe

This comment has been minimized.

Show comment
Hide comment
@josh-m-sharpe

josh-m-sharpe Sep 11, 2011

Contributor

To be clear, I'm agreeing with you - asset_host should be ignored during precompile.

Contributor

josh-m-sharpe commented Sep 11, 2011

To be clear, I'm agreeing with you - asset_host should be ignored during precompile.

@kennyj

This comment has been minimized.

Show comment
Hide comment
@kennyj

kennyj Sep 11, 2011

Contributor

commited on my repo.
kennyj/rails@00ddf14

Contributor

kennyj commented Sep 11, 2011

commited on my repo.
kennyj/rails@00ddf14

@guilleiguaran

This comment has been minimized.

Show comment
Hide comment
@guilleiguaran

guilleiguaran Sep 11, 2011

Member

@crankharder: I think the link/script tags must include the asset host when the asset path is calculated inside a view (isn't equal to the domain app domain in all the cases):

<link href="https://ssl.example.org/assets/application-aea14f68042284f50eb1c0d3154737e5.css" media="screen" rel="stylesheet" type="text/css" />

But it should be ignore inside the CSS files when asset_path is used since the domain of css is the same domain of the other assets, for example

.logo { background: url(/assets/logo-aea14f68042284f50eb1c0d3154737e5.png); }
Member

guilleiguaran commented Sep 11, 2011

@crankharder: I think the link/script tags must include the asset host when the asset path is calculated inside a view (isn't equal to the domain app domain in all the cases):

<link href="https://ssl.example.org/assets/application-aea14f68042284f50eb1c0d3154737e5.css" media="screen" rel="stylesheet" type="text/css" />

But it should be ignore inside the CSS files when asset_path is used since the domain of css is the same domain of the other assets, for example

.logo { background: url(/assets/logo-aea14f68042284f50eb1c0d3154737e5.png); }
@kennyj

This comment has been minimized.

Show comment
Hide comment
@kennyj

kennyj Sep 11, 2011

Contributor

@guilleiguaran, I think so :-)

Contributor

kennyj commented Sep 11, 2011

@guilleiguaran, I think so :-)

@guilleiguaran

This comment has been minimized.

Show comment
Hide comment
@guilleiguaran

guilleiguaran Sep 11, 2011

Member

@kennyj I think your fix can be merged but you will need to provide a test case.

Member

guilleiguaran commented Sep 11, 2011

@kennyj I think your fix can be merged but you will need to provide a test case.

@kennyj

This comment has been minimized.

Show comment
Hide comment
@kennyj

kennyj Sep 11, 2011

Contributor

@guilleiguaran I go to sleep today and will continue tomorrow (in japan, it is 3:18 a.m. now.).

Contributor

kennyj commented Sep 11, 2011

@guilleiguaran I go to sleep today and will continue tomorrow (in japan, it is 3:18 a.m. now.).

@kennyj

This comment has been minimized.

Show comment
Hide comment
@kennyj

kennyj Sep 12, 2011

Contributor

@guilleiguaran this commit include testcase.

kennyj/rails@09f9539

Contributor

kennyj commented Sep 12, 2011

@guilleiguaran this commit include testcase.

kennyj/rails@09f9539

@guilleiguaran

This comment has been minimized.

Show comment
Hide comment
@guilleiguaran

guilleiguaran Sep 12, 2011

Member

@kennyj please squash the commits and send a pull request :)

Member

guilleiguaran commented Sep 12, 2011

@kennyj please squash the commits and send a pull request :)

@kennyj

This comment has been minimized.

Show comment
Hide comment
@kennyj

kennyj Sep 12, 2011

Contributor

@guilleiguaran @crankharder I send a pull request #2987.
thanks!

Contributor

kennyj commented Sep 12, 2011

@guilleiguaran @crankharder I send a pull request #2987.
thanks!

@spastorino

This comment has been minimized.

Show comment
Hide comment
@spastorino

spastorino Sep 13, 2011

Member

Pushed

Member

spastorino commented Sep 13, 2011

Pushed

@spastorino spastorino closed this Sep 13, 2011

@josh-m-sharpe

This comment has been minimized.

Show comment
Hide comment
@josh-m-sharpe

josh-m-sharpe Sep 13, 2011

Contributor

Hey all. Thanks! Much appreciated.

Contributor

josh-m-sharpe commented Sep 13, 2011

Hey all. Thanks! Much appreciated.

@cgriego

This comment has been minimized.

Show comment
Hide comment
@cgriego

cgriego Sep 14, 2011

Contributor

The use of asset hosts was one of the compelling features of the asset pipeline over alternatives. Couldn't your proc have just been changed to make the request argument optional? This change takes away the ability to use asset hosts in compiled assets from those that were not relying on the request object and doesn't even give them a configuration option.

Contributor

cgriego commented Sep 14, 2011

The use of asset hosts was one of the compelling features of the asset pipeline over alternatives. Couldn't your proc have just been changed to make the request argument optional? This change takes away the ability to use asset hosts in compiled assets from those that were not relying on the request object and doesn't even give them a configuration option.

@josh-m-sharpe

This comment has been minimized.

Show comment
Hide comment
@josh-m-sharpe

josh-m-sharpe Sep 14, 2011

Contributor

@cgriego This doesn't change the behavior of precompile:assets. It just makes it work without raising an error. You can still use <%= asset_path(...) %> in your css/js.

Contributor

josh-m-sharpe commented Sep 14, 2011

@cgriego This doesn't change the behavior of precompile:assets. It just makes it work without raising an error. You can still use <%= asset_path(...) %> in your css/js.

@cgriego

This comment has been minimized.

Show comment
Hide comment
@cgriego

cgriego Sep 14, 2011

Contributor

The related pull request overwrites my application's config. How does that not change the behavior?

#2987

Contributor

cgriego commented Sep 14, 2011

The related pull request overwrites my application's config. How does that not change the behavior?

#2987

@josh-m-sharpe

This comment has been minimized.

Show comment
Hide comment
@josh-m-sharpe

josh-m-sharpe Sep 14, 2011

Contributor

It only overwrites it for the duration of the rake task. There's no request inside of a rake task...

Contributor

josh-m-sharpe commented Sep 14, 2011

It only overwrites it for the duration of the rake task. There's no request inside of a rake task...

@cgriego

This comment has been minimized.

Show comment
Hide comment
@cgriego

cgriego Sep 14, 2011

Contributor

Right, I understand that piece, but the duration of the rake task is what precompiles the assets. So now none of the CSS, where the bulk of the images are used (images being the bulk of the http requests), benefit from asset hosts and there's nothing I can do about it.

Contributor

cgriego commented Sep 14, 2011

Right, I understand that piece, but the duration of the rake task is what precompiles the assets. So now none of the CSS, where the bulk of the images are used (images being the bulk of the http requests), benefit from asset hosts and there's nothing I can do about it.

@josh-m-sharpe

This comment has been minimized.

Show comment
Hide comment
@josh-m-sharpe

josh-m-sharpe Sep 14, 2011

Contributor

Can you show an asset_host as an example?

Contributor

josh-m-sharpe commented Sep 14, 2011

Can you show an asset_host as an example?

@cgriego

This comment has been minimized.

Show comment
Hide comment
@cgriego

cgriego Sep 15, 2011

Contributor

Here, this is taken almost exactly from the Rails framework documentation.

config.action_controller.asset_host = Proc.new { |source|
  "//assets#{Digest::MD5.hexdigest(source).to_i(16) % 2 + 1}.example.com"
}
Contributor

cgriego commented Sep 15, 2011

Here, this is taken almost exactly from the Rails framework documentation.

config.action_controller.asset_host = Proc.new { |source|
  "//assets#{Digest::MD5.hexdigest(source).to_i(16) % 2 + 1}.example.com"
}
@josh-m-sharpe

This comment has been minimized.

Show comment
Hide comment
@josh-m-sharpe

josh-m-sharpe Sep 15, 2011

Contributor

@guilleiguaran, @spastorino,

I'm pretty sure that @cgriego has valid point. With this patch included all assets in the css will be served up on the domain that served that stylesheet. So the benefit of rotating assets on multiple subdomains is completely removed.

I think the correct answer to my original question/problem is not a patch, but recognition that you can't serve secure assets on a single domain and also rotate unsecure assets on 4 subdomains - which is what my very first post is trying to achieve.

I think I'm going to change my asset_host to this:

config.action_controller.asset_host = Proc.new { |source|
"//assets#{(source.length % 4) + 1}.example.com"
}

....and get a wildcard cert.

This would solve my problem without the patch.

Ultimately, I think the patch should be reverted.

Contributor

josh-m-sharpe commented Sep 15, 2011

@guilleiguaran, @spastorino,

I'm pretty sure that @cgriego has valid point. With this patch included all assets in the css will be served up on the domain that served that stylesheet. So the benefit of rotating assets on multiple subdomains is completely removed.

I think the correct answer to my original question/problem is not a patch, but recognition that you can't serve secure assets on a single domain and also rotate unsecure assets on 4 subdomains - which is what my very first post is trying to achieve.

I think I'm going to change my asset_host to this:

config.action_controller.asset_host = Proc.new { |source|
"//assets#{(source.length % 4) + 1}.example.com"
}

....and get a wildcard cert.

This would solve my problem without the patch.

Ultimately, I think the patch should be reverted.

@guilleiguaran

This comment has been minimized.

Show comment
Hide comment
@guilleiguaran

guilleiguaran Sep 15, 2011

Member

Maybe revert and print a warning if config.action_controller.asset_host is a Proc with 2 args

Member

guilleiguaran commented Sep 15, 2011

Maybe revert and print a warning if config.action_controller.asset_host is a Proc with 2 args

@josh-m-sharpe

This comment has been minimized.

Show comment
Hide comment
@josh-m-sharpe

josh-m-sharpe Sep 15, 2011

Contributor

So... we should probably get this issue reopened?

Contributor

josh-m-sharpe commented Sep 15, 2011

So... we should probably get this issue reopened?

@josh-m-sharpe

This comment has been minimized.

Show comment
Hide comment
@josh-m-sharpe

josh-m-sharpe Sep 16, 2011

Contributor

@cgriego this has been reverted.

#3040

Contributor

josh-m-sharpe commented Sep 16, 2011

@cgriego this has been reverted.

#3040

@cgriego

This comment has been minimized.

Show comment
Hide comment
@cgriego

cgriego Sep 16, 2011

Contributor

Thanks everyone!

Contributor

cgriego commented Sep 16, 2011

Thanks everyone!

@ghost

This comment has been minimized.

Show comment
Hide comment
@ghost

ghost Aug 16, 2012

Is this issue resolved?

I am currently in the same situation where I dont need absolute url of image but the image-url adds asset_host.
My asset_host is different for a http request and https request, but the compilation always returns a url having http asset host.

config.action_controller.asset_host = Proc.new do |source, request|
method = request.ssl? ? "https" : "http"
"#{method}://#{ENV['FOG_DIRECTORY']}.cloudfront.com"
end

Anyone in same situation?

ghost commented Aug 16, 2012

Is this issue resolved?

I am currently in the same situation where I dont need absolute url of image but the image-url adds asset_host.
My asset_host is different for a http request and https request, but the compilation always returns a url having http asset host.

config.action_controller.asset_host = Proc.new do |source, request|
method = request.ssl? ? "https" : "http"
"#{method}://#{ENV['FOG_DIRECTORY']}.cloudfront.com"
end

Anyone in same situation?

@nextofsearch

This comment has been minimized.

Show comment
Hide comment
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment