asset_link 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4b6b58526fe25fe9c9505b63a704dcd5289f1d1c
4
+ data.tar.gz: 7f9bcb6ea40828f4a84fc245c779d742260b7a89
5
+ SHA512:
6
+ metadata.gz: ada813208b60e65201a1f35080d01467531be7c3c6ac9f88d883051b80f48b37efaa3737055ae7c5dcb7c562912e21fc312a02cbb4f9486f865653154524abfc
7
+ data.tar.gz: 306b2a4989281f7b0be50c0c698b39f9b0da97f829256470b7564625dd8179b3e608628bcf4877c8f0a9194f032d4357c531c6d6ef7cab490aeee7feea80125b
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ .idea
2
+ *.iml
3
+ /.bundle/
4
+ /.yardoc
5
+ /Gemfile.lock
6
+ /_yardoc/
7
+ /coverage/
8
+ /doc/
9
+ /pkg/
10
+ /spec/reports/
11
+ /tmp/
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'test-unit'
4
+ gem 'mocha'
5
+ # Specify your gem's dependencies in asset_link.gemspec
6
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Anton Antonov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,79 @@
1
+ # AssetLink
2
+
3
+ This gem allows to replace any asset (image, CSS stylesheet, script, etc.) with a light-weight link to the same asset located at a remote storage (e.g. Amazon S3).
4
+ The idea behind it is to reduce the size of the application deployment, especially when it is limited by a hosting service (e.g. max slug size at Heroku is 300MB).
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'asset_link'
12
+ ```
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install asset_link
21
+
22
+ ## Usage
23
+
24
+ ### Upload
25
+
26
+ To upload asset(s) to the remote storage run:
27
+
28
+ $ asset_link_upload [FILE_PATTERN]
29
+
30
+ e.g. to upload all .jpg images from /app/assets folder run:
31
+
32
+ $ cd ./app
33
+ $ asset_link_upload ./assets/**/*.jpg
34
+
35
+ As a result each image.jpg file would be uploaded to the remote storage and replaced by a text file image.jpg.link that contains a link to that remote file.
36
+
37
+ ### Download
38
+
39
+ To download asset(s) from the remote storage run:
40
+
41
+ $ asset_link_download [FILE_PATTERN]
42
+
43
+ e.g. to replace all .jpg.link images by originals in /app/assets folder run:
44
+
45
+ $ cd ./app
46
+ $ asset_link_upload ./assets/**/*.jpg.link
47
+
48
+ As a result each image.jpg.link file would be replaced by the original image.jpg file from the remote storage.
49
+
50
+ ### Middleware
51
+
52
+ In order to allow Rails server to respond with original asset content from .link file, install middleware:
53
+
54
+ in config.ru add before ``run Rails.application``:
55
+
56
+ ```ruby
57
+ use AssetLink::Middleware
58
+ ```
59
+
60
+ in config/initializers/sprokets.rb:
61
+
62
+ ```ruby
63
+ Sprockets.register_engine '.link', AssetLink::Processor.new, silence_deprecation: true
64
+ ```
65
+
66
+ ## Development
67
+
68
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
69
+
70
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
71
+
72
+ ## Contributing
73
+
74
+ Bug reports and pull requests are welcome on GitHub at https://github.com/doubleton/asset_link.
75
+
76
+ ## License
77
+
78
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
79
+
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task :default => :spec
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'asset_link/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "asset_link"
8
+ spec.version = AssetLink::VERSION
9
+ spec.authors = ["Anton Antonov"]
10
+ spec.email = ["anton.antonov@castle.co"]
11
+
12
+ spec.summary = %q{Gem that allows to replace any asset with a light-weight link to a remote storage.}
13
+ spec.description = %q{This gem allows to replace any asset (image, CSS stylesheet, script, etc.) with a light-weight link to the same asset located at a remote storage (e.g. Amazon S3). The idea behind it is to reduce the size of the application deployment, especially when it is limited by a hosting service (e.g. max slug size at Heroku is 300MB).}
14
+ spec.homepage = "https://github.com/doubleton/asset_link"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = "bin"
19
+ spec.executables = ["asset_link"]
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_development_dependency "mime-types", "~> 3.0"
23
+ spec.add_development_dependency "bundler", "~> 1.11"
24
+ spec.add_development_dependency "rake", "~> 10.0"
25
+ spec.add_development_dependency "fog", '~> 1.20'
26
+ end
data/bin/asset_link ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'asset_link'
4
+
5
+ args = ARGV
6
+ action = args.shift
7
+
8
+ case action
9
+ when "-upload"
10
+ AssetLink::Loader.new.upload args
11
+ when "-download"
12
+ AssetLink::Loader.new.download args
13
+ else
14
+ puts "Usage: asset_link -upload [FILES] or asset_link -download [FILES]"
15
+ end
data/lib/asset_link.rb ADDED
@@ -0,0 +1,8 @@
1
+ require "asset_link/version"
2
+ require "asset_link/middleware"
3
+ require "asset_link/processor"
4
+
5
+ require "asset_link/config"
6
+ require "asset_link/storage"
7
+ require "asset_link/multi_mime"
8
+ require "asset_link/loader"
@@ -0,0 +1,29 @@
1
+ module AssetLink
2
+ class Config
3
+
4
+ # FOG configuration
5
+ attr_accessor :fog_provider, :fog_directory, :fog_region
6
+
7
+ # Amazon AWS
8
+ attr_accessor :aws_access_key_id, :aws_secret_access_key
9
+
10
+ def initialize
11
+ self.fog_provider = ENV.fetch('FOG_PROVIDER') { 'AWS' }
12
+ self.fog_directory = ENV['FOG_DIRECTORY'] || ENV['AWS_S3_BUCKET']
13
+ self.fog_region = ENV['FOG_REGION'] || ENV['AWS_REGION']
14
+ self.aws_access_key_id = ENV['AWS_ACCESS_KEY_ID']
15
+ self.aws_secret_access_key = ENV['AWS_SECRET_ACCESS_KEY']
16
+ end
17
+
18
+ def fog_options
19
+ options = {
20
+ provider: fog_provider,
21
+ aws_access_key_id: aws_access_key_id,
22
+ aws_secret_access_key: aws_secret_access_key
23
+ }
24
+ options.merge!({region: fog_region}) if fog_region
25
+ options
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,67 @@
1
+ require 'open-uri'
2
+
3
+ module AssetLink
4
+ class Loader
5
+
6
+ def upload(files)
7
+ files.each do |f|
8
+ next unless File.file?(f)
9
+ puts "Uploading: #{f}"
10
+ link = upload_file(f)
11
+ create_link_file(f, link)
12
+ File.delete(f)
13
+ end
14
+ end
15
+
16
+ def download(files)
17
+ files.each do |f|
18
+ next if !File.file?(f) || File.extname(f) != '.link'
19
+ puts "Downloading: #{f}"
20
+ link = read_file(f)
21
+ download_file(f, link)
22
+ File.delete(f)
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def read_file(f)
29
+ File.read(f).strip
30
+ end
31
+
32
+ def upload_file(f)
33
+ ext = File.extname(f)[1..-1]
34
+ mime = MultiMime.lookup(ext)
35
+ file = {
36
+ :key => f,
37
+ :body => File.open(f),
38
+ :public => true,
39
+ :content_type => mime
40
+ }
41
+
42
+ storage.bucket.files.create(file).public_url
43
+ end
44
+
45
+ def download_file(f, link)
46
+ new_filename = f.gsub('.link', '')
47
+ open(new_filename, 'w') do |file|
48
+ file << open(link).read
49
+ end
50
+ end
51
+
52
+ def create_link_file(f, link)
53
+ File.open("#{f}.link", "w") do |file|
54
+ file.write(link)
55
+ end
56
+ end
57
+
58
+ def config
59
+ @config ||= AssetLink::Config.new
60
+ end
61
+
62
+ def storage
63
+ @storage ||= AssetLink::Storage.new(config)
64
+ end
65
+
66
+ end
67
+ end
@@ -0,0 +1,64 @@
1
+ require 'open-uri'
2
+
3
+ module AssetLink
4
+ class Middleware
5
+ def initialize(app)
6
+ @app = app
7
+ @manifest = load_manifest
8
+ end
9
+
10
+ def call(env)
11
+ request = Rack::Request.new(env)
12
+ code, headers, body = @app.call(env)
13
+
14
+ if URI.unescape(request.path).start_with?('/assets/') && code == 200
15
+ entry = body.respond_to?(:to_a) ? body.to_a.first : body
16
+
17
+ asset = case entry
18
+ when Sprockets::Asset
19
+ entry
20
+ when Rack::File::Iterator
21
+ find_asset(entry.path)
22
+ end
23
+
24
+ if asset && asset.filename.ends_with?('.link')
25
+ link = File.read(asset.filename).strip # the file contains a link to the actual asset
26
+
27
+ open(link) do |f|
28
+ headers = f.meta
29
+ body.close if body.respond_to?(:closed?) && !body.closed?
30
+ body = [f.read]
31
+ end
32
+ end
33
+ end
34
+ [code, headers, body]
35
+ end
36
+
37
+ private
38
+
39
+ def find_asset(path)
40
+ filename = URI.unescape(path).gsub(/.*\/assets\//, '')
41
+
42
+ if @manifest && @manifest['files'][filename]
43
+ manifest_file = @manifest['files'][filename]
44
+ assets_engine.find_asset(manifest_file['logical_path'])
45
+ elsif filename =~ %r{(.*)-[a-z0-9]+\.(.+)}
46
+ assets_engine.find_asset("#{$1}.#{$2}")
47
+ end
48
+ end
49
+
50
+ def assets_engine
51
+ @assets_engine ||= Sprockets::Environment.new(Rails.root).tap do |e|
52
+ Dir[Rails.root.join('app', 'assets', '*')].each { |p| e.append_path p }
53
+ end
54
+ end
55
+
56
+ def load_manifest
57
+ manifests = Dir[Rails.root.join('public', 'assets', '.sprockets-manifest-*.json')]
58
+ if manifests.first
59
+ file = File.read(manifests.first)
60
+ JSON.parse(file)
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,20 @@
1
+ require 'mime/types'
2
+
3
+ module AssetLink
4
+ class MultiMime
5
+
6
+ def self.lookup(ext)
7
+
8
+ if defined?(Mime::Type)
9
+ Mime::Type.lookup_by_extension(ext)
10
+ elsif defined?(Rack::Mime)
11
+ ext_with_dot = ".#{ext}"
12
+ Rack::Mime.mime_type(ext_with_dot)
13
+ else
14
+ ::MIME::Types.type_for(ext).first
15
+ end
16
+
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,9 @@
1
+ module AssetLink
2
+ class Processor
3
+
4
+ def call(*)
5
+ { data: '' }
6
+ end
7
+
8
+ end
9
+ end
@@ -0,0 +1,27 @@
1
+ require 'fog'
2
+
3
+ module AssetLink
4
+ class Storage
5
+
6
+ class BucketNotFound < StandardError; end
7
+
8
+ attr_accessor :config
9
+
10
+ def initialize(cfg)
11
+ @config = cfg
12
+ end
13
+
14
+ def connection
15
+ @connection ||= Fog::Storage.new(config.fog_options)
16
+ end
17
+
18
+ def bucket
19
+ @bucket ||= begin
20
+ bucket = connection.directories.get(config.fog_directory)
21
+ bucket = connection.directories.create(key: config.fog_directory) unless bucket
22
+ bucket
23
+ end
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,3 @@
1
+ module AssetLink
2
+ VERSION = "0.0.1"
3
+ end
metadata ADDED
@@ -0,0 +1,121 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: asset_link
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Anton Antonov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-08-19 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: '3.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.11'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.11'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: fog
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.20'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.20'
69
+ description: This gem allows to replace any asset (image, CSS stylesheet, script,
70
+ etc.) with a light-weight link to the same asset located at a remote storage (e.g.
71
+ Amazon S3). The idea behind it is to reduce the size of the application deployment,
72
+ especially when it is limited by a hosting service (e.g. max slug size at Heroku
73
+ is 300MB).
74
+ email:
75
+ - anton.antonov@castle.co
76
+ executables:
77
+ - asset_link
78
+ extensions: []
79
+ extra_rdoc_files: []
80
+ files:
81
+ - ".gitignore"
82
+ - Gemfile
83
+ - LICENSE.txt
84
+ - README.md
85
+ - Rakefile
86
+ - asset_link.gemspec
87
+ - bin/asset_link
88
+ - lib/asset_link.rb
89
+ - lib/asset_link/config.rb
90
+ - lib/asset_link/loader.rb
91
+ - lib/asset_link/middleware.rb
92
+ - lib/asset_link/multi_mime.rb
93
+ - lib/asset_link/processor.rb
94
+ - lib/asset_link/storage.rb
95
+ - lib/asset_link/version.rb
96
+ homepage: https://github.com/doubleton/asset_link
97
+ licenses:
98
+ - MIT
99
+ metadata: {}
100
+ post_install_message:
101
+ rdoc_options: []
102
+ require_paths:
103
+ - lib
104
+ required_ruby_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ required_rubygems_version: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ requirements: []
115
+ rubyforge_project:
116
+ rubygems_version: 2.4.5.1
117
+ signing_key:
118
+ specification_version: 4
119
+ summary: Gem that allows to replace any asset with a light-weight link to a remote
120
+ storage.
121
+ test_files: []