rack-zippy 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|