butler_static 0.0.7 → 0.0.8.alpha.20
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +101 -5
- data/Rakefile +1 -0
- data/butler.gemspec +5 -4
- data/lib/butler.rb +1 -1
- data/lib/butler/railtie.rb +27 -3
- data/lib/butler/static.rb +8 -8
- data/lib/butler/version.rb +2 -2
- metadata +18 -34
data/README.md
CHANGED
@@ -1,6 +1,20 @@
|
|
1
1
|
# Butler
|
2
2
|
|
3
|
-
|
3
|
+
Butler is a Rack Web Server for Static Files based on ActionDispatch::Static.
|
4
|
+
It is intended to be used as a Rails Middleware in an environment where serving static assets through a specialized web server such as nginx is technically not an option.
|
5
|
+
|
6
|
+
### Background
|
7
|
+
|
8
|
+
Butler extends ActionDispatch::Static's functionality to allow a the developer to set custom rules for the HTTP headers that the files sent should carry.
|
9
|
+
|
10
|
+
The author's intent was to allow Rails to serve static assets with custom HTTP Headers.
|
11
|
+
This allows for example serving webfonts or icon fonts carrying the appropriate HTTP headers via a Content Delivery Network (CDN) such as Amazon's Cloudfront. Files requested by the CDN will need to carry the headers the file should be sent with to the visitor's browser already when being sent from the web server.
|
12
|
+
|
13
|
+
ActionDispatch::Static, Rack::Static et al. don't allow (yet) to add custom HTTP headers to files because the underlying Rack::File implementation only allows for setting a static 'Cache-Control' header.
|
14
|
+
|
15
|
+
Code and Tests taken from Rails' ActionDispatch::Static.
|
16
|
+
|
17
|
+
If no matching file can be found in the precompiled assets the request will bubble up to the Rails stack to decide how to handle it, which mimicks ActionDispatch::Static's behaviour.
|
4
18
|
|
5
19
|
## Installation
|
6
20
|
|
@@ -18,12 +32,94 @@ Or install it yourself as:
|
|
18
32
|
|
19
33
|
## Usage
|
20
34
|
|
21
|
-
|
35
|
+
### Configuration
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
# config/environment/production.rb
|
39
|
+
|
40
|
+
# Use Butler
|
41
|
+
# to serve precompiled assets
|
42
|
+
config.assets.use_butler = true
|
43
|
+
|
44
|
+
# Rules for HTTP Headers to be set on files
|
45
|
+
# sent by Butler
|
46
|
+
config.assets.header_rules = {
|
47
|
+
rule => {http_field => content},
|
48
|
+
rule => {http_field => content}
|
49
|
+
}
|
50
|
+
```
|
51
|
+
|
52
|
+
### Providing Rules for setting HTTP Headers
|
53
|
+
|
54
|
+
There are a few way to set rules for all files or files in a certain folder or a certain extension.
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
# 1) Global Rules
|
58
|
+
:global => Matches every file
|
59
|
+
Ex.: :global => {
|
60
|
+
'Cache-Control' => 'public, max-age=31536000', # 1 year
|
61
|
+
'Some Custom Header' => 'Some Custom Content'
|
62
|
+
}
|
63
|
+
|
64
|
+
# 2) Folders
|
65
|
+
'/folder' => Matches all files in a certain folder
|
66
|
+
'/folder/subfolder' => ...
|
67
|
+
Note: Provide the folder as a string,
|
68
|
+
with or without the starting slash
|
69
|
+
Ex.: '/fonts' => {'Access-Control-Allow-Origin' => '*'}
|
70
|
+
|
71
|
+
# 3) File Extensions
|
72
|
+
['css', 'js'] => Will match all files ending in .css or .js
|
73
|
+
%w(css js) => ...
|
74
|
+
Note: Provide the file extensions in an array,
|
75
|
+
use any ruby syntax you like to set that array up
|
76
|
+
Ex.: %w(eot ttf otf woff svg) => {... => ...}
|
77
|
+
|
78
|
+
# 4) Regular Expressions / Regexp
|
79
|
+
%r{\.(?:css|js)\z} => will match all files ending in .css or .js
|
80
|
+
/\.(?:eot|ttf|otf|woff|svg)\z/ => will match all files ending
|
81
|
+
in the most common web font formats
|
82
|
+
|
83
|
+
# 5) Shortcuts
|
84
|
+
There is currently only one shortcut defined.
|
85
|
+
:fonts => will match all files ending in eot, ttf, otf, woff, svg
|
86
|
+
using the Regexp stated above
|
87
|
+
Ex.: :fonts => {'Access-Control-Allow-Origin' => '*'} # Will allow fonts and icon fonts to be displayed in Firefox 3.5+
|
88
|
+
|
89
|
+
|
90
|
+
Note: The rules will be applied in the order the are listed,
|
91
|
+
thus more special rules further down below can override
|
92
|
+
general global HTTP header settings
|
93
|
+
```
|
94
|
+
|
95
|
+
## Complete Example Use Case
|
96
|
+
|
97
|
+
The example code below is from a Rails app deployed to [Heroku](http://www.heroku.com) using butler to serve the precompiled assets.
|
98
|
+
Cache-Control headers are set on all served files, and Access-Control Headers on Fonts / Icon Fonts.
|
99
|
+
|
100
|
+
```ruby
|
101
|
+
# config/environment/production.rb
|
102
|
+
|
103
|
+
# Use Butler
|
104
|
+
# to serve precompiled assets
|
105
|
+
config.assets.use_butler = true
|
106
|
+
|
107
|
+
# Rules for HTTP Headers
|
108
|
+
# to be set on static files sent by Butler
|
109
|
+
config.assets.header_rules = {
|
110
|
+
:global => {'Cache-Control' => 'public, max-age=31536000'},
|
111
|
+
:fonts => {'Access-Control-Allow-Origin' => '*'}
|
112
|
+
}
|
113
|
+
```
|
114
|
+
That's it. I hope you like Butler.
|
115
|
+
Shoot me an [email](github@tklemm.eu) or [tweet](https://www.twitter.com/thomasjklemm) if you have any questions or thoughts about how to improve Butler. Enjoy your life!
|
22
116
|
|
23
117
|
## Contributing
|
24
118
|
|
25
119
|
1. Fork it
|
26
120
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
-
3.
|
28
|
-
|
29
|
-
|
121
|
+
3. Improve Butler
|
122
|
+
3a. Run tests continually (`bundle exec guard start`) or manually every time (`rake test`)
|
123
|
+
4. Commit your changes (`git commit -am 'Add some feature'`)
|
124
|
+
5. Push to the branch (`git push origin my-new-feature`)
|
125
|
+
6. Create new Pull Request
|
data/Rakefile
CHANGED
data/butler.gemspec
CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |gem|
|
|
8
8
|
gem.version = Butler::VERSION
|
9
9
|
gem.authors = ["Thomas Klemm"]
|
10
10
|
gem.email = ["github@tklemm.eu"]
|
11
|
-
gem.description = "Butler is a Rack Middleware that serves static assets for your Rails app."
|
12
|
-
gem.summary = "Butler
|
11
|
+
gem.description = "Butler is a Rack Middleware that serves static assets for your Rails app. It allows you to set HTTP headers for individual files or folders based on rules."
|
12
|
+
gem.summary = "butler_static-#{ Butler::VERSION }"
|
13
13
|
gem.homepage = "https://github.com/thomasklemm/butler"
|
14
14
|
|
15
15
|
gem.files = `git ls-files`.split($/)
|
@@ -19,6 +19,7 @@ Gem::Specification.new do |gem|
|
|
19
19
|
|
20
20
|
# Dependencies
|
21
21
|
gem.add_dependency 'rack'
|
22
|
+
gem.add_dependency 'rails', '>= 3.1.0'
|
22
23
|
|
23
24
|
# Tests
|
24
25
|
gem.add_development_dependency 'minitest'
|
@@ -26,6 +27,6 @@ Gem::Specification.new do |gem|
|
|
26
27
|
gem.add_development_dependency 'turn'
|
27
28
|
# Only ActiveSupport and ActionController nescessary
|
28
29
|
# gem.add_development_dependency 'rails', '~> 3.2.8'
|
29
|
-
gem.add_development_dependency 'activesupport', '~> 3.2.8'
|
30
|
-
gem.add_development_dependency 'actionpack', '~> 3.2.8'
|
30
|
+
# gem.add_development_dependency 'activesupport', '~> 3.2.8'
|
31
|
+
# gem.add_development_dependency 'actionpack', '~> 3.2.8'
|
31
32
|
end
|
data/lib/butler.rb
CHANGED
data/lib/butler/railtie.rb
CHANGED
@@ -1,6 +1,30 @@
|
|
1
|
-
require 'butler'
|
2
|
-
|
3
1
|
module Butler
|
4
|
-
class Railtie < Rails::Railtie
|
2
|
+
class Railtie < ::Rails::Railtie
|
3
|
+
puts 'Processing Railtie...'
|
4
|
+
# config.butler = ActiveSupport::OrderedOptions.new # enable namespaced configuration in Rails environments
|
5
|
+
|
6
|
+
# # Config
|
7
|
+
# use_butler = Rails.application.config.assets.use_butler || nil
|
8
|
+
# path = Rails.application.config.paths['public'].first
|
9
|
+
|
10
|
+
# header_rules = Rails.application.config.assets.header_rules || {}
|
11
|
+
# options = { header_rules: header_rules }
|
12
|
+
|
13
|
+
initializer "butler.configure_rails_initialization" do |app|
|
14
|
+
app.middleware.swap 'ActionDispatch::Static', 'Butler::Static'
|
15
|
+
raise app.inspect
|
16
|
+
# if use_butler
|
17
|
+
# if defined? ActionDispatch::Static
|
18
|
+
# if defined? Rack::Cache # will not work
|
19
|
+
# app.config.middleware.delete ActionDispatch::Static
|
20
|
+
# app.config.middleware.insert_before Rack::Cache, Butler::Static, path, options
|
21
|
+
# else
|
22
|
+
# app.config.middleware.swap ActionDispatch::Static, Butler::Static, path, options
|
23
|
+
# end
|
24
|
+
# else
|
25
|
+
# app.config.middleware.use Butler::Static, path, options
|
26
|
+
# end
|
27
|
+
# end
|
28
|
+
end
|
5
29
|
end
|
6
30
|
end
|
data/lib/butler/static.rb
CHANGED
@@ -34,7 +34,8 @@ module Butler
|
|
34
34
|
# the request will bubble up to the Rails stack to decide
|
35
35
|
# how to handle it
|
36
36
|
#
|
37
|
-
# Usage:
|
37
|
+
# Usage with Rails:
|
38
|
+
# # config/environment/production.rb
|
38
39
|
# config.middleware.delete ActionDispatch::Static
|
39
40
|
# config.middleware.insert_before Rack::Cache, Butler::Static
|
40
41
|
#
|
@@ -75,13 +76,12 @@ module Butler
|
|
75
76
|
# general global HTTP header settings
|
76
77
|
#
|
77
78
|
class Static
|
78
|
-
def initialize(app, path
|
79
|
-
@app = app
|
80
|
-
|
81
|
-
|
82
|
-
header_rules =
|
83
|
-
|
84
|
-
@file_handler = Butler::Handler.new(path, header_rules: header_rules)
|
79
|
+
def initialize(app, path, options={})
|
80
|
+
@app = app # Rails app
|
81
|
+
config = {}
|
82
|
+
# Rules for setting HTTP Headers on files
|
83
|
+
config[:header_rules] = options[:header_rules] if options[:header_rules]
|
84
|
+
@file_handler = Butler::Handler.new(path, config)
|
85
85
|
end
|
86
86
|
|
87
87
|
def call(env)
|
data/lib/butler/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
1
|
module Butler
|
2
|
-
VERSION = "0.0.
|
3
|
-
end
|
2
|
+
VERSION = "0.0.8.alpha.20"
|
3
|
+
end
|
metadata
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: butler_static
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.0.8.alpha.20
|
5
|
+
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Thomas Klemm
|
@@ -28,23 +28,23 @@ dependencies:
|
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: '0'
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
|
-
name:
|
31
|
+
name: rails
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
33
33
|
none: false
|
34
34
|
requirements:
|
35
35
|
- - ! '>='
|
36
36
|
- !ruby/object:Gem::Version
|
37
|
-
version:
|
38
|
-
type: :
|
37
|
+
version: 3.1.0
|
38
|
+
type: :runtime
|
39
39
|
prerelease: false
|
40
40
|
version_requirements: !ruby/object:Gem::Requirement
|
41
41
|
none: false
|
42
42
|
requirements:
|
43
43
|
- - ! '>='
|
44
44
|
- !ruby/object:Gem::Version
|
45
|
-
version:
|
45
|
+
version: 3.1.0
|
46
46
|
- !ruby/object:Gem::Dependency
|
47
|
-
name:
|
47
|
+
name: minitest
|
48
48
|
requirement: !ruby/object:Gem::Requirement
|
49
49
|
none: false
|
50
50
|
requirements:
|
@@ -60,7 +60,7 @@ dependencies:
|
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
62
|
- !ruby/object:Gem::Dependency
|
63
|
-
name:
|
63
|
+
name: guard-minitest
|
64
64
|
requirement: !ruby/object:Gem::Requirement
|
65
65
|
none: false
|
66
66
|
requirements:
|
@@ -76,39 +76,24 @@ dependencies:
|
|
76
76
|
- !ruby/object:Gem::Version
|
77
77
|
version: '0'
|
78
78
|
- !ruby/object:Gem::Dependency
|
79
|
-
name:
|
80
|
-
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
|
-
requirements:
|
83
|
-
- - ~>
|
84
|
-
- !ruby/object:Gem::Version
|
85
|
-
version: 3.2.8
|
86
|
-
type: :development
|
87
|
-
prerelease: false
|
88
|
-
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
|
-
requirements:
|
91
|
-
- - ~>
|
92
|
-
- !ruby/object:Gem::Version
|
93
|
-
version: 3.2.8
|
94
|
-
- !ruby/object:Gem::Dependency
|
95
|
-
name: actionpack
|
79
|
+
name: turn
|
96
80
|
requirement: !ruby/object:Gem::Requirement
|
97
81
|
none: false
|
98
82
|
requirements:
|
99
|
-
- -
|
83
|
+
- - ! '>='
|
100
84
|
- !ruby/object:Gem::Version
|
101
|
-
version:
|
85
|
+
version: '0'
|
102
86
|
type: :development
|
103
87
|
prerelease: false
|
104
88
|
version_requirements: !ruby/object:Gem::Requirement
|
105
89
|
none: false
|
106
90
|
requirements:
|
107
|
-
- -
|
91
|
+
- - ! '>='
|
108
92
|
- !ruby/object:Gem::Version
|
109
|
-
version:
|
93
|
+
version: '0'
|
110
94
|
description: Butler is a Rack Middleware that serves static assets for your Rails
|
111
|
-
app.
|
95
|
+
app. It allows you to set HTTP headers for individual files or folders based on
|
96
|
+
rules.
|
112
97
|
email:
|
113
98
|
- github@tklemm.eu
|
114
99
|
executables: []
|
@@ -175,16 +160,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
175
160
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
176
161
|
none: false
|
177
162
|
requirements:
|
178
|
-
- - ! '
|
163
|
+
- - ! '>'
|
179
164
|
- !ruby/object:Gem::Version
|
180
|
-
version:
|
165
|
+
version: 1.3.1
|
181
166
|
requirements: []
|
182
167
|
rubyforge_project:
|
183
168
|
rubygems_version: 1.8.23
|
184
169
|
signing_key:
|
185
170
|
specification_version: 3
|
186
|
-
summary:
|
187
|
-
It allows you to set HTTP headers for individual files or folders based on rules.
|
171
|
+
summary: butler_static-0.0.8.alpha.20
|
188
172
|
test_files:
|
189
173
|
- spec/butler/asset_spec.rb
|
190
174
|
- spec/butler/files/index.html
|