rack-zippy 0.1.0
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/.gitignore +21 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +9 -0
- data/LICENSE +20 -0
- data/README.md +39 -0
- data/Rakefile +7 -0
- data/lib/rack-zippy.rb +108 -0
- data/lib/rack-zippy/version.rb +5 -0
- data/rack-zippy.gemspec +19 -0
- data/test/asset_server_test.rb +283 -0
- data/test/public/assets/application.css +3 -0
- data/test/public/assets/application.css.gz +0 -0
- data/test/public/assets/application.js +1 -0
- data/test/public/assets/application.js.gz +0 -0
- data/test/public/assets/favicon.ico +0 -0
- data/test/public/assets/rails.png +0 -0
- data/test/public/favicon.ico +0 -0
- data/test/public/robots.txt +1 -0
- data/test/public/thanks.html +6 -0
- data/test/test_helper.rb +18 -0
- metadata +78 -0
data/.gitignore
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
.idea/*
|
19
|
+
*.iml
|
20
|
+
.ruby-version
|
21
|
+
vendor
|
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2013 Eliot Sykes
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
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, FITNESS
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# rack-zippy
|
2
|
+
|
3
|
+
rack-zippy is a Rack middleware for serving static gzipped assets precompiled by the Rails asset pipeline into the public/assets directory. Use it
|
4
|
+
on Heroku if you want to serve the precompiled gzipped assets to gzip-capable clients with sensible caching headers.
|
5
|
+
|
6
|
+
By default, Rails + Heroku will not serve *.gz assets even though they are generated at deploy time.
|
7
|
+
|
8
|
+
rack-zippy replaces the ActionDispatch::Static middleware used by Rails, which is not capable of serving the gzipped assets created by
|
9
|
+
the `rake assets:precompile` task. rack-zippy will serve non-gzipped assets where they are not available or not supported by the
|
10
|
+
requesting client.
|
11
|
+
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
Add this line to your application's Gemfile:
|
15
|
+
|
16
|
+
gem 'rack-zippy'
|
17
|
+
|
18
|
+
And then execute:
|
19
|
+
|
20
|
+
$ bundle
|
21
|
+
|
22
|
+
Add this line to config/application.rb:
|
23
|
+
|
24
|
+
config.middleware.swap(ActionDispatch::Static, Rack::Zippy::AssetServer)
|
25
|
+
|
26
|
+
## Usage
|
27
|
+
|
28
|
+
Follow the installation instructions above and rack-zippy will serve any static assets, including gzipped assets, from your
|
29
|
+
application's public/ directory and will respond with sensible caching headers.
|
30
|
+
|
31
|
+
## Contributing
|
32
|
+
|
33
|
+
1. Fork it
|
34
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
35
|
+
3. Run tests (`rake test`)
|
36
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
37
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
38
|
+
5. Create new Pull Request
|
39
|
+
|
data/Rakefile
ADDED
data/lib/rack-zippy.rb
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
require "rack-zippy/version"
|
2
|
+
|
3
|
+
module Rack
|
4
|
+
module Zippy
|
5
|
+
class AssetServer
|
6
|
+
|
7
|
+
def initialize(app, asset_root='public')
|
8
|
+
@app = app
|
9
|
+
@asset_root = asset_root
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(env)
|
13
|
+
path_info = env['PATH_INFO']
|
14
|
+
assert_legal_path path_info
|
15
|
+
|
16
|
+
if serve?(path_info)
|
17
|
+
|
18
|
+
file_path = "#{@asset_root}#{path_info}"
|
19
|
+
|
20
|
+
if ::File.exists?(file_path)
|
21
|
+
headers = {
|
22
|
+
'Content-Type' => Rack::Mime.mime_type(::File.extname(path_info)),
|
23
|
+
'Last-Modified' => 'Mon, 10 Jan 2005 10:00:00 GMT',
|
24
|
+
'Cache-Control' => "public, max-age=#{max_age_in_secs(path_info)}"
|
25
|
+
}
|
26
|
+
|
27
|
+
gzipped_file_path = "#{file_path}.gz"
|
28
|
+
gzipped_file_present = ::File.exists?(gzipped_file_path)
|
29
|
+
|
30
|
+
if gzipped_file_present
|
31
|
+
headers['Vary'] = 'Accept-Encoding'
|
32
|
+
|
33
|
+
if client_accepts_gzip?(env)
|
34
|
+
file_path = gzipped_file_path
|
35
|
+
headers['Content-Encoding'] = 'gzip'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
status = 200
|
40
|
+
headers['Content-Length'] = ::File.size(file_path).to_s
|
41
|
+
response_body = [::File.read(file_path)]
|
42
|
+
else
|
43
|
+
status = 404
|
44
|
+
headers = {}
|
45
|
+
response_body = ['Not Found']
|
46
|
+
end
|
47
|
+
return [status, headers, response_body]
|
48
|
+
end
|
49
|
+
|
50
|
+
@app.call(env)
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
SECONDS_IN = {
|
56
|
+
:day => 24*60*60,
|
57
|
+
:month => 31*(24*60*60),
|
58
|
+
:year => 365*(24*60*60)
|
59
|
+
}.freeze
|
60
|
+
|
61
|
+
STATIC_EXTENSION_REGEX = /\.(?:css|js|html|htm|txt|ico|png|jpg|jpeg|gif|pdf|svg|zip|gz|eps|psd|ai)\z/i
|
62
|
+
|
63
|
+
PRECOMPILED_ASSETS_SUBDIR_REGEX = /\A\/assets\//
|
64
|
+
|
65
|
+
ACCEPTS_GZIP_REGEX = /\bgzip\b/
|
66
|
+
|
67
|
+
ILLEGAL_PATH_REGEX = /(\.\.|\/\.)/
|
68
|
+
|
69
|
+
def serve?(path_info)
|
70
|
+
is_compilable_asset = (path_info =~ PRECOMPILED_ASSETS_SUBDIR_REGEX)
|
71
|
+
if is_compilable_asset
|
72
|
+
return should_assets_be_compiled_already?
|
73
|
+
end
|
74
|
+
return has_static_extension?(path_info)
|
75
|
+
end
|
76
|
+
|
77
|
+
def should_assets_be_compiled_already?
|
78
|
+
!::Rails.configuration.assets.compile
|
79
|
+
end
|
80
|
+
|
81
|
+
def max_age_in_secs(path_info)
|
82
|
+
case path_info
|
83
|
+
when PRECOMPILED_ASSETS_SUBDIR_REGEX
|
84
|
+
max_age = SECONDS_IN[:year]
|
85
|
+
when '/favicon.ico'
|
86
|
+
max_age = SECONDS_IN[:month]
|
87
|
+
else
|
88
|
+
max_age = SECONDS_IN[:day]
|
89
|
+
end
|
90
|
+
|
91
|
+
return max_age
|
92
|
+
end
|
93
|
+
|
94
|
+
def client_accepts_gzip?(rack_env)
|
95
|
+
rack_env['HTTP_ACCEPT_ENCODING'] =~ ACCEPTS_GZIP_REGEX
|
96
|
+
end
|
97
|
+
|
98
|
+
def has_static_extension?(path)
|
99
|
+
path =~ STATIC_EXTENSION_REGEX
|
100
|
+
end
|
101
|
+
|
102
|
+
def assert_legal_path(path_info)
|
103
|
+
raise SecurityError.new('Illegal path requested') if path_info =~ ILLEGAL_PATH_REGEX
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
data/rack-zippy.gemspec
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'rack-zippy/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "rack-zippy"
|
8
|
+
gem.version = Rack::Zippy::VERSION
|
9
|
+
gem.authors = ["Eliot Sykes"]
|
10
|
+
gem.email = ["e@jetbootlabs.com"]
|
11
|
+
gem.description = %q{Rack middleware for serving static gzipped assets generated by the Rails asset pipeline}
|
12
|
+
gem.summary = %q{Rack middleware for serving static gzipped assets generated by the Rails asset pipeline}
|
13
|
+
gem.homepage = "https://github.com/eliotsykes/rack-zippy"
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
end
|
@@ -0,0 +1,283 @@
|
|
1
|
+
require_relative 'test_helper'
|
2
|
+
|
3
|
+
class Rack::Zippy::AssetServerTest < Test::Unit::TestCase
|
4
|
+
include Rack::Test::Methods
|
5
|
+
|
6
|
+
def setup
|
7
|
+
ensure_correct_working_directory
|
8
|
+
::Rails.configuration.assets.compile = false
|
9
|
+
end
|
10
|
+
|
11
|
+
def teardown
|
12
|
+
revert_to_original_working_directory
|
13
|
+
end
|
14
|
+
|
15
|
+
def app
|
16
|
+
response = 'Up above the streets and houses'
|
17
|
+
headers = {}
|
18
|
+
status = 200
|
19
|
+
rack_app = lambda { |env| [status, headers, response] }
|
20
|
+
Rack::Zippy::AssetServer.new(rack_app)
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_does_not_serve_assets_subdir_request_when_assets_compile_enabled
|
24
|
+
::Rails.configuration.assets.compile = true
|
25
|
+
get '/assets/application.css'
|
26
|
+
assert_response_ok
|
27
|
+
assert_equal 'Up above the streets and houses', last_response.body
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_serve_returns_true_if_request_has_static_extension
|
31
|
+
assert app.send(:serve?, '/about.html')
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_serve_returns_false_if_request_does_not_have_static_extension
|
35
|
+
assert !app.send(:serve?, '/about')
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_serve_returns_true_for_assets_subdir_request_when_assets_compile_disabled
|
39
|
+
assert app.send(:serve?, '/assets/application.css')
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_serve_returns_false_for_assets_subdir_request_when_assets_compile_enabled
|
43
|
+
::Rails.configuration.assets.compile = true
|
44
|
+
assert !app.send(:serve?, '/assets/application.css')
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_should_assets_be_compiled_already_returns_false_if_assets_compile_enabled
|
48
|
+
::Rails.configuration.assets.compile = true
|
49
|
+
assert ::Rails.configuration.assets.compile
|
50
|
+
assert !app.send(:should_assets_be_compiled_already?)
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_should_assets_be_compiled_already_returns_true_if_assets_compile_disabled
|
54
|
+
assert !::Rails.configuration.assets.compile
|
55
|
+
assert app.send(:should_assets_be_compiled_already?)
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_responds_with_gzipped_css_to_gzip_capable_clients
|
59
|
+
params = {}
|
60
|
+
get '/assets/application.css', params, env_for_gzip_capable_client
|
61
|
+
assert_response_ok
|
62
|
+
assert_content_length 'public/assets/application.css.gz'
|
63
|
+
assert_content_type 'text/css'
|
64
|
+
assert_cache_max_age :year
|
65
|
+
assert_cache_friendly_last_modified
|
66
|
+
assert_equal 'gzip', last_response.headers['content-encoding']
|
67
|
+
assert_vary_accept_encoding_header
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_responds_with_gzipped_js_to_gzip_capable_clients
|
71
|
+
params = {}
|
72
|
+
get '/assets/application.js', params, env_for_gzip_capable_client
|
73
|
+
assert_response_ok
|
74
|
+
assert_content_length 'public/assets/application.js.gz'
|
75
|
+
assert_content_type 'application/javascript'
|
76
|
+
assert_cache_max_age :year
|
77
|
+
assert_cache_friendly_last_modified
|
78
|
+
assert_equal 'gzip', last_response.headers['content-encoding']
|
79
|
+
assert_vary_accept_encoding_header
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_responds_with_maximum_cache_headers_for_assets_subdir_requests
|
83
|
+
get '/assets/favicon.ico'
|
84
|
+
assert_response_ok
|
85
|
+
assert_cache_max_age :year
|
86
|
+
assert_cache_friendly_last_modified
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_responds_with_month_long_cache_headers_for_root_favicon
|
90
|
+
get '/favicon.ico'
|
91
|
+
assert_response_ok
|
92
|
+
assert_cache_max_age :month
|
93
|
+
assert_cache_friendly_last_modified
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_responds_with_day_long_cache_headers_for_robots_txt
|
97
|
+
get '/robots.txt'
|
98
|
+
assert_response_ok
|
99
|
+
assert_cache_max_age :day
|
100
|
+
assert_cache_friendly_last_modified
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_responds_with_day_long_cache_headers_for_root_html_requests
|
104
|
+
get '/thanks.html'
|
105
|
+
assert_response_ok
|
106
|
+
assert_cache_max_age :day
|
107
|
+
assert_cache_friendly_last_modified
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_max_cache_and_vary_accept_encoding_headers_present_for_css_requests_by_non_gzip_clients
|
111
|
+
get '/assets/application.css'
|
112
|
+
assert_response_ok
|
113
|
+
assert_content_length 'public/assets/application.css'
|
114
|
+
assert_content_type 'text/css'
|
115
|
+
assert_cache_max_age :year
|
116
|
+
assert_cache_friendly_last_modified
|
117
|
+
assert_nil last_response.headers['content-encoding']
|
118
|
+
assert_vary_accept_encoding_header
|
119
|
+
end
|
120
|
+
|
121
|
+
def test_max_cache_and_vary_accept_encoding_headers_present_for_js_requests_by_non_gzip_clients
|
122
|
+
get '/assets/application.js'
|
123
|
+
assert_response_ok
|
124
|
+
assert_content_type 'application/javascript'
|
125
|
+
assert_content_length 'public/assets/application.js'
|
126
|
+
assert_cache_max_age :year
|
127
|
+
assert_cache_friendly_last_modified
|
128
|
+
assert_nil last_response.headers['content-encoding']
|
129
|
+
assert_vary_accept_encoding_header
|
130
|
+
end
|
131
|
+
|
132
|
+
def test_vary_header_not_present_if_gzipped_asset_unavailable
|
133
|
+
get '/assets/rails.png'
|
134
|
+
assert_response_ok
|
135
|
+
assert_nil last_response.headers['vary']
|
136
|
+
end
|
137
|
+
|
138
|
+
def assert_raises_illegal_path_error(path)
|
139
|
+
e = assert_raises SecurityError do
|
140
|
+
get path
|
141
|
+
end
|
142
|
+
assert_equal 'Illegal path requested', e.message
|
143
|
+
end
|
144
|
+
|
145
|
+
def test_throws_exception_if_path_contains_hidden_dir
|
146
|
+
paths = ['.confidential/secret-plans.pdf', '/.you-aint-seen-me/index.html', '/nothing/.to/see/here.jpg']
|
147
|
+
paths.each do |path|
|
148
|
+
assert_raises_illegal_path_error path
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def test_throws_exception_if_path_ends_with_hidden_file
|
153
|
+
hidden_files = ['.htaccess', '/.top-secret', '/assets/.shhh']
|
154
|
+
hidden_files.each do |path|
|
155
|
+
assert_raises_illegal_path_error path
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def test_throws_exception_if_path_contains_consecutive_periods
|
160
|
+
assert_raises_illegal_path_error '/hello/../sensitive/file'
|
161
|
+
end
|
162
|
+
|
163
|
+
def test_serves_html
|
164
|
+
get '/thanks.html'
|
165
|
+
assert_response_ok
|
166
|
+
assert_content_type 'text/html'
|
167
|
+
assert_content_length 'public/thanks.html'
|
168
|
+
end
|
169
|
+
|
170
|
+
def test_serves_robots_txt
|
171
|
+
get '/robots.txt'
|
172
|
+
assert_response_ok
|
173
|
+
assert_content_type 'text/plain'
|
174
|
+
assert_content_length 'public/robots.txt'
|
175
|
+
end
|
176
|
+
|
177
|
+
def test_has_static_extension_handles_non_lowercase_chars
|
178
|
+
['pNG', 'JPEG', 'HTML', 'HtM', 'GIF', 'Ico'].each do |extension|
|
179
|
+
assert app.send(:has_static_extension?, "/some-asset.#{extension}")
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def test_has_static_extension_returns_false_for_asset_paths_without_period
|
184
|
+
['/assets/somepng', '/indexhtml', '/assets/applicationcss'].each do |path|
|
185
|
+
assert !app.send(:has_static_extension?, path)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
def test_passes_non_asset_requests_onto_app
|
190
|
+
get '/about'
|
191
|
+
assert_underlying_app_responded
|
192
|
+
end
|
193
|
+
|
194
|
+
def test_does_not_pass_not_found_asset_requests_onto_app
|
195
|
+
get '/index.html'
|
196
|
+
assert_not_found
|
197
|
+
end
|
198
|
+
|
199
|
+
def test_responds_with_favicon_in_assets_dir
|
200
|
+
get '/assets/favicon.ico'
|
201
|
+
assert_response_ok
|
202
|
+
assert_content_type 'image/vnd.microsoft.icon'
|
203
|
+
assert_content_length 'public/assets/favicon.ico'
|
204
|
+
end
|
205
|
+
|
206
|
+
def test_responds_with_favicon_at_root
|
207
|
+
get '/favicon.ico'
|
208
|
+
assert_response_ok
|
209
|
+
assert_content_type 'image/vnd.microsoft.icon'
|
210
|
+
assert_content_length 'public/favicon.ico'
|
211
|
+
end
|
212
|
+
|
213
|
+
def test_responds_404_not_found_for_non_existent_image
|
214
|
+
get '/assets/pot-of-gold.png'
|
215
|
+
assert_not_found
|
216
|
+
end
|
217
|
+
|
218
|
+
def test_responds_404_not_found_for_non_existent_css
|
219
|
+
get '/assets/unicorn.css'
|
220
|
+
assert_not_found
|
221
|
+
end
|
222
|
+
|
223
|
+
def test_responds_404_not_found_for_non_existent_js
|
224
|
+
get '/assets/dragon.js'
|
225
|
+
assert_not_found
|
226
|
+
end
|
227
|
+
|
228
|
+
private
|
229
|
+
|
230
|
+
DURATIONS_IN_SECS = {:year => 31536000, :month => 2678400, :day => 86400}.freeze
|
231
|
+
|
232
|
+
def env_for_gzip_capable_client
|
233
|
+
{'HTTP_ACCEPT_ENCODING' => 'deflate,gzip,sdch'}
|
234
|
+
end
|
235
|
+
|
236
|
+
def assert_vary_accept_encoding_header
|
237
|
+
assert_equal 'Accept-Encoding', last_response.headers['vary']
|
238
|
+
end
|
239
|
+
|
240
|
+
def assert_cache_max_age(duration)
|
241
|
+
assert_equal "public, max-age=#{DURATIONS_IN_SECS[duration]}", last_response.headers['cache-control']
|
242
|
+
end
|
243
|
+
|
244
|
+
# Browsers favour caching assets with older Last Modified dates IIRC
|
245
|
+
def assert_cache_friendly_last_modified
|
246
|
+
assert_equal 'Mon, 10 Jan 2005 10:00:00 GMT', last_response.headers['last-modified']
|
247
|
+
end
|
248
|
+
|
249
|
+
def assert_underlying_app_responded
|
250
|
+
assert_response_ok
|
251
|
+
assert_equal 'Up above the streets and houses', last_response.body
|
252
|
+
end
|
253
|
+
|
254
|
+
def assert_response_ok
|
255
|
+
assert_equal 200, last_response.status
|
256
|
+
end
|
257
|
+
|
258
|
+
def assert_content_type(expected_content_type)
|
259
|
+
assert_equal expected_content_type, last_response.headers['content-type']
|
260
|
+
end
|
261
|
+
|
262
|
+
def assert_content_length(path)
|
263
|
+
assert_equal ::File.size(path).to_s, last_response.headers['content-length']
|
264
|
+
end
|
265
|
+
|
266
|
+
def assert_not_found
|
267
|
+
assert_equal 404, last_response.status
|
268
|
+
assert_equal 'Not Found', last_response.body
|
269
|
+
end
|
270
|
+
|
271
|
+
def ensure_correct_working_directory
|
272
|
+
is_project_root_working_directory = File.exists?('rack-zippy.gemspec')
|
273
|
+
if is_project_root_working_directory
|
274
|
+
@original_dir = Dir.pwd
|
275
|
+
Dir.chdir 'test'
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
def revert_to_original_working_directory
|
280
|
+
Dir.chdir @original_dir if @original_dir
|
281
|
+
end
|
282
|
+
|
283
|
+
end
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
var zippyMessage = 'Hello World!';
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
# This is robots.txt
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
|
4
|
+
Bundler.require :default, :development
|
5
|
+
|
6
|
+
require 'test/unit'
|
7
|
+
require 'rack/test'
|
8
|
+
|
9
|
+
module Rails
|
10
|
+
|
11
|
+
@configuration = Struct.new(:assets).new
|
12
|
+
@configuration.assets = Struct.new(:compile).new
|
13
|
+
|
14
|
+
def self.configuration
|
15
|
+
@configuration
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rack-zippy
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Eliot Sykes
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-08-21 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: Rack middleware for serving static gzipped assets generated by the Rails
|
15
|
+
asset pipeline
|
16
|
+
email:
|
17
|
+
- e@jetbootlabs.com
|
18
|
+
executables: []
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- .gitignore
|
23
|
+
- CHANGELOG.md
|
24
|
+
- Gemfile
|
25
|
+
- LICENSE
|
26
|
+
- README.md
|
27
|
+
- Rakefile
|
28
|
+
- lib/rack-zippy.rb
|
29
|
+
- lib/rack-zippy/version.rb
|
30
|
+
- rack-zippy.gemspec
|
31
|
+
- test/asset_server_test.rb
|
32
|
+
- test/public/assets/application.css
|
33
|
+
- test/public/assets/application.css.gz
|
34
|
+
- test/public/assets/application.js
|
35
|
+
- test/public/assets/application.js.gz
|
36
|
+
- test/public/assets/favicon.ico
|
37
|
+
- test/public/assets/rails.png
|
38
|
+
- test/public/favicon.ico
|
39
|
+
- test/public/robots.txt
|
40
|
+
- test/public/thanks.html
|
41
|
+
- test/test_helper.rb
|
42
|
+
homepage: https://github.com/eliotsykes/rack-zippy
|
43
|
+
licenses: []
|
44
|
+
post_install_message:
|
45
|
+
rdoc_options: []
|
46
|
+
require_paths:
|
47
|
+
- lib
|
48
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ! '>='
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0'
|
60
|
+
requirements: []
|
61
|
+
rubyforge_project:
|
62
|
+
rubygems_version: 1.8.23
|
63
|
+
signing_key:
|
64
|
+
specification_version: 3
|
65
|
+
summary: Rack middleware for serving static gzipped assets generated by the Rails
|
66
|
+
asset pipeline
|
67
|
+
test_files:
|
68
|
+
- test/asset_server_test.rb
|
69
|
+
- test/public/assets/application.css
|
70
|
+
- test/public/assets/application.css.gz
|
71
|
+
- test/public/assets/application.js
|
72
|
+
- test/public/assets/application.js.gz
|
73
|
+
- test/public/assets/favicon.ico
|
74
|
+
- test/public/assets/rails.png
|
75
|
+
- test/public/favicon.ico
|
76
|
+
- test/public/robots.txt
|
77
|
+
- test/public/thanks.html
|
78
|
+
- test/test_helper.rb
|