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 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
- - [Eliot Sykes](https://github.com/eliotsykes)
116
- - [Kieran Topping](https://github.com/ktopping)
117
- - [Luke Wendling](https://github.com/lukewendling)
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, e.g. '1.0.1.pre' becomes '1.0.1'
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, e.g. '1.0.1' becomes '1.0.2.pre'.
128
- 7. Commit and push the updated lib/rack-zippy/version.rb.
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
- @asset_root = asset_root
28
- @asset_compiler = resolve_asset_compiler
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
- serveable_file = ServeableFile.find_first(
39
+ serveable_file_options = {
37
40
  :path_info => path_info,
38
- :asset_root => @asset_root,
39
- :asset_compiler => @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
- when PRECOMPILED_ASSETS_SUBDIR_REGEX
30
- lifetime = :year
31
- last_modified = CACHE_FRIENDLY_LAST_MODIFIED
32
- when '/favicon.ico'
33
- lifetime = :month
34
- last_modified = CACHE_FRIENDLY_LAST_MODIFIED
35
- else
36
- lifetime = :day
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=#{SECONDS_IN[lifetime]}" }
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
- return ServeableFile.new(
82
- :path => gzipped_file_path,
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
- private
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
- :day => 24*60*60,
126
- :month => 31*(24*60*60),
127
- :year => 365*(24*60*60)
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
@@ -1,5 +1,5 @@
1
1
  module Rack
2
2
  module Zippy
3
- VERSION = '2.0.0'
3
+ VERSION = '2.0.1'
4
4
  end
5
5
  end
@@ -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
- asset_compiler = app.instance_variable_get('@asset_compiler')
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
- asset_compiler = app.instance_variable_get('@asset_compiler')
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.instance_variable_get('@asset_root')
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.instance_variable_get('@asset_root')
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
- return AssetServer.new(create_rack_app)
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
- # In a pure rack app, non-Rails env
274
- return AssetServer.new(create_rack_app, asset_root)
286
+ return @app
275
287
  end
276
288
 
277
289
  def create_rack_app
@@ -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
- assert_equal "public, max-age=#{DURATIONS_IN_SECS[expected_duration]}", headers['Cache-Control']
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.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-07 00:00:00.000000000 Z
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