rack-zippy 2.0.0 → 2.0.1
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/CHANGELOG.md +3 -0
- data/README.md +32 -7
- data/bin/rake +16 -0
- data/lib/rack-zippy.rb +22 -8
- data/lib/rack-zippy/serveable_file.rb +25 -25
- data/lib/rack-zippy/version.rb +1 -1
- data/test/asset_server_test.rb +21 -9
- data/test/serveable_file_test.rb +20 -1
- metadata +11 -3
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
## 2.0.1 / 2014-12-15
|
2
|
+
- New `:max_age_fallback` (in seconds) option
|
3
|
+
|
1
4
|
## 2.0.0 / 2014-12-07
|
2
5
|
- Rack Zippy now works cleanly with all Rack apps, including Rails apps ([#23](https://github.com/eliotsykes/rack-zippy/issues/23))
|
3
6
|
- Decomposed AssetServer into AssetServer, ServeableFile, and AssetCompiler classes
|
data/README.md
CHANGED
@@ -66,6 +66,24 @@ In `config.ru`:
|
|
66
66
|
Follow the installation instructions above and rack-zippy will serve any static assets, including gzipped assets, from your
|
67
67
|
application's public/ directory and will respond with sensible caching headers.
|
68
68
|
|
69
|
+
### Options
|
70
|
+
|
71
|
+
#### max_age_fallback
|
72
|
+
|
73
|
+
`max_age_fallback`, is an integer value in seconds that should be used as the max_age fallback for files served by rack-zippy that live **outside** the `/assets` subdirectory *and* aren't `/favicon.ico`.
|
74
|
+
|
75
|
+
A typical use for `max_age_fallback` is to define how long the cache lifetime for static HTML files served by rack-zippy should be. For one of my sites I have this set to 10 minutes:
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
max_age_in_secs = 10*60 # 10 mins = 600 secs
|
79
|
+
use Rack::Zippy::AssetServer, asset_root, max_age_fallback: max_age_in_secs
|
80
|
+
```
|
81
|
+
|
82
|
+
Any files given the `max_age_fallback` would have the following `Cache-Control` header:
|
83
|
+
|
84
|
+
```
|
85
|
+
Cache-Control: public, max-age=600
|
86
|
+
```
|
69
87
|
|
70
88
|
## Troubleshooting
|
71
89
|
|
@@ -75,6 +93,12 @@ Check your environment (in config/environments/) does not have `serve_static_ass
|
|
75
93
|
|
76
94
|
config.serve_static_assets = false # Oops! Should be set to true for rack-zippy
|
77
95
|
|
96
|
+
##### NameError: uninitialized constant Rack::Zippy
|
97
|
+
|
98
|
+
- Check `Gemfile` doesn't limit rack-zippy to a subset of environment groups
|
99
|
+
- Run `bundle install`
|
100
|
+
- Check `Gemfile.lock` contains an entry for rack-zippy
|
101
|
+
|
78
102
|
|
79
103
|
## Contributing
|
80
104
|
|
@@ -112,18 +136,19 @@ Cleanup time! When you’re finished testing, delete the local override and set
|
|
112
136
|
|
113
137
|
## Contributors
|
114
138
|
|
115
|
-
-
|
116
|
-
-
|
117
|
-
-
|
139
|
+
- Eliot Sykes https://eliotsykes.com
|
140
|
+
- Kieran Topping https://github.com/ktopping
|
141
|
+
- Luke Wendling https://github.com/lukewendling
|
118
142
|
|
119
143
|
|
120
144
|
## Releasing a new gem
|
121
145
|
|
122
|
-
1. Update pre-release version to the release version in lib/rack-zippy/version.rb
|
123
|
-
2. Update CHANGELOG.md and Contributors in README.md
|
146
|
+
1. Update pre-release version to the release version in `lib/rack-zippy/version.rb`, e.g. `1.0.1.pre` becomes `1.0.1`
|
147
|
+
2. Update `CHANGELOG.md` version and date. Update Contributors in `README.md`.
|
124
148
|
3. Tests pass? (`rake test`)
|
125
149
|
4. Build the gem (`rake build`)
|
126
150
|
5. Release on rubygems.org (`rake release`)
|
127
|
-
6. Update version to the next pre-release version in lib/rack-zippy/version.rb
|
128
|
-
7.
|
151
|
+
6. Update version to the next pre-release version in `lib/rack-zippy/version.rb`, e.g. `1.0.1` becomes `1.0.2.pre`.
|
152
|
+
7. Add new heading to `CHANGELOG` for the next pre-release
|
153
|
+
8. Commit and push the updated `lib/rack-zippy/version.rb` and `CHANGELOG` files.
|
129
154
|
|
data/bin/rake
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This file was generated by Bundler.
|
4
|
+
#
|
5
|
+
# The application 'rake' is installed as part of a gem, and
|
6
|
+
# this file is here to facilitate running it.
|
7
|
+
#
|
8
|
+
|
9
|
+
require 'pathname'
|
10
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
11
|
+
Pathname.new(__FILE__).realpath)
|
12
|
+
|
13
|
+
require 'rubygems'
|
14
|
+
require 'bundler/setup'
|
15
|
+
|
16
|
+
load Gem.bin_path('rake', 'rake')
|
data/lib/rack-zippy.rb
CHANGED
@@ -14,7 +14,7 @@ module Rack
|
|
14
14
|
|
15
15
|
HTTP_STATUS_CODE_OK = 200
|
16
16
|
|
17
|
-
def initialize(app, asset_root=nil)
|
17
|
+
def initialize(app, asset_root=nil, options={})
|
18
18
|
if asset_root.nil?
|
19
19
|
if RailsAssetCompiler.rails_env?
|
20
20
|
asset_root = ::Rails.public_path
|
@@ -24,8 +24,11 @@ module Rack
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
@app = app
|
27
|
-
|
28
|
-
@
|
27
|
+
|
28
|
+
@options = {
|
29
|
+
:asset_compiler => resolve_asset_compiler,
|
30
|
+
:asset_root => asset_root
|
31
|
+
}.merge(options)
|
29
32
|
end
|
30
33
|
|
31
34
|
def call(env)
|
@@ -33,12 +36,15 @@ module Rack
|
|
33
36
|
|
34
37
|
return not_found_response if path_info =~ ILLEGAL_PATH_REGEX
|
35
38
|
|
36
|
-
|
39
|
+
serveable_file_options = {
|
37
40
|
:path_info => path_info,
|
38
|
-
:asset_root =>
|
39
|
-
:asset_compiler =>
|
40
|
-
:include_gzipped => client_accepts_gzip?(env)
|
41
|
-
|
41
|
+
:asset_root => asset_root,
|
42
|
+
:asset_compiler => asset_compiler,
|
43
|
+
:include_gzipped => client_accepts_gzip?(env),
|
44
|
+
:max_age_fallback => @options[:max_age_fallback]
|
45
|
+
}
|
46
|
+
|
47
|
+
serveable_file = ServeableFile.find_first(serveable_file_options)
|
42
48
|
|
43
49
|
if serveable_file
|
44
50
|
return [HTTP_STATUS_CODE_OK, serveable_file.headers, serveable_file.response_body]
|
@@ -47,6 +53,10 @@ module Rack
|
|
47
53
|
@app.call(env)
|
48
54
|
end
|
49
55
|
|
56
|
+
def asset_root
|
57
|
+
@options[:asset_root]
|
58
|
+
end
|
59
|
+
|
50
60
|
private
|
51
61
|
|
52
62
|
ACCEPTS_GZIP_REGEX = /\bgzip\b/
|
@@ -62,6 +72,10 @@ module Rack
|
|
62
72
|
return asset_compiler_class.new
|
63
73
|
end
|
64
74
|
|
75
|
+
def asset_compiler
|
76
|
+
@options[:asset_compiler]
|
77
|
+
end
|
78
|
+
|
65
79
|
def not_found_response
|
66
80
|
[404, {}, ['Not Found']]
|
67
81
|
end
|
@@ -11,6 +11,7 @@ module Rack
|
|
11
11
|
@full_path_info = options[:full_path_info]
|
12
12
|
@has_encoding_variants = options[:has_encoding_variants]
|
13
13
|
@is_gzipped = options[:is_gzipped]
|
14
|
+
@max_age_fallback = options[:max_age_fallback] || SECONDS_IN[:day]
|
14
15
|
end
|
15
16
|
|
16
17
|
def headers
|
@@ -26,17 +27,17 @@ module Rack
|
|
26
27
|
|
27
28
|
def cache_headers
|
28
29
|
case full_path_info
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
30
|
+
when PRECOMPILED_ASSETS_SUBDIR_REGEX
|
31
|
+
lifetime_in_secs = SECONDS_IN[:year]
|
32
|
+
last_modified = CACHE_FRIENDLY_LAST_MODIFIED
|
33
|
+
when '/favicon.ico'
|
34
|
+
lifetime_in_secs = SECONDS_IN[:month]
|
35
|
+
last_modified = CACHE_FRIENDLY_LAST_MODIFIED
|
36
|
+
else
|
37
|
+
lifetime_in_secs = @max_age_fallback
|
37
38
|
end
|
38
39
|
|
39
|
-
headers = { 'Cache-Control' => "public, max-age=#{
|
40
|
+
headers = { 'Cache-Control' => "public, max-age=#{lifetime_in_secs}" }
|
40
41
|
headers['Last-Modified'] = last_modified if last_modified
|
41
42
|
|
42
43
|
return headers
|
@@ -49,7 +50,7 @@ module Rack
|
|
49
50
|
def self.find_first(options)
|
50
51
|
asset_compiler = options[:asset_compiler]
|
51
52
|
path_info = options[:path_info].chomp('/')
|
52
|
-
|
53
|
+
|
53
54
|
return nil if asset_compiler.compiles?(path_info)
|
54
55
|
|
55
56
|
asset_root = options[:asset_root]
|
@@ -77,20 +78,19 @@ module Rack
|
|
77
78
|
|
78
79
|
has_encoding_variants = gzipped_file_present
|
79
80
|
|
81
|
+
init_options = {
|
82
|
+
:path => file_path,
|
83
|
+
:full_path_info => full_path_info,
|
84
|
+
:has_encoding_variants => has_encoding_variants,
|
85
|
+
:max_age_fallback => options[:max_age_fallback]
|
86
|
+
}
|
87
|
+
|
80
88
|
if include_gzipped && gzipped_file_present
|
81
|
-
|
82
|
-
|
83
|
-
:full_path_info => full_path_info,
|
84
|
-
:has_encoding_variants => has_encoding_variants,
|
85
|
-
:is_gzipped => true
|
86
|
-
)
|
89
|
+
init_options[:path] = gzipped_file_path
|
90
|
+
init_options[:is_gzipped] = true
|
87
91
|
end
|
88
92
|
|
89
|
-
return ServeableFile.new(
|
90
|
-
:path => file_path,
|
91
|
-
:full_path_info => full_path_info,
|
92
|
-
:has_encoding_variants => has_encoding_variants
|
93
|
-
)
|
93
|
+
return ServeableFile.new(init_options)
|
94
94
|
end
|
95
95
|
|
96
96
|
def self.has_static_extension?(path)
|
@@ -116,15 +116,15 @@ module Rack
|
|
116
116
|
end
|
117
117
|
alias_method :eql?, :==
|
118
118
|
|
119
|
-
|
119
|
+
private
|
120
120
|
|
121
121
|
# Old last-modified headers encourage caching via browser heuristics. Use it for year-long cached assets.
|
122
122
|
CACHE_FRIENDLY_LAST_MODIFIED = 'Mon, 10 Jan 2005 10:00:00 GMT'
|
123
123
|
|
124
124
|
SECONDS_IN = {
|
125
|
-
|
126
|
-
|
127
|
-
|
125
|
+
:day => 24*60*60,
|
126
|
+
:month => 31*(24*60*60),
|
127
|
+
:year => 365*(24*60*60)
|
128
128
|
}.freeze
|
129
129
|
|
130
130
|
DEFAULT_STATIC_EXTENSION = '.html'.freeze
|
data/lib/rack-zippy/version.rb
CHANGED
data/test/asset_server_test.rb
CHANGED
@@ -14,6 +14,7 @@ module Rack
|
|
14
14
|
|
15
15
|
def teardown
|
16
16
|
revert_to_original_working_directory
|
17
|
+
@app = nil
|
17
18
|
end
|
18
19
|
|
19
20
|
def test_serves_static_file_as_directory
|
@@ -43,14 +44,12 @@ module Rack
|
|
43
44
|
end
|
44
45
|
|
45
46
|
def test_rails_asset_compiler_set_when_rails_environment_detected
|
46
|
-
|
47
|
-
assert_equal RailsAssetCompiler, asset_compiler.class
|
47
|
+
assert_equal RailsAssetCompiler, app.send(:asset_compiler).class
|
48
48
|
end
|
49
49
|
|
50
50
|
def test_null_asset_compiler_set_when_no_rails_environment_detected
|
51
51
|
exit_rails_env
|
52
|
-
|
53
|
-
assert_equal NullAssetCompiler, asset_compiler.class
|
52
|
+
assert_equal NullAssetCompiler, app.send(:asset_compiler).class
|
54
53
|
end
|
55
54
|
|
56
55
|
def test_request_for_non_asset_path_beginning_with_assets_dir_name_bypasses_middleware
|
@@ -255,23 +254,36 @@ module Rack
|
|
255
254
|
|
256
255
|
def test_asset_root_constructor_arg_accepts_string
|
257
256
|
asset_server = AssetServer.new(create_rack_app, '/custom/asset/root')
|
258
|
-
assert_equal '/custom/asset/root', asset_server.
|
257
|
+
assert_equal '/custom/asset/root', asset_server.asset_root
|
259
258
|
end
|
260
259
|
|
261
260
|
def test_default_asset_root_is_rails_public_path
|
262
261
|
Rails.public_path = '/unexpected/absolute/path/to/public'
|
263
262
|
asset_server = AssetServer.new(create_rack_app)
|
264
|
-
assert_equal '/unexpected/absolute/path/to/public', asset_server.
|
263
|
+
assert_equal '/unexpected/absolute/path/to/public', asset_server.asset_root
|
264
|
+
end
|
265
|
+
|
266
|
+
def test_asset_server_accepts_max_age_fallback_option
|
267
|
+
fallback_in_secs = 1234
|
268
|
+
@app = AssetServer.new(
|
269
|
+
create_rack_app, asset_root, max_age_fallback: fallback_in_secs
|
270
|
+
)
|
271
|
+
|
272
|
+
get '/thanks.html'
|
273
|
+
assert_equal "public, max-age=1234", last_response.headers['cache-control']
|
265
274
|
end
|
266
275
|
|
267
276
|
private
|
268
277
|
|
269
278
|
def app
|
279
|
+
return @app if @app
|
270
280
|
if in_rails_env?
|
271
|
-
|
281
|
+
@app = AssetServer.new(create_rack_app)
|
282
|
+
else
|
283
|
+
# In a pure rack app, non-Rails env
|
284
|
+
@app = AssetServer.new(create_rack_app, asset_root)
|
272
285
|
end
|
273
|
-
|
274
|
-
return AssetServer.new(create_rack_app, asset_root)
|
286
|
+
return @app
|
275
287
|
end
|
276
288
|
|
277
289
|
def create_rack_app
|
data/test/serveable_file_test.rb
CHANGED
@@ -30,6 +30,24 @@ module Rack
|
|
30
30
|
assert_last_modified cache_headers, nil
|
31
31
|
end
|
32
32
|
|
33
|
+
def test_max_age_fallback_used_for_cache_headers
|
34
|
+
|
35
|
+
ten_mins_in_secs = 10*60
|
36
|
+
|
37
|
+
serveable_file = ServeableFile.new(
|
38
|
+
:full_path_info => "/thanks.html",
|
39
|
+
:path => "#{asset_root}/thanks.html",
|
40
|
+
:has_encoding_variants => false,
|
41
|
+
:is_gzipped => false,
|
42
|
+
:max_age_fallback => ten_mins_in_secs
|
43
|
+
)
|
44
|
+
|
45
|
+
cache_headers = serveable_file.cache_headers
|
46
|
+
|
47
|
+
assert_cache_max_age cache_headers, ten_mins_in_secs
|
48
|
+
assert_last_modified cache_headers, nil
|
49
|
+
end
|
50
|
+
|
33
51
|
def test_cache_max_age_is_month_for_root_favicon
|
34
52
|
serveable_file = ServeableFile.new(
|
35
53
|
:full_path_info => "/favicon.ico",
|
@@ -460,7 +478,8 @@ module Rack
|
|
460
478
|
end
|
461
479
|
|
462
480
|
def assert_cache_max_age(headers, expected_duration)
|
463
|
-
|
481
|
+
duration_in_secs = DURATIONS_IN_SECS[expected_duration] || expected_duration
|
482
|
+
assert_equal "public, max-age=#{duration_in_secs}", headers['Cache-Control']
|
464
483
|
end
|
465
484
|
|
466
485
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-zippy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,13 +9,14 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-12-
|
12
|
+
date: 2014-12-15 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: Rack middleware for serving static gzipped assets generated by the Rails
|
15
15
|
asset pipeline
|
16
16
|
email:
|
17
17
|
- e@jetbootlabs.com
|
18
|
-
executables:
|
18
|
+
executables:
|
19
|
+
- rake
|
19
20
|
extensions: []
|
20
21
|
extra_rdoc_files: []
|
21
22
|
files:
|
@@ -26,6 +27,7 @@ files:
|
|
26
27
|
- LICENSE
|
27
28
|
- README.md
|
28
29
|
- Rakefile
|
30
|
+
- bin/rake
|
29
31
|
- lib/rack-zippy.rb
|
30
32
|
- lib/rack-zippy/asset_compiler.rb
|
31
33
|
- lib/rack-zippy/serveable_file.rb
|
@@ -63,12 +65,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
63
65
|
- - ! '>='
|
64
66
|
- !ruby/object:Gem::Version
|
65
67
|
version: '0'
|
68
|
+
segments:
|
69
|
+
- 0
|
70
|
+
hash: -1213525352478824492
|
66
71
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
72
|
none: false
|
68
73
|
requirements:
|
69
74
|
- - ! '>='
|
70
75
|
- !ruby/object:Gem::Version
|
71
76
|
version: '0'
|
77
|
+
segments:
|
78
|
+
- 0
|
79
|
+
hash: -1213525352478824492
|
72
80
|
requirements: []
|
73
81
|
rubyforge_project:
|
74
82
|
rubygems_version: 1.8.23.2
|