cloudfront_asset_host 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +1 -0
- data/MIT-LICENSE +20 -0
- data/README.markdown +61 -0
- data/Rakefile +39 -0
- data/VERSION +1 -0
- data/cloudfront_asset_host.gemspec +64 -0
- data/lib/cloudfront_asset_host.rb +103 -0
- data/lib/cloudfront_asset_host/asset_tag_helper_ext.rb +37 -0
- data/lib/cloudfront_asset_host/css_rewriter.rb +65 -0
- data/lib/cloudfront_asset_host/mime_types.yml +151 -0
- data/lib/cloudfront_asset_host/uploader.rb +124 -0
- data/test/app/config/s3.yml +5 -0
- data/test/app/public/images/image.png +0 -0
- data/test/app/public/javascripts/application.js +1 -0
- data/test/app/public/stylesheets/style.css +4 -0
- data/test/cloudfront_asset_host_test.rb +104 -0
- data/test/css_rewriter_test.rb +28 -0
- data/test/test_helper.rb +26 -0
- data/test/uploader_test.rb +113 -0
- metadata +94 -0
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
pkg
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Menno van der Sman
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
# CloudFront AssetHost
|
2
|
+
|
3
|
+
Easy deployment of your assets on CloudFront or S3. When enabled in production, your assets will be served from Cloudfront/S3 which will result in a speedier front-end.
|
4
|
+
|
5
|
+
## Installing
|
6
|
+
|
7
|
+
Include the gem in your app's `environment.rb` or Gemfile. It is hosted at Gemcutter[http://gemcutter.org/gems/cloudfront_asset_host]
|
8
|
+
|
9
|
+
### Dependencies
|
10
|
+
|
11
|
+
Make sure your s3-credentials are stored in _config/s3.yml_ like this:
|
12
|
+
|
13
|
+
access_key_id: 'access_key'
|
14
|
+
secret_access_key: 'secret'
|
15
|
+
|
16
|
+
The gem relies on +openssl md5+ and +gzip+ utilities. Make sure they are available locally and on your servers.
|
17
|
+
|
18
|
+
### Configuration
|
19
|
+
Create an initializer to configure the plugin _config/initializers/cloudfront_asset_host.rb_
|
20
|
+
|
21
|
+
# Simple configuration
|
22
|
+
CloudfrontAssetHost.configure do |config|
|
23
|
+
config.bucket = "bucketname" # required
|
24
|
+
config.enabled = true if Rails.env.production? # only enable in production
|
25
|
+
end
|
26
|
+
|
27
|
+
# Extended configuration
|
28
|
+
CloudfrontAssetHost.configure do |config|
|
29
|
+
config.bucket = "bucketname" # required
|
30
|
+
config.cname = "assets.domain.com" # if you have a cname configured for your distribution or bucket
|
31
|
+
config.key_prefix = "app/" # if you share the bucket and want to keep things separated
|
32
|
+
config.s3_config = "#{RAILS_ROOT}/config/s3.yml" # Alternative location of your s3-config file
|
33
|
+
|
34
|
+
# gzip related configuration
|
35
|
+
config.gzip = true # enable gzipped assets (defaults to true)
|
36
|
+
config.gzip_extensions = ['js', 'css'] # only gzip javascript or css (defaults to %w(js css))
|
37
|
+
config.gzip_prefix = "gz" # prefix for gzipped bucket (defaults to "gz")
|
38
|
+
|
39
|
+
config.enabled = true if Rails.env.production? # only enable in production
|
40
|
+
end
|
41
|
+
|
42
|
+
## Usage
|
43
|
+
|
44
|
+
### Uploading your assets
|
45
|
+
Run `CloudfrontAssetHost::Uploader.upload!(:verbose => true, :dryrun => false)` before your deployment. Put it for example in your Rakefile or capistrano-recipe. Verbose output will include information about which keys are being uploaded. Enabling _dryrun_ will skip the actual upload if you're just interested to see what will be uploaded.
|
46
|
+
|
47
|
+
### Hooks
|
48
|
+
If the plugin is enabled. Rails' internal `asset_host` and `asset_id` functionality will be overridden to point to the location of the assets on Cloudfront.
|
49
|
+
|
50
|
+
### Other plugins
|
51
|
+
When using in combination with SASS and/or asset_packager it is recommended to generate the css-files and package your assets before uploading them to Cloudfront. For example, call `Sass::Plugin.update_stylesheets` and `Synthesis::AssetPackage.build_all` first.
|
52
|
+
|
53
|
+
## Compatibility
|
54
|
+
|
55
|
+
Tested on Rails 2.3.5 with SASS and AssetPackager plugins
|
56
|
+
|
57
|
+
## Copyright
|
58
|
+
|
59
|
+
Created at Wakoopa
|
60
|
+
|
61
|
+
Copyright (c) 2010 Menno van der Sman, released under the MIT license
|
data/Rakefile
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
|
5
|
+
desc 'Default: run unit tests.'
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
desc 'Test the cloudfront_asset_host plugin.'
|
9
|
+
Rake::TestTask.new(:test) do |t|
|
10
|
+
t.libs << 'lib'
|
11
|
+
t.libs << 'test'
|
12
|
+
t.pattern = 'test/**/*_test.rb'
|
13
|
+
t.verbose = true
|
14
|
+
end
|
15
|
+
|
16
|
+
desc 'Generate documentation for the cloudfront_asset_host plugin.'
|
17
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
18
|
+
rdoc.rdoc_dir = 'rdoc'
|
19
|
+
rdoc.title = 'CloudfrontAssetHost'
|
20
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
21
|
+
rdoc.rdoc_files.include('README')
|
22
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
23
|
+
end
|
24
|
+
|
25
|
+
begin
|
26
|
+
require 'jeweler'
|
27
|
+
Jeweler::Tasks.new do |gemspec|
|
28
|
+
gemspec.name = "cloudfront_asset_host"
|
29
|
+
gemspec.summary = "Rails plugin to easily and efficiently deploy your assets on Amazon's S3 or CloudFront"
|
30
|
+
gemspec.description = "Easy deployment of your assets on CloudFront or S3 using a simple rake-task. When enabled in production, the application's asset_host and public_paths will point to the correct location."
|
31
|
+
gemspec.email = "menno@wakoopa.com"
|
32
|
+
gemspec.homepage = "http://github.com/menno/cloudfront_asset_host"
|
33
|
+
gemspec.authors = ["Menno van der Sman"]
|
34
|
+
gemspec.add_dependency 'right_aws'
|
35
|
+
end
|
36
|
+
Jeweler::GemcutterTasks.new
|
37
|
+
rescue LoadError
|
38
|
+
puts "Jeweler not available. Install it with: sudo gem install jeweler"
|
39
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.0.0
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{cloudfront_asset_host}
|
8
|
+
s.version = "1.0.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Menno van der Sman"]
|
12
|
+
s.date = %q{2010-03-18}
|
13
|
+
s.description = %q{Easy deployment of your assets on CloudFront or S3 using a simple rake-task. When enabled in production, the application's asset_host and public_paths will point to the correct location.}
|
14
|
+
s.email = %q{menno@wakoopa.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"README.markdown"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
".gitignore",
|
20
|
+
"MIT-LICENSE",
|
21
|
+
"README.markdown",
|
22
|
+
"Rakefile",
|
23
|
+
"VERSION",
|
24
|
+
"cloudfront_asset_host.gemspec",
|
25
|
+
"lib/cloudfront_asset_host.rb",
|
26
|
+
"lib/cloudfront_asset_host/asset_tag_helper_ext.rb",
|
27
|
+
"lib/cloudfront_asset_host/css_rewriter.rb",
|
28
|
+
"lib/cloudfront_asset_host/mime_types.yml",
|
29
|
+
"lib/cloudfront_asset_host/uploader.rb",
|
30
|
+
"test/app/config/s3.yml",
|
31
|
+
"test/app/public/images/image.png",
|
32
|
+
"test/app/public/javascripts/application.js",
|
33
|
+
"test/app/public/stylesheets/style.css",
|
34
|
+
"test/cloudfront_asset_host_test.rb",
|
35
|
+
"test/css_rewriter_test.rb",
|
36
|
+
"test/test_helper.rb",
|
37
|
+
"test/uploader_test.rb"
|
38
|
+
]
|
39
|
+
s.homepage = %q{http://github.com/menno/cloudfront_asset_host}
|
40
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
41
|
+
s.require_paths = ["lib"]
|
42
|
+
s.rubygems_version = %q{1.3.6}
|
43
|
+
s.summary = %q{Rails plugin to easily and efficiently deploy your assets on Amazon's S3 or CloudFront}
|
44
|
+
s.test_files = [
|
45
|
+
"test/cloudfront_asset_host_test.rb",
|
46
|
+
"test/css_rewriter_test.rb",
|
47
|
+
"test/test_helper.rb",
|
48
|
+
"test/uploader_test.rb"
|
49
|
+
]
|
50
|
+
|
51
|
+
if s.respond_to? :specification_version then
|
52
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
53
|
+
s.specification_version = 3
|
54
|
+
|
55
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
56
|
+
s.add_runtime_dependency(%q<right_aws>, [">= 0"])
|
57
|
+
else
|
58
|
+
s.add_dependency(%q<right_aws>, [">= 0"])
|
59
|
+
end
|
60
|
+
else
|
61
|
+
s.add_dependency(%q<right_aws>, [">= 0"])
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'cloudfront_asset_host/asset_tag_helper_ext'
|
2
|
+
|
3
|
+
module CloudfrontAssetHost
|
4
|
+
|
5
|
+
autoload :Uploader, 'cloudfront_asset_host/uploader'
|
6
|
+
autoload :CssRewriter, 'cloudfront_asset_host/css_rewriter'
|
7
|
+
|
8
|
+
# Bucket that will be used to store all the assets (required)
|
9
|
+
mattr_accessor :bucket
|
10
|
+
|
11
|
+
# CNAME that is configured for the bucket or CloudFront distribution
|
12
|
+
mattr_accessor :cname
|
13
|
+
|
14
|
+
# Prefix keys
|
15
|
+
mattr_accessor :key_prefix
|
16
|
+
|
17
|
+
# Path to S3 config. Expects an +access_key_id+ and +secret_access_key+
|
18
|
+
mattr_accessor :s3_config
|
19
|
+
|
20
|
+
# Indicates whether the plugin should be enabled
|
21
|
+
mattr_accessor :enabled
|
22
|
+
|
23
|
+
# Upload gzipped assets and serve those assets when applicable
|
24
|
+
mattr_accessor :gzip
|
25
|
+
|
26
|
+
# Which extensions to serve as gzip
|
27
|
+
mattr_accessor :gzip_extensions
|
28
|
+
|
29
|
+
# Key-prefix under which to store gzipped assets
|
30
|
+
mattr_accessor :gzip_prefix
|
31
|
+
|
32
|
+
class << self
|
33
|
+
|
34
|
+
def configure
|
35
|
+
# default configuration
|
36
|
+
self.bucket = nil
|
37
|
+
self.cname = nil
|
38
|
+
self.key_prefix = ""
|
39
|
+
self.s3_config = "#{RAILS_ROOT}/config/s3.yml"
|
40
|
+
self.enabled = false
|
41
|
+
|
42
|
+
self.gzip = true
|
43
|
+
self.gzip_extensions = %w(js css)
|
44
|
+
self.gzip_prefix = "gz"
|
45
|
+
|
46
|
+
yield(self)
|
47
|
+
|
48
|
+
if properly_configured?
|
49
|
+
enable!
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def asset_host(source = nil, request = nil)
|
54
|
+
host = cname.present? ? "http://#{self.cname}" : "http://#{self.bucket_host}"
|
55
|
+
|
56
|
+
if source && request && CloudfrontAssetHost.gzip
|
57
|
+
gzip_allowed = CloudfrontAssetHost.gzip_allowed_for_source?(source)
|
58
|
+
gzip_accepted = !(request.headers['User-Agent'].to_s =~ /(Mozilla\/4\.0[678])|(MSIE\s[1-6])/) && request.headers['Accept-Encoding'].to_s.include?('gzip')
|
59
|
+
|
60
|
+
if gzip_accepted && gzip_allowed
|
61
|
+
host << "/#{CloudfrontAssetHost.gzip_prefix}"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
host
|
66
|
+
end
|
67
|
+
|
68
|
+
def bucket_host
|
69
|
+
"#{self.bucket}.s3.amazonaws.com"
|
70
|
+
end
|
71
|
+
|
72
|
+
def enable!
|
73
|
+
if enabled
|
74
|
+
ActionController::Base.asset_host = Proc.new { |source, request| CloudfrontAssetHost.asset_host(source, request) }
|
75
|
+
ActionView::Helpers::AssetTagHelper.send(:alias_method_chain, :rewrite_asset_path, :cloudfront)
|
76
|
+
ActionView::Helpers::AssetTagHelper.send(:alias_method_chain, :rails_asset_id, :cloudfront)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def key_for_path(path)
|
81
|
+
key_prefix + md5sum(path)[0..8]
|
82
|
+
end
|
83
|
+
|
84
|
+
def gzip_allowed_for_source?(source)
|
85
|
+
extension = source.split('.').last
|
86
|
+
CloudfrontAssetHost.gzip_extensions.include?(extension)
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def properly_configured?
|
92
|
+
raise "You'll need to specify a bucket" if bucket.blank?
|
93
|
+
raise "Could not find S3-configuration" unless File.exists?(s3_config)
|
94
|
+
true
|
95
|
+
end
|
96
|
+
|
97
|
+
def md5sum(path)
|
98
|
+
`openssl md5 #{path}`.split(/\s/)[1].to_s
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module ActionView
|
2
|
+
module Helpers
|
3
|
+
module AssetTagHelper
|
4
|
+
|
5
|
+
private
|
6
|
+
|
7
|
+
# Override asset_id so it calculates the key by md5 instead of modified-time
|
8
|
+
def rails_asset_id_with_cloudfront(source)
|
9
|
+
if @@cache_asset_timestamps && (asset_id = @@asset_timestamps_cache[source])
|
10
|
+
asset_id
|
11
|
+
else
|
12
|
+
path = File.join(ASSETS_DIR, source)
|
13
|
+
asset_id = File.exist?(path) ? CloudfrontAssetHost.key_for_path(path) : ''
|
14
|
+
|
15
|
+
if @@cache_asset_timestamps
|
16
|
+
@@asset_timestamps_cache_guard.synchronize do
|
17
|
+
@@asset_timestamps_cache[source] = asset_id
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
asset_id
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Override asset_path so it prepends the asset_id
|
26
|
+
def rewrite_asset_path_with_cloudfront(source)
|
27
|
+
asset_id = rails_asset_id(source)
|
28
|
+
if asset_id.blank?
|
29
|
+
source
|
30
|
+
else
|
31
|
+
"/#{asset_id}#{source}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
|
3
|
+
module CloudfrontAssetHost
|
4
|
+
module CssRewriter
|
5
|
+
|
6
|
+
# Location of the stylesheets directory
|
7
|
+
mattr_accessor :stylesheets_dir
|
8
|
+
self.stylesheets_dir = File.join(Rails.public_path, 'stylesheets')
|
9
|
+
|
10
|
+
class << self
|
11
|
+
# matches optional quoted url(<path>)
|
12
|
+
ReplaceRexeg = /url\(["']?([^\)"']+)["']?\)/i
|
13
|
+
|
14
|
+
# Returns the path to the temporary file that contains the
|
15
|
+
# rewritten stylesheet
|
16
|
+
def rewrite_stylesheet(path)
|
17
|
+
contents = File.read(path)
|
18
|
+
contents.gsub!(ReplaceRexeg) do |match|
|
19
|
+
rewrite_asset_link(match, path)
|
20
|
+
end
|
21
|
+
|
22
|
+
tmp = Tempfile.new("cfah-css")
|
23
|
+
tmp.write(contents)
|
24
|
+
tmp.flush
|
25
|
+
tmp
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def rewrite_asset_link(asset_link, stylesheet_path)
|
31
|
+
url = asset_link.match(ReplaceRexeg)[1]
|
32
|
+
if url
|
33
|
+
path = path_for_url(url, stylesheet_path)
|
34
|
+
|
35
|
+
if path.present? && File.exists?(path)
|
36
|
+
key = CloudfrontAssetHost.key_for_path(path) + path.gsub(Rails.public_path, '')
|
37
|
+
"url(#{CloudfrontAssetHost.asset_host}/#{key})"
|
38
|
+
else
|
39
|
+
puts "Could not extract path: #{path}"
|
40
|
+
asset_link
|
41
|
+
end
|
42
|
+
else
|
43
|
+
puts "Could not find url in #{asset_link}"
|
44
|
+
asset_link
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def path_for_url(url, stylesheet_path)
|
49
|
+
if url.starts_with?('/')
|
50
|
+
# absolute to public path
|
51
|
+
File.expand_path(File.join(Rails.public_path, url))
|
52
|
+
else
|
53
|
+
# relative to stylesheet_path
|
54
|
+
File.expand_path(File.join(File.dirname(stylesheet_path), url))
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def stylesheets_to_rewrite
|
59
|
+
Dir.glob("#{stylesheets_dir}/**/*.css")
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,151 @@
|
|
1
|
+
"text/html":
|
2
|
+
- html
|
3
|
+
- htm
|
4
|
+
- shtml
|
5
|
+
"text/css":
|
6
|
+
- css
|
7
|
+
"text/xml":
|
8
|
+
- xml
|
9
|
+
- rss
|
10
|
+
"image/gif":
|
11
|
+
- gif
|
12
|
+
"image/jpeg":
|
13
|
+
- jpeg
|
14
|
+
- jpg
|
15
|
+
"application/x-javascript":
|
16
|
+
- js
|
17
|
+
"application/atom+xml":
|
18
|
+
- atom
|
19
|
+
"text/mathml":
|
20
|
+
- mml
|
21
|
+
"text/plain":
|
22
|
+
- txt
|
23
|
+
"text/vnd.sun.j2me.app-descriptor":
|
24
|
+
- jad
|
25
|
+
"text/vnd.wap.wml":
|
26
|
+
- wml
|
27
|
+
"text/x-component":
|
28
|
+
- htc
|
29
|
+
"image/png":
|
30
|
+
- png
|
31
|
+
"image/tiff":
|
32
|
+
- tif
|
33
|
+
- tiff
|
34
|
+
"image/vnd.wap.wbmp":
|
35
|
+
- wbmp
|
36
|
+
"image/x-icon":
|
37
|
+
- ico
|
38
|
+
"image/x-jng":
|
39
|
+
- jng
|
40
|
+
"image/x-ms-bmp":
|
41
|
+
- bmp
|
42
|
+
"image/svg+xml":
|
43
|
+
- svg
|
44
|
+
"application/java-archive":
|
45
|
+
- jar
|
46
|
+
- war
|
47
|
+
- ear
|
48
|
+
"application/mac-binhex40":
|
49
|
+
- hqx
|
50
|
+
"application/msword":
|
51
|
+
- doc
|
52
|
+
"application/pdf":
|
53
|
+
- pdf
|
54
|
+
"application/postscript":
|
55
|
+
- ps
|
56
|
+
- eps
|
57
|
+
- ai
|
58
|
+
"application/rtf":
|
59
|
+
- rtf
|
60
|
+
"application/vnd.ms-excel":
|
61
|
+
- xls
|
62
|
+
"application/vnd.ms-powerpoint":
|
63
|
+
- ppt
|
64
|
+
"application/vnd.wap.wmlc":
|
65
|
+
- wmlc
|
66
|
+
"application/vnd.wap.xhtml+xml":
|
67
|
+
- xhtml
|
68
|
+
"application/x-cocoa":
|
69
|
+
- cco
|
70
|
+
"application/x-java-archive-diff":
|
71
|
+
- jardiff
|
72
|
+
"application/x-java-jnlp-file":
|
73
|
+
- jnlp
|
74
|
+
"application/x-makeself":
|
75
|
+
- run
|
76
|
+
"application/x-perl":
|
77
|
+
- pl
|
78
|
+
- pm
|
79
|
+
"application/x-pilot":
|
80
|
+
- prc
|
81
|
+
- pdb
|
82
|
+
"application/x-rar-compressed":
|
83
|
+
- rar
|
84
|
+
"application/x-redhat-package-manager":
|
85
|
+
- rpm
|
86
|
+
"application/x-sea":
|
87
|
+
- sea
|
88
|
+
"application/x-shockwave-flash":
|
89
|
+
- swf
|
90
|
+
"application/x-stuffit":
|
91
|
+
- sit
|
92
|
+
"application/x-tcl":
|
93
|
+
- tcl
|
94
|
+
- tk
|
95
|
+
"application/x-x509-ca-cert":
|
96
|
+
- der
|
97
|
+
- pem
|
98
|
+
- crt
|
99
|
+
"application/x-xpinstall":
|
100
|
+
- xpi
|
101
|
+
"application/zip":
|
102
|
+
- zip
|
103
|
+
"application/octet-stream":
|
104
|
+
- bin
|
105
|
+
- exe
|
106
|
+
- dll
|
107
|
+
"application/octet-stream":
|
108
|
+
- deb
|
109
|
+
"application/octet-stream":
|
110
|
+
- dmg
|
111
|
+
"application/octet-stream":
|
112
|
+
- eot
|
113
|
+
"application/octet-stream":
|
114
|
+
- iso
|
115
|
+
- img
|
116
|
+
"application/octet-stream":
|
117
|
+
- msi
|
118
|
+
- msp
|
119
|
+
- msm
|
120
|
+
"audio/midi":
|
121
|
+
- mid
|
122
|
+
- midi
|
123
|
+
- kar
|
124
|
+
"audio/mpeg":
|
125
|
+
- mp3
|
126
|
+
"audio/x-realaudio":
|
127
|
+
- ra
|
128
|
+
"video/3gpp":
|
129
|
+
- 3gpp
|
130
|
+
- 3gp
|
131
|
+
"video/mpeg":
|
132
|
+
- mpeg
|
133
|
+
- mpg
|
134
|
+
"video/quicktime":
|
135
|
+
- mov
|
136
|
+
"video/x-flv":
|
137
|
+
- flv
|
138
|
+
"video/x-mng":
|
139
|
+
- mng
|
140
|
+
"video/x-ms-asf":
|
141
|
+
- asx
|
142
|
+
- asf
|
143
|
+
"video/x-ms-wmv":
|
144
|
+
- wmv
|
145
|
+
"video/x-msvideo":
|
146
|
+
- avi
|
147
|
+
"text/plain":
|
148
|
+
- py
|
149
|
+
- php
|
150
|
+
- config
|
151
|
+
- txt
|
@@ -0,0 +1,124 @@
|
|
1
|
+
require 'right_aws'
|
2
|
+
require 'tempfile'
|
3
|
+
|
4
|
+
module CloudfrontAssetHost
|
5
|
+
module Uploader
|
6
|
+
|
7
|
+
class << self
|
8
|
+
|
9
|
+
def upload!(options = {})
|
10
|
+
dryrun = options.delete(:dryrun) || false
|
11
|
+
verbose = options.delete(:verbose) || false
|
12
|
+
|
13
|
+
puts "-- Updating uncompressed files" if verbose
|
14
|
+
upload_keys_with_paths(keys_with_paths, dryrun, verbose, false)
|
15
|
+
|
16
|
+
if CloudfrontAssetHost.gzip
|
17
|
+
puts "-- Updating compressed files" if verbose
|
18
|
+
upload_keys_with_paths(gzip_keys_with_paths, dryrun, verbose, true)
|
19
|
+
end
|
20
|
+
|
21
|
+
@existing_keys = nil
|
22
|
+
end
|
23
|
+
|
24
|
+
def upload_keys_with_paths(keys_paths, dryrun, verbose, gzip)
|
25
|
+
keys_paths.each do |key, path|
|
26
|
+
if existing_keys.include?(key)
|
27
|
+
puts "= #{key}" if verbose
|
28
|
+
else
|
29
|
+
puts "+ #{key}" if verbose
|
30
|
+
|
31
|
+
extension = File.extname(path)[1..-1]
|
32
|
+
|
33
|
+
path = rewritten_css_path(path)
|
34
|
+
|
35
|
+
data_path = gzip ? gzipped_path(path) : path
|
36
|
+
bucket.put(key, File.read(data_path), {}, 'public-read', headers_for_path(extension, gzip)) unless dryrun
|
37
|
+
|
38
|
+
File.unlink(data_path) if gzip && File.exists?(data_path)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def gzipped_path(path)
|
44
|
+
tmp = Tempfile.new("cfah-gz")
|
45
|
+
`gzip #{path} -q -c > #{tmp.path}`
|
46
|
+
tmp.path
|
47
|
+
end
|
48
|
+
|
49
|
+
def rewritten_css_path(path)
|
50
|
+
if File.extname(path) == '.css'
|
51
|
+
tmp = CloudfrontAssetHost::CssRewriter.rewrite_stylesheet(path)
|
52
|
+
tmp.path
|
53
|
+
else
|
54
|
+
path
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def keys_with_paths
|
59
|
+
current_paths.inject({}) do |result, path|
|
60
|
+
key = CloudfrontAssetHost.key_for_path(path) + path.gsub(Rails.public_path, '')
|
61
|
+
|
62
|
+
result[key] = path
|
63
|
+
result
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def gzip_keys_with_paths
|
68
|
+
current_paths.inject({}) do |result, path|
|
69
|
+
source = path.gsub(Rails.public_path, '')
|
70
|
+
|
71
|
+
if CloudfrontAssetHost.gzip_allowed_for_source?(source)
|
72
|
+
key = "#{CloudfrontAssetHost.gzip_prefix}/" << CloudfrontAssetHost.key_for_path(path) << source
|
73
|
+
result[key] = path
|
74
|
+
end
|
75
|
+
|
76
|
+
result
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def existing_keys
|
81
|
+
@existing_keys ||= begin
|
82
|
+
keys = []
|
83
|
+
keys.concat bucket.keys('prefix' => CloudfrontAssetHost.key_prefix).map { |key| key.name }
|
84
|
+
keys.concat bucket.keys('prefix' => CloudfrontAssetHost.gzip_prefix).map { |key| key.name }
|
85
|
+
keys
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def current_paths
|
90
|
+
@current_paths ||= Dir.glob("#{Rails.public_path}/{images,javascripts,stylesheets}/**/*").reject { |path| File.directory?(path) }
|
91
|
+
end
|
92
|
+
|
93
|
+
def headers_for_path(extension, gzip = false)
|
94
|
+
mime = ext_to_mime[extension] || 'application/octet-stream'
|
95
|
+
headers = {
|
96
|
+
'Content-Type' => mime,
|
97
|
+
'Cache-Control' => "max-age=#{10.years.to_i}",
|
98
|
+
'Expires' => 1.year.from_now.utc.to_s
|
99
|
+
}
|
100
|
+
headers['Content-Encoding'] = 'gzip' if gzip
|
101
|
+
|
102
|
+
headers
|
103
|
+
end
|
104
|
+
|
105
|
+
def ext_to_mime
|
106
|
+
@ext_to_mime ||= Hash[ *( YAML::load_file(File.join(File.dirname(__FILE__), "mime_types.yml")).collect { |k,vv| vv.collect{ |v| [v,k] } }.flatten ) ]
|
107
|
+
end
|
108
|
+
|
109
|
+
def bucket
|
110
|
+
@bucket ||= s3.bucket(CloudfrontAssetHost.bucket)
|
111
|
+
end
|
112
|
+
|
113
|
+
def s3
|
114
|
+
@s3 ||= RightAws::S3.new(config['access_key_id'], config['secret_access_key'])
|
115
|
+
end
|
116
|
+
|
117
|
+
def config
|
118
|
+
@config ||= YAML::load_file(CloudfrontAssetHost.s3_config)
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
end
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
// Javascripts here
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class CloudfrontAssetHostTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
context "A configured plugin" do
|
6
|
+
setup do
|
7
|
+
CloudfrontAssetHost.configure do |config|
|
8
|
+
config.cname = "assethost.com"
|
9
|
+
config.bucket = "bucketname"
|
10
|
+
config.key_prefix = ""
|
11
|
+
config.enabled = false
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
should "add methods to asset-tag-helper" do
|
16
|
+
assert ActionView::Helpers::AssetTagHelper.private_method_defined?('rails_asset_id_with_cloudfront')
|
17
|
+
assert ActionView::Helpers::AssetTagHelper.private_method_defined?('rewrite_asset_path_with_cloudfront')
|
18
|
+
end
|
19
|
+
|
20
|
+
should "not enable itself by default" do
|
21
|
+
assert_equal false, CloudfrontAssetHost.enabled
|
22
|
+
assert_equal "", ActionController::Base.asset_host
|
23
|
+
end
|
24
|
+
|
25
|
+
should "return key for path" do
|
26
|
+
assert_equal "8ed41cb87", CloudfrontAssetHost.key_for_path(File.join(RAILS_ROOT, 'public', 'javascripts', 'application.js'))
|
27
|
+
end
|
28
|
+
|
29
|
+
should "prepend prefix to key" do
|
30
|
+
CloudfrontAssetHost.key_prefix = "prefix/"
|
31
|
+
assert_equal "prefix/8ed41cb87", CloudfrontAssetHost.key_for_path(File.join(RAILS_ROOT, 'public', 'javascripts', 'application.js'))
|
32
|
+
end
|
33
|
+
|
34
|
+
context "asset-host" do
|
35
|
+
|
36
|
+
setup do
|
37
|
+
@gzip_request = stub(:headers => {'Accept-Encoding' => 'gzip, compress'})
|
38
|
+
@request = stub(:headers => {})
|
39
|
+
@img_source = "/images/logo.png"
|
40
|
+
@js_source = "/javascripts/application.js"
|
41
|
+
end
|
42
|
+
|
43
|
+
should "use cname for asset_host" do
|
44
|
+
assert_equal "http://assethost.com", CloudfrontAssetHost.asset_host(@img_source, @request)
|
45
|
+
end
|
46
|
+
|
47
|
+
should "use bucket_host when cname is not present" do
|
48
|
+
CloudfrontAssetHost.cname = nil
|
49
|
+
assert_equal "http://bucketname.s3.amazonaws.com", CloudfrontAssetHost.asset_host(@img_source, @request)
|
50
|
+
end
|
51
|
+
|
52
|
+
should "add gz to asset_host when applicable" do
|
53
|
+
assert_equal "http://assethost.com/gz", CloudfrontAssetHost.asset_host(@js_source, @gzip_request)
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context "An enabled and configured plugin" do
|
60
|
+
setup do
|
61
|
+
CloudfrontAssetHost.configure do |config|
|
62
|
+
config.enabled = true
|
63
|
+
config.cname = "assethost.com"
|
64
|
+
config.bucket = "bucketname"
|
65
|
+
config.key_prefix = ""
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
should "set the asset_host" do
|
70
|
+
assert ActionController::Base.asset_host.is_a?(Proc)
|
71
|
+
end
|
72
|
+
|
73
|
+
should "alias methods in asset-tag-helper" do
|
74
|
+
assert ActionView::Helpers::AssetTagHelper.private_method_defined?('rails_asset_id_without_cloudfront')
|
75
|
+
assert ActionView::Helpers::AssetTagHelper.private_method_defined?('rewrite_asset_path_without_cloudfront')
|
76
|
+
assert ActionView::Helpers::AssetTagHelper.private_method_defined?('rails_asset_id')
|
77
|
+
assert ActionView::Helpers::AssetTagHelper.private_method_defined?('rewrite_asset_path')
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
context "An improperly configured plugin" do
|
82
|
+
should "complain about bucket not being set" do
|
83
|
+
assert_raise(RuntimeError) {
|
84
|
+
CloudfrontAssetHost.configure do |config|
|
85
|
+
config.enabled = false
|
86
|
+
config.cname = "assethost.com"
|
87
|
+
config.bucket = nil
|
88
|
+
end
|
89
|
+
}
|
90
|
+
end
|
91
|
+
|
92
|
+
should "complain about missing s3-config" do
|
93
|
+
assert_raise(RuntimeError) {
|
94
|
+
CloudfrontAssetHost.configure do |config|
|
95
|
+
config.enabled = false
|
96
|
+
config.cname = "assethost.com"
|
97
|
+
config.bucket = "bucketname"
|
98
|
+
config.s3_config = "bogus"
|
99
|
+
end
|
100
|
+
}
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class CssRewriterTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
context "The CssRewriter" do
|
6
|
+
|
7
|
+
setup do
|
8
|
+
CloudfrontAssetHost.configure do |config|
|
9
|
+
config.cname = "assethost.com"
|
10
|
+
config.bucket = "bucketname"
|
11
|
+
config.key_prefix = ""
|
12
|
+
config.enabled = false
|
13
|
+
end
|
14
|
+
|
15
|
+
@stylesheet_path = File.join(Rails.public_path, 'stylesheets', 'style.css')
|
16
|
+
end
|
17
|
+
|
18
|
+
should "rewrite a single css file" do
|
19
|
+
tmp = CloudfrontAssetHost::CssRewriter.rewrite_stylesheet(@stylesheet_path)
|
20
|
+
contents = File.read(tmp.path)
|
21
|
+
contents.split("\n").each do |line|
|
22
|
+
assert_equal "body { background-image: url(http://assethost.com/d41d8cd98/images/image.png); }", line
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'rubygems'
|
3
|
+
|
4
|
+
require 'action_controller'
|
5
|
+
require 'right_aws'
|
6
|
+
|
7
|
+
require 'shoulda'
|
8
|
+
require 'mocha'
|
9
|
+
begin require 'redgreen'; rescue LoadError; end
|
10
|
+
begin require 'turn'; rescue LoadError; end
|
11
|
+
|
12
|
+
RAILS_ROOT = File.expand_path(File.join(File.dirname(__FILE__), 'app'))
|
13
|
+
|
14
|
+
module Rails
|
15
|
+
class << self
|
16
|
+
def root
|
17
|
+
RAILS_ROOT
|
18
|
+
end
|
19
|
+
|
20
|
+
def public_path
|
21
|
+
File.join(RAILS_ROOT, 'public')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'cloudfront_asset_host')
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class UploaderTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
context "A configured uploader" do
|
6
|
+
setup do
|
7
|
+
CloudfrontAssetHost.configure do |config|
|
8
|
+
config.cname = "assethost.com"
|
9
|
+
config.bucket = "bucketname"
|
10
|
+
config.key_prefix = ""
|
11
|
+
config.s3_config = "#{RAILS_ROOT}/config/s3.yml"
|
12
|
+
config.enabled = false
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
should "be able to retrieve s3-config" do
|
17
|
+
config = CloudfrontAssetHost::Uploader.config
|
18
|
+
assert_equal 'access_key', config['access_key_id']
|
19
|
+
assert_equal 'secret', config['secret_access_key']
|
20
|
+
end
|
21
|
+
|
22
|
+
should "be able to instantiate s3-interface" do
|
23
|
+
RightAws::S3.expects(:new).with('access_key', 'secret').returns(mock)
|
24
|
+
assert_not_nil CloudfrontAssetHost::Uploader.s3
|
25
|
+
end
|
26
|
+
|
27
|
+
should "glob current files" do
|
28
|
+
assert_equal 3, CloudfrontAssetHost::Uploader.current_paths.length
|
29
|
+
end
|
30
|
+
|
31
|
+
should "calculate keys for paths" do
|
32
|
+
keys_with_paths = CloudfrontAssetHost::Uploader.keys_with_paths
|
33
|
+
assert_equal 3, keys_with_paths.length
|
34
|
+
assert_match %r{/test/app/public/javascripts/application\.js$}, keys_with_paths["8ed41cb87/javascripts/application.js"]
|
35
|
+
end
|
36
|
+
|
37
|
+
should "calculate gzip keys for paths" do
|
38
|
+
gz_keys_with_paths = CloudfrontAssetHost::Uploader.gzip_keys_with_paths
|
39
|
+
assert_equal 2, gz_keys_with_paths.length
|
40
|
+
assert_match %r{/test/app/public/javascripts/application\.js$}, gz_keys_with_paths["gz/8ed41cb87/javascripts/application.js"]
|
41
|
+
assert_match %r{/test/app/public/stylesheets/style\.css$}, gz_keys_with_paths["gz/bd258f13d/stylesheets/style.css"]
|
42
|
+
end
|
43
|
+
|
44
|
+
should "return a mimetype for an extension" do
|
45
|
+
assert_equal 'application/x-javascript', CloudfrontAssetHost::Uploader.ext_to_mime['js']
|
46
|
+
end
|
47
|
+
|
48
|
+
should "construct the headers for a path" do
|
49
|
+
headers = CloudfrontAssetHost::Uploader.headers_for_path('js')
|
50
|
+
assert_equal 'application/x-javascript', headers['Content-Type']
|
51
|
+
assert_match /max-age=\d+/, headers['Cache-Control']
|
52
|
+
assert DateTime.parse(headers['Expires'])
|
53
|
+
end
|
54
|
+
|
55
|
+
should "add gzip-header" do
|
56
|
+
headers = CloudfrontAssetHost::Uploader.headers_for_path('js', true)
|
57
|
+
assert_equal 'application/x-javascript', headers['Content-Type']
|
58
|
+
assert_equal 'gzip', headers['Content-Encoding']
|
59
|
+
assert_match /max-age=\d+/, headers['Cache-Control']
|
60
|
+
assert DateTime.parse(headers['Expires'])
|
61
|
+
end
|
62
|
+
|
63
|
+
should "retrieve existing keys" do
|
64
|
+
bucket_mock = mock
|
65
|
+
bucket_mock.expects(:keys).with({'prefix' => ''}).returns([stub(:name => "keyname")])
|
66
|
+
bucket_mock.expects(:keys).with({'prefix' => 'gz'}).returns([stub(:name => "gz/keyname")])
|
67
|
+
|
68
|
+
CloudfrontAssetHost::Uploader.expects(:bucket).times(2).returns(bucket_mock)
|
69
|
+
assert_equal ["keyname", "gz/keyname"], CloudfrontAssetHost::Uploader.existing_keys
|
70
|
+
end
|
71
|
+
|
72
|
+
should "upload files when there are no existing keys" do
|
73
|
+
bucket_mock = mock
|
74
|
+
bucket_mock.expects(:put).times(5)
|
75
|
+
CloudfrontAssetHost::Uploader.stubs(:bucket).returns(bucket_mock)
|
76
|
+
CloudfrontAssetHost::Uploader.stubs(:existing_keys).returns([])
|
77
|
+
|
78
|
+
CloudfrontAssetHost::Uploader.upload!
|
79
|
+
end
|
80
|
+
|
81
|
+
should "not re-upload existing keys" do
|
82
|
+
CloudfrontAssetHost::Uploader.expects(:bucket).never
|
83
|
+
CloudfrontAssetHost::Uploader.stubs(:existing_keys).returns(
|
84
|
+
["gz/8ed41cb87/javascripts/application.js", "8ed41cb87/javascripts/application.js",
|
85
|
+
"d41d8cd98/images/image.png",
|
86
|
+
"bd258f13d/stylesheets/style.css", "gz/bd258f13d/stylesheets/style.css"]
|
87
|
+
)
|
88
|
+
|
89
|
+
CloudfrontAssetHost::Uploader.upload!
|
90
|
+
end
|
91
|
+
|
92
|
+
should "correctly gzip files" do
|
93
|
+
path = File.join(RAILS_ROOT, 'public', 'javascripts', 'application.js')
|
94
|
+
contents = File.read(path)
|
95
|
+
|
96
|
+
gz_path = CloudfrontAssetHost::Uploader.gzipped_path(path)
|
97
|
+
gunzip_contents = `gunzip #{gz_path} -q -c`
|
98
|
+
|
99
|
+
assert_equal contents, gunzip_contents
|
100
|
+
end
|
101
|
+
|
102
|
+
should "correctly rewrite css files" do
|
103
|
+
path = File.join(RAILS_ROOT, 'public', 'stylesheets', 'style.css')
|
104
|
+
css_path = CloudfrontAssetHost::Uploader.rewritten_css_path(path)
|
105
|
+
|
106
|
+
File.read(css_path).split("\n").each do |line|
|
107
|
+
assert_equal "body { background-image: url(http://assethost.com/d41d8cd98/images/image.png); }", line
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
metadata
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cloudfront_asset_host
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 1
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
version: 1.0.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Menno van der Sman
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-03-18 00:00:00 +01:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: right_aws
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
version: "0"
|
30
|
+
type: :runtime
|
31
|
+
version_requirements: *id001
|
32
|
+
description: Easy deployment of your assets on CloudFront or S3 using a simple rake-task. When enabled in production, the application's asset_host and public_paths will point to the correct location.
|
33
|
+
email: menno@wakoopa.com
|
34
|
+
executables: []
|
35
|
+
|
36
|
+
extensions: []
|
37
|
+
|
38
|
+
extra_rdoc_files:
|
39
|
+
- README.markdown
|
40
|
+
files:
|
41
|
+
- .gitignore
|
42
|
+
- MIT-LICENSE
|
43
|
+
- README.markdown
|
44
|
+
- Rakefile
|
45
|
+
- VERSION
|
46
|
+
- cloudfront_asset_host.gemspec
|
47
|
+
- lib/cloudfront_asset_host.rb
|
48
|
+
- lib/cloudfront_asset_host/asset_tag_helper_ext.rb
|
49
|
+
- lib/cloudfront_asset_host/css_rewriter.rb
|
50
|
+
- lib/cloudfront_asset_host/mime_types.yml
|
51
|
+
- lib/cloudfront_asset_host/uploader.rb
|
52
|
+
- test/app/config/s3.yml
|
53
|
+
- test/app/public/images/image.png
|
54
|
+
- test/app/public/javascripts/application.js
|
55
|
+
- test/app/public/stylesheets/style.css
|
56
|
+
- test/cloudfront_asset_host_test.rb
|
57
|
+
- test/css_rewriter_test.rb
|
58
|
+
- test/test_helper.rb
|
59
|
+
- test/uploader_test.rb
|
60
|
+
has_rdoc: true
|
61
|
+
homepage: http://github.com/menno/cloudfront_asset_host
|
62
|
+
licenses: []
|
63
|
+
|
64
|
+
post_install_message:
|
65
|
+
rdoc_options:
|
66
|
+
- --charset=UTF-8
|
67
|
+
require_paths:
|
68
|
+
- lib
|
69
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
segments:
|
74
|
+
- 0
|
75
|
+
version: "0"
|
76
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
segments:
|
81
|
+
- 0
|
82
|
+
version: "0"
|
83
|
+
requirements: []
|
84
|
+
|
85
|
+
rubyforge_project:
|
86
|
+
rubygems_version: 1.3.6
|
87
|
+
signing_key:
|
88
|
+
specification_version: 3
|
89
|
+
summary: Rails plugin to easily and efficiently deploy your assets on Amazon's S3 or CloudFront
|
90
|
+
test_files:
|
91
|
+
- test/cloudfront_asset_host_test.rb
|
92
|
+
- test/css_rewriter_test.rb
|
93
|
+
- test/test_helper.rb
|
94
|
+
- test/uploader_test.rb
|