asset_oss_rails4 0.3.1448447091

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 49c765dd6313c120f32a96e4a0b5984c097c64ff
4
+ data.tar.gz: f7e5c8cc7459a54595621ef84e2651039a566a1b
5
+ SHA512:
6
+ metadata.gz: e746bfd498af8db083135a3345239d165ffc74f384c5947766eb9c0b5d62d10367cbaaa1e21bb9d608ecd7f58eae1ebc68bb2f234296e4f468c7e4feb5550f6c
7
+ data.tar.gz: 6517a3d315a6aa28e1264ee01ed5e465fa2941690958f5a1ce9f0e131efaceb9c17f3a413de3a2d7b2ab0764bb6edc4486910cac35465902257f75851f8b19f9
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) Richard Taylor
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.
@@ -0,0 +1,44 @@
1
+ Asset OSS - 上传Rails项目静态文件到Aliyun OSS
2
+ ===
3
+
4
+ 关于
5
+ ---
6
+
7
+ 基于[asset_id](https://github.com/moocode/asset_id),[aset_sync](https://github.com/rumblelabs/asset_sync)也许是更好的选择
8
+
9
+ 一个简单的上传Rails assets目录里静态文件到Aliyun OSS工具
10
+
11
+ 使用和配置
12
+ ---
13
+
14
+ 添加`gem "asset_oss"`到你的Gemfile
15
+
16
+ 修改`config/environments/production.rb`文件, `config.action_controller.asset_host = "http://my_live_bucket.oss.aliyuncs.com"`
17
+
18
+ 新建一个`config/asset_oss.yml`文件
19
+ ```
20
+ production:
21
+ host: 'oss.aliyuncs.com'
22
+ access_key_id: 'MY_ACCESS_KEY'
23
+ secret_access_key: 'MY_ACCESS_SECRET'
24
+ bucket: "my_live_bucket"
25
+ ```
26
+
27
+ 创建rake任务, `lib/tasks/asset_oss.rake`
28
+ ```
29
+ namespace :asset do
30
+ namespace :oss do
31
+
32
+ desc "uploads the current assets to aliyun oss with stamped ids"
33
+ task :upload do
34
+ AssetOSS::Asset.asset_paths += ['assets'] # Configure additional asset paths
35
+ AssetOSS::OSS.upload
36
+ end
37
+
38
+ end
39
+ end
40
+ ```
41
+
42
+ 其它
43
+ ---
44
+ 也许可以通过修改Rails `config.assets.prefix`实现缓存过期,记得prefix要是assets开头,同时修改`AssetOSS::Asset.asset_paths`
@@ -0,0 +1,90 @@
1
+ h1. Asset OSS - Asset stamping and uploading to Aliyun OSS for Rails
2
+
3
+ h2. About
4
+
5
+ 基于asset_id修改,aset_sync也许是更好的选择
6
+
7
+ Uploads static assets to Aliyun OSS with unique identifiers encoded into the path of the asset.
8
+
9
+ Only works with Rails 3.x because Rails 3 makes doing this sort of thing a lot easier and
10
+ that is all I needed it for.
11
+
12
+ This library takes standard Rails asset paths such as <code>/stylesheets/main.css?1288717704</code> and converts them
13
+ into <code>http://my_bucket.oss.aliyuncs.com/stylesheets/main-id-95df8d9bf5237ad08df3115ee74dcb10.css</code>.
14
+
15
+ It uses an MD5 hash of the file contents to produce the id so the same asset will always have the same ID.
16
+
17
+ In my quest to achieve a Google Page Speed score of 100, this library achieves the following:
18
+
19
+ * Assets served from a cookie-less domain
20
+ * Unique identifier is not encoded into a query parameter (so it is cacheable by proxy servers)
21
+ * All assets have far-future expires headers for caching
22
+ * Assets have the Cache-Control: public header for caching
23
+ * CSS and javascript is GZipped and the correct headers are added
24
+
25
+ As an added bonus, all your assets are available over <code>https://</code> as well.
26
+
27
+ h2. Usage
28
+
29
+ Add the gem to your <code>Gemfile</code>
30
+
31
+ <code>gem "asset_oss"</code>
32
+
33
+ Configure <code>config/environments/production.rb</code> to use Aliyun OSS as the asset host
34
+ and to use the id-stamped asset paths in helpers
35
+
36
+ <pre><code>config.action_controller.asset_host = Proc.new do |source|
37
+ 'http://my_bucket.oss.aliyuncs.com'
38
+ end
39
+ config.action_controller.asset_path = Proc.new do |source|
40
+ AssetOSS::Asset.fingerprint(source)
41
+ end
42
+ </code></pre>
43
+
44
+ Add your Aliyun OSS configuration details to <code>config/asset_oss.yml</code>
45
+
46
+ <pre><code>production:
47
+ access_key_id: 'MY_ACCESS_KEY'
48
+ secret_access_key: 'MY_ACCESS_SECRET'
49
+ bucket: "my_live_bucket"
50
+ </code></pre>
51
+
52
+ Optionally create a rake task in <code>lib/tasks/asset_oss.rake</code> to
53
+ perform the upload for use in your deploy scripts
54
+
55
+ <pre><code>namespace :asset do
56
+ namespace :oss do
57
+
58
+ desc "uploads the current assets to aliyun oss with stamped ids"
59
+ task :upload do
60
+ Aliyun::OSS::DEFAULT_HOST.replace "oss-internal.aliyuncs.com"
61
+ AssetOSS::Asset.asset_paths += ['assets'] # Configure additional asset paths
62
+ AssetOSS::OSS.upload
63
+ end
64
+
65
+ end
66
+ end
67
+ </code></pre>
68
+
69
+ h2. SSL configuration
70
+
71
+ If you want to use the SSL host in your configuration you can do so in <code>config/environments/production.rb</code>
72
+
73
+ <pre><code>config.action_controller.asset_host = Proc.new do |source|
74
+ request.ssl? 'https://my_bucket.oss.aliyuncs.com' : 'http://my_bucket.oss.aliyuncs.com'
75
+ end
76
+ </code></pre>
77
+
78
+ h2. CSS Images
79
+
80
+ By default any relative CSS images that match files on the filesystem are converted to AssetOSS paths as well.
81
+
82
+ For aliyun oss, if you don't specify a <code>prefix</code> it will use the <code>http://</code> bucket URL by default. You can override this in <code>config/asset_oss.yml</code>. For example if you wanted to use the <code>https://</code> url:
83
+
84
+ <pre><code>production:
85
+ host: 'oss-internal.aliyuncs.com'
86
+ access_key_id: 'MY_ACCESS_KEY'
87
+ secret_access_key: 'MY_ACCESS_SECRET'
88
+ bucket: "my_live_bucket"
89
+ prefix: "https://my_bucket.oss.aliyuncs.com"
90
+ </code></pre>
@@ -0,0 +1,3 @@
1
+ require 'asset_oss/asset'
2
+ require 'asset_oss/cache'
3
+ require 'asset_oss/backend/oss'
@@ -0,0 +1,168 @@
1
+ require 'digest/md5'
2
+ require 'mime/types'
3
+ require 'time'
4
+ require 'zlib'
5
+
6
+ module AssetOSS
7
+ class Asset
8
+
9
+ DEFAULT_ASSET_PATHS = ['favicon.ico', 'images', 'javascripts', 'stylesheets']
10
+ @@asset_paths = DEFAULT_ASSET_PATHS
11
+
12
+ #DEFAULT_GZIP_TYPES = ['text/css', 'application/javascript']
13
+ DEFAULT_GZIP_TYPES = []
14
+ @@gzip_types = DEFAULT_GZIP_TYPES
15
+
16
+ @@debug = false
17
+ @@nocache = false
18
+ @@nofingerprint = false
19
+
20
+ def self.init(options)
21
+ @@debug = options[:debug] if options[:debug]
22
+ @@nocache = options[:nocache] if options[:nocache]
23
+ @@nofingerprint = options[:nofingerprint] if options[:nofingerprint]
24
+ @@nofingerprint ||= []
25
+ end
26
+
27
+ def self.asset_paths
28
+ @@asset_paths
29
+ end
30
+
31
+ def self.gzip_types
32
+ @@gzip_types
33
+ end
34
+
35
+ def self.asset_paths=(paths)
36
+ @@asset_paths = paths
37
+ end
38
+
39
+ def self.gzip_types=(types)
40
+ @@gzip_types = types
41
+ end
42
+
43
+ def self.find(paths=Asset.asset_paths)
44
+ paths.inject([]) {|assets, path|
45
+ path = File.join Rails.root, 'public', path
46
+ a = Asset.new(path)
47
+ #TODO 暂时不上传gz文件,相好解决ie6 gzip的问题再说
48
+ assets << a if a.is_file? and !a.cache_hit? and !a.gz_file?
49
+ assets += Dir.glob(path+'/**/*').inject([]) {|m, file|
50
+ a = Asset.new(file); m << a if a.is_file? and !a.cache_hit? and !a.gz_file?; m
51
+ }
52
+ }
53
+ end
54
+
55
+ def self.fingerprint(path)
56
+ asset = Asset.new(path)
57
+ hit = Cache.get(asset)
58
+ return hit[:fingerprint] if hit
59
+ return asset.fingerprint
60
+ end
61
+
62
+ attr_reader :path
63
+
64
+ def initialize(path)
65
+ @path = path
66
+ @path = absolute_path
67
+ end
68
+
69
+ def path_prefix
70
+ File.join Rails.root, 'public'
71
+ end
72
+
73
+ def absolute_path
74
+ path =~ /#{path_prefix}/ ? path : File.join(path_prefix, path)
75
+ end
76
+
77
+ def relative_path
78
+ path.gsub(path_prefix, '')
79
+ end
80
+
81
+ def gzip_type?
82
+ Asset.gzip_types.include? mime_type
83
+ end
84
+
85
+ def data
86
+ @data ||= File.read(path)
87
+ end
88
+
89
+ def md5
90
+ @digest ||= Digest::MD5.hexdigest(data)
91
+ end
92
+
93
+ def fingerprint
94
+ p = relative_path
95
+ return p if relative_path =~ /^\/assets.*\//
96
+ File.join File.dirname(p), "#{File.basename(p, File.extname(p))}-id-#{md5}#{File.extname(p)}"
97
+ end
98
+
99
+ def mime_type
100
+ MIME::Types.of(path).first.to_s
101
+ end
102
+
103
+ def css?
104
+ mime_type == 'text/css'
105
+ end
106
+
107
+ def replace_css_images!(options={})
108
+ options[:prefix] ||= ''
109
+ # adapted from https://github.com/blakink/asset_id
110
+ data.gsub! /url\((?:"([^"]*)"|'([^']*)'|([^)]*))\)/mi do |match|
111
+ begin
112
+ # $1 is the double quoted string, $2 is single quoted, $3 is no quotes
113
+ uri = ($1 || $2 || $3).to_s.strip
114
+ uri.gsub!(/^\.\.\//, '/')
115
+
116
+ # if the uri appears to begin with a protocol then the asset isn't on the local filesystem
117
+ if uri =~ /[a-z]+:\/\//i
118
+ "url(#{uri})"
119
+ else
120
+ asset = Asset.new(uri)
121
+ # TODO: Check the referenced asset is in the asset_paths
122
+ puts " - Changing CSS URI #{uri} to #{options[:prefix]}#{asset.fingerprint}" if @@debug
123
+ "url(#{options[:prefix]}#{asset.fingerprint})"
124
+ end
125
+ rescue Errno::ENOENT => e
126
+ puts " - Warning: #{uri} not found" if @@debug
127
+ "url(#{uri})"
128
+ end
129
+ end
130
+ end
131
+
132
+ def gzip!
133
+ # adapted from https://github.com/blakink/asset_id
134
+ @data = returning StringIO.open('', 'w') do |gz_data|
135
+ gz = Zlib::GzipWriter.new(gz_data, nil, nil)
136
+ gz.write(data)
137
+ gz.close
138
+ end.string
139
+ end
140
+
141
+ def expiry_date
142
+ @expiry_date ||= (Time.now + (60*60*24*365)).httpdate
143
+ end
144
+
145
+ def cache_headers
146
+ {'Expires' => expiry_date, 'Cache-Control' => 'public'} # 1 year expiry
147
+ end
148
+
149
+ def gzip_headers
150
+ {'Content-Encoding' => 'gzip', 'Vary' => 'Accept-Encoding'}
151
+ end
152
+
153
+ def is_file?
154
+ File.exists? absolute_path and !File.directory? absolute_path
155
+ end
156
+
157
+ def cache_hit?
158
+ return false if @@nocache or Cache.miss? self
159
+ puts "AssetOSS: #{relative_path} - Cache Hit"
160
+ return true
161
+ end
162
+
163
+ def gz_file?
164
+ path =~ /\.gz$/
165
+ end
166
+
167
+ end
168
+ end
@@ -0,0 +1,87 @@
1
+ require 'aliyun/oss'
2
+
3
+ module AssetOSS
4
+ class OSS
5
+
6
+ def self.oss_config
7
+ @@config ||= YAML.load_file(File.join(Rails.root, "config/asset_oss.yml"))[Rails.env] rescue nil || {}
8
+ end
9
+
10
+ def self.connect_to_oss
11
+ Aliyun::OSS::Base.establish_connection!(
12
+ :server => oss_config['host'] || Aliyun::OSS::DEFAULT_HOST,
13
+ :access_key_id => oss_config['access_key_id'],
14
+ :secret_access_key => oss_config['secret_access_key']
15
+ )
16
+ end
17
+
18
+ def self.oss_permissions
19
+ :public_read
20
+ end
21
+
22
+ def self.oss_bucket
23
+ oss_config['bucket']
24
+ end
25
+
26
+ def self.oss_folder
27
+ oss_config['folder']
28
+ end
29
+
30
+ def self.oss_prefix
31
+ oss_config['prefix'] || oss_bucket_url
32
+ end
33
+
34
+ def self.oss_bucket_url
35
+ "http://#{oss_bucket}.oss.aliyuncs.com#{oss_folder ? "/#{oss_folder}" : '' }"
36
+ end
37
+
38
+ def self.full_path(asset)
39
+ oss_folder ? "/#{oss_folder}#{asset.fingerprint}" : asset.fingerprint
40
+ end
41
+
42
+ def self.upload(options={})
43
+ Asset.init(:debug => options[:debug], :nofingerprint => options[:nofingerprint])
44
+
45
+ assets = Asset.find
46
+ return if assets.empty?
47
+
48
+ connect_to_oss
49
+
50
+ Aliyun::OSS::Bucket.create(oss_bucket, :access => oss_permissions)
51
+
52
+ assets.each do |asset|
53
+
54
+ puts "AssetOSS: #{asset.relative_path}" if options[:debug]
55
+
56
+ headers = {
57
+ :content_type => asset.mime_type,
58
+ }.merge(asset.cache_headers)
59
+
60
+ asset.replace_css_images!(:prefix => oss_prefix) if asset.css?
61
+
62
+ if asset.gzip_type?
63
+ headers.merge!(asset.gzip_headers)
64
+ asset.gzip!
65
+ end
66
+
67
+ if options[:debug]
68
+ puts " - Uploading: #{full_path(asset)} [#{asset.data.size} bytes]"
69
+ puts " - Headers: #{headers.inspect}"
70
+ end
71
+
72
+ unless options[:dry_run]
73
+ res = Aliyun::OSS::OSSObject.store(
74
+ full_path(asset),
75
+ asset.data,
76
+ oss_bucket,
77
+ headers
78
+ )
79
+ puts " - Response: #{res.inspect}" if options[:debug]
80
+ end
81
+ end
82
+
83
+ Cache.save! unless options[:dry_run]
84
+ end
85
+
86
+ end
87
+ end
@@ -0,0 +1,37 @@
1
+ require 'yaml'
2
+
3
+ module AssetOSS
4
+ class Cache
5
+
6
+ def self.empty
7
+ @cache = {}
8
+ end
9
+
10
+ def self.cache
11
+ @cache ||= YAML.load_file(cache_path) rescue {}
12
+ end
13
+
14
+ def self.cache_path
15
+ File.join(Rails.root, 'log', 'asset_oss_cache.yml')
16
+ end
17
+
18
+ def self.get(asset)
19
+ cache[asset.relative_path]
20
+ end
21
+
22
+ def self.hit?(asset)
23
+ return true if cache[asset.relative_path] and cache[asset.relative_path][:fingerprint] == asset.fingerprint
24
+ cache[asset.relative_path] = {:expires => asset.expiry_date.to_s, :fingerprint => asset.fingerprint}
25
+ false
26
+ end
27
+
28
+ def self.miss?(asset)
29
+ !hit?(asset)
30
+ end
31
+
32
+ def self.save!
33
+ File.open(cache_path, 'w') {|f| f.write(YAML.dump(cache))}
34
+ end
35
+
36
+ end
37
+ end
metadata ADDED
@@ -0,0 +1,79 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: asset_oss_rails4
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.1448447091
5
+ platform: ruby
6
+ authors:
7
+ - mangege
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-11-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: mime-types
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: aliyun-oss-rails4
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: asset_oss is a library for uploading static assets to Aliyun OSS.
42
+ email: langyong135@gmail.com
43
+ executables: []
44
+ extensions: []
45
+ extra_rdoc_files: []
46
+ files:
47
+ - LICENSE
48
+ - README.md
49
+ - README_EN.textile
50
+ - lib/asset_oss.rb
51
+ - lib/asset_oss/asset.rb
52
+ - lib/asset_oss/backend/oss.rb
53
+ - lib/asset_oss/cache.rb
54
+ homepage: http://github.com/mangege/asset_oss
55
+ licenses: []
56
+ metadata: {}
57
+ post_install_message:
58
+ rdoc_options:
59
+ - "--inline-source"
60
+ - "--charset=UTF-8"
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ requirements: []
74
+ rubyforge_project:
75
+ rubygems_version: 2.4.5.1
76
+ signing_key:
77
+ specification_version: 4
78
+ summary: asset_oss is a library for uploading static assets to Aliyun OSS.
79
+ test_files: []