roda 2.14.0 → 2.15.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +10 -0
- data/Rakefile +1 -1
- data/doc/release_notes/2.15.0.txt +53 -0
- data/lib/roda/plugins/assets.rb +4 -4
- data/lib/roda/plugins/content_for.rb +38 -13
- data/lib/roda/plugins/header_matchers.rb +16 -1
- data/lib/roda/plugins/public.rb +114 -0
- data/lib/roda/plugins/sinatra_helpers.rb +9 -3
- data/lib/roda/plugins/static.rb +2 -0
- data/lib/roda/version.rb +1 -1
- data/spec/all.rb +3 -0
- data/spec/plugin/_erubis_escaping_spec.rb +6 -0
- data/spec/plugin/assets_spec.rb +7 -6
- data/spec/plugin/content_for_spec.rb +24 -0
- data/spec/plugin/header_matchers_spec.rb +16 -4
- data/spec/plugin/public_spec.rb +62 -0
- data/spec/plugin/render_spec.rb +3 -2
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 625daaffa474b5553308633c41d20b76fa3096d8
|
4
|
+
data.tar.gz: 4bcfc8c8c1258f6860e8ac430ba59679b2c62c69
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2331dd19bd5efb8c3187df90917c4a23f814d52ec205b553ac1131fb39a787fffc83930ce697011cda5ac6926ab7cf31a209033dfc5589342b9410ff09b6a743
|
7
|
+
data.tar.gz: 0abd741f20b87dbe497eba823357ce323aa1d82f7a8048895afe4d5b47eefeb340e50fdf9c71daa8c9cb2c064a5e4f30cda800aa751a345f84f57d2424a6a617
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
= 2.15.0 (2016-06-13)
|
2
|
+
|
3
|
+
* Add public plugin for r.public method for serving all files in the public directory (jeremyevans)
|
4
|
+
|
5
|
+
* Make send_file in sinatra_helpers plugin work with Rack 2 (jeremyevans)
|
6
|
+
|
7
|
+
* Make :header matcher prefixes the env key with HTTP_ if application :header_matcher_prefix option is set (timothypage, jeremyevans) (#69)
|
8
|
+
|
9
|
+
* Add content_for plugin :append option to support appending to the existing content (evanleck, jeremyevans) (#66)
|
10
|
+
|
1
11
|
= 2.14.0 (2016-05-13)
|
2
12
|
|
3
13
|
* Add symbol_status plugin for using symbols as status codes (Papierkorb) (#65)
|
data/Rakefile
CHANGED
@@ -0,0 +1,53 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* A public plugin has been added. This adds an r.public method
|
4
|
+
for serving all files in the public directory. The public
|
5
|
+
plugin can replace usage of the static plugin, and is more
|
6
|
+
flexible. You can place r.public at any point in the routing
|
7
|
+
tree, and it will use the remaining path to lookup the file
|
8
|
+
in the public directory. You can also pass the :gzip option
|
9
|
+
when loading the plugin, and it will serve already gzipped
|
10
|
+
files to the client if the client supports gzipped transfer
|
11
|
+
encoding and the file exists with a .gz extension. Example:
|
12
|
+
|
13
|
+
plugin :public
|
14
|
+
route do |r|
|
15
|
+
# Serve public files before routing
|
16
|
+
r.public
|
17
|
+
|
18
|
+
# ...
|
19
|
+
end
|
20
|
+
|
21
|
+
* The :header matcher added by the header_matchers plugin now
|
22
|
+
automatically prefixes the key with HTTP_ when looking it up in
|
23
|
+
the environment, if the :header_matcher_prefix application
|
24
|
+
option is set. This behavior will probably be the default in
|
25
|
+
Roda 3.
|
26
|
+
|
27
|
+
# Before
|
28
|
+
r.on :header => 'http_accept'
|
29
|
+
|
30
|
+
# Now, with :header_matcher_prefix=>true application option
|
31
|
+
r.on :header => 'accept'
|
32
|
+
|
33
|
+
* The content_for plugin now accepts an :append=>true option to
|
34
|
+
support appending to the existing content instead of overwriting
|
35
|
+
the existing content if called multiple times. This behavior
|
36
|
+
will probably be the default in Roda 3.
|
37
|
+
|
38
|
+
# Before
|
39
|
+
content_for(:form, 'a')
|
40
|
+
content_for(:form, 'b')
|
41
|
+
content_for(:form) # => 'b'
|
42
|
+
|
43
|
+
# Now, with :append=>true option
|
44
|
+
content_for(:form, 'a')
|
45
|
+
content_for(:form, 'b')
|
46
|
+
content_for(:form) # => 'ab'
|
47
|
+
|
48
|
+
= Other Improvements
|
49
|
+
|
50
|
+
* The r.send_file method in the sinatra_helpers plugin now works
|
51
|
+
correctly when using rack 2.
|
52
|
+
|
53
|
+
* The specs now run correctly on Windows.
|
data/lib/roda/plugins/assets.rb
CHANGED
@@ -10,7 +10,7 @@ class Roda
|
|
10
10
|
# This uses the render plugin for rendering the assets, and the render
|
11
11
|
# plugin uses tilt internally, so you can use any template engine
|
12
12
|
# supported by tilt for your assets. Tilt ships with support for
|
13
|
-
# the following asset template engines, assuming the necessary
|
13
|
+
# the following asset template engines, assuming the necessary libraries
|
14
14
|
# are installed:
|
15
15
|
#
|
16
16
|
# css :: Less, Sass, Scss
|
@@ -77,7 +77,7 @@ class Roda
|
|
77
77
|
# assets/css/frontend/some_frontend_file.scss
|
78
78
|
# assets/css/backend/some_backend_file.scss
|
79
79
|
#
|
80
|
-
# If you
|
80
|
+
# If you do not want to force that directory structure when using
|
81
81
|
# asset groups, you can use the <tt>:group_subdirs => false</tt> option.
|
82
82
|
#
|
83
83
|
# In your view code use an array argument in your call to assets:
|
@@ -86,7 +86,7 @@ class Roda
|
|
86
86
|
#
|
87
87
|
# === Nesting
|
88
88
|
#
|
89
|
-
# Asset groups also
|
89
|
+
# Asset groups also support nesting, though that should only be needed
|
90
90
|
# in fairly large applications. You can use a nested hash when loading
|
91
91
|
# the plugin:
|
92
92
|
#
|
@@ -221,7 +221,7 @@ class Roda
|
|
221
221
|
# :compiled_js_route :: Route under :prefix for compiled javscript assets (default: :compiled_js_dir)
|
222
222
|
# :compiled_name :: Compiled file name prefix (default: 'app')
|
223
223
|
# :compiled_path:: Path inside public folder in which compiled files are stored (default: :prefix)
|
224
|
-
# :concat_only :: Whether to just concatenate instead of
|
224
|
+
# :concat_only :: Whether to just concatenate instead of concatenating
|
225
225
|
# and compressing files (default: false)
|
226
226
|
# :css_compressor :: Compressor to use for compressing CSS, either :yui, :none, or nil (the default, which will try
|
227
227
|
# :yui if available, but not fail if it is not available)
|
@@ -26,34 +26,59 @@ class Roda
|
|
26
26
|
# call content_for without the block:
|
27
27
|
#
|
28
28
|
# <%= content_for :foo %>
|
29
|
+
#
|
30
|
+
# If content_for is used multiple times with the same key,
|
31
|
+
# by default, the last call will override previous calls.
|
32
|
+
# If you want to append to the content, pass the :append
|
33
|
+
# option when loading the plugin:
|
34
|
+
#
|
35
|
+
# plugin :content_for, :append=>true
|
29
36
|
module ContentFor
|
30
37
|
# Depend on the render plugin, since this plugin only makes
|
31
38
|
# sense when the render plugin is used.
|
32
|
-
def self.load_dependencies(app)
|
39
|
+
def self.load_dependencies(app, _opts = {})
|
33
40
|
app.plugin :render
|
34
41
|
end
|
35
42
|
|
43
|
+
# Configure whether to append or overwrite if content_for
|
44
|
+
# is called multiple times to set data. Overwrite is default, use
|
45
|
+
# the :append option to append.
|
46
|
+
def self.configure(app, opts = {})
|
47
|
+
app.opts[:append_content_for] = opts.fetch(:append, false)
|
48
|
+
end
|
49
|
+
|
36
50
|
module InstanceMethods
|
37
51
|
# If called with a block, store content enclosed by block
|
38
52
|
# under the given key. If called without a block, retrieve
|
39
53
|
# stored content with the given key, or return nil if there
|
40
54
|
# is no content stored with that key.
|
41
55
|
def content_for(key, value=nil, &block)
|
42
|
-
|
43
|
-
outvar = render_opts[:template_opts][:outvar]
|
44
|
-
buf_was = instance_variable_get(outvar)
|
45
|
-
# clean the output buffer for ERB-based rendering systems
|
46
|
-
instance_variable_set(outvar, String.new)
|
56
|
+
append = opts[:append_content_for]
|
47
57
|
|
48
|
-
|
49
|
-
|
58
|
+
if block || value
|
59
|
+
if block
|
60
|
+
outvar = render_opts[:template_opts][:outvar]
|
61
|
+
buf_was = instance_variable_get(outvar)
|
62
|
+
|
63
|
+
# Use temporary output buffer for ERB-based rendering systems
|
64
|
+
instance_variable_set(outvar, String.new)
|
65
|
+
value = Tilt[render_opts[:engine]].new(&block).render
|
66
|
+
instance_variable_set(outvar, buf_was)
|
67
|
+
end
|
50
68
|
|
51
|
-
instance_variable_set(outvar, buf_was)
|
52
|
-
elsif value
|
53
69
|
@_content_for ||= {}
|
54
|
-
|
55
|
-
|
56
|
-
|
70
|
+
|
71
|
+
if append
|
72
|
+
(@_content_for[key] ||= []) << value
|
73
|
+
else
|
74
|
+
@_content_for[key] = value
|
75
|
+
end
|
76
|
+
elsif @_content_for && (value = @_content_for[key])
|
77
|
+
if append
|
78
|
+
value = value.join
|
79
|
+
end
|
80
|
+
|
81
|
+
value
|
57
82
|
end
|
58
83
|
end
|
59
84
|
end
|
@@ -11,7 +11,16 @@ class Roda
|
|
11
11
|
# It adds a +:header+ matcher for matching on arbitrary headers, which matches
|
12
12
|
# if the header is present:
|
13
13
|
#
|
14
|
+
# r.on :header=>'HTTP-X-App-Token' do |header_value|
|
15
|
+
# # Looks for env['HTTP_X_APP_TOKEN']
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# For backwards compatibility, the header value is not automatically prefixed
|
19
|
+
# with HTTP_. You can set the +:header_matcher_prefix+ option for the application,
|
20
|
+
# which will automatically prefix the header with HTTP_:
|
21
|
+
#
|
14
22
|
# r.on :header=>'X-App-Token' do |header_value|
|
23
|
+
# # Looks for env['HTTP_X_APP_TOKEN']
|
15
24
|
# end
|
16
25
|
#
|
17
26
|
# It adds a +:host+ matcher for matching by the host of the request:
|
@@ -54,7 +63,13 @@ class Roda
|
|
54
63
|
|
55
64
|
# Match if the given uppercase key is present inside the environment.
|
56
65
|
def match_header(key)
|
57
|
-
|
66
|
+
key = key.upcase.tr("-","_")
|
67
|
+
|
68
|
+
if roda_class.opts[:header_matcher_prefix]
|
69
|
+
key = "HTTP_#{key}"
|
70
|
+
end
|
71
|
+
|
72
|
+
if v = @env[key]
|
58
73
|
@captures << v
|
59
74
|
end
|
60
75
|
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
require 'uri'
|
4
|
+
|
5
|
+
#
|
6
|
+
class Roda
|
7
|
+
module RodaPlugins
|
8
|
+
# The public plugin adds a +r.public+ routing method to serve static files
|
9
|
+
# from a directory.
|
10
|
+
#
|
11
|
+
# The public plugin recognizes the application's :root option, and defaults to
|
12
|
+
# using the +public+ subfolder of the application's +:root+ option. If the application's
|
13
|
+
# :root option is not set, it defaults to the the +public+ folder in the working
|
14
|
+
# directory. Additionally, if a relative path is provided as the :root
|
15
|
+
# option to the plugin, it will be considered relative to the application's
|
16
|
+
# +:root+ option.
|
17
|
+
#
|
18
|
+
# Examples:
|
19
|
+
#
|
20
|
+
# opts[:root] = '/path/to/app'
|
21
|
+
# plugin :public
|
22
|
+
# plugin :public, :root=>'static'
|
23
|
+
module Public
|
24
|
+
NULL_BYTE = "\0".freeze
|
25
|
+
SPLIT = Regexp.union(*[File::SEPARATOR, File::ALT_SEPARATOR].compact)
|
26
|
+
PARSER = RUBY_VERSION >= '1.9' ? URI::DEFAULT_PARSER : URI
|
27
|
+
|
28
|
+
# Use options given to setup a Rack::File instance for serving files. Options:
|
29
|
+
# :default_mime :: The default mime type to use if the mime type is not recognized.
|
30
|
+
# :gzip :: Whether to serve already gzipped files with a .gz extension for clients
|
31
|
+
# supporting gzipped transfer encoding.
|
32
|
+
# :headers :: A hash of headers to use for statically served files
|
33
|
+
# :root :: Use this option for the root of the public directory (default: "public")
|
34
|
+
def self.configure(app, opts={})
|
35
|
+
root = File.expand_path(opts[:root]||"public", app.opts[:root])
|
36
|
+
app.opts[:public_server] = ::Rack::File.new(root, opts[:headers]||{}, opts[:default_mime] || 'text/plain')
|
37
|
+
app.opts[:public_gzip] = opts[:gzip]
|
38
|
+
end
|
39
|
+
|
40
|
+
module RequestMethods
|
41
|
+
# Serve files from the public directory if the file exists and this is a GET request.
|
42
|
+
def public
|
43
|
+
if is_get?
|
44
|
+
path = PARSER.unescape(remaining_path)
|
45
|
+
return if path.include?(NULL_BYTE)
|
46
|
+
|
47
|
+
roda_opts = roda_class.opts
|
48
|
+
server = roda_opts[:public_server]
|
49
|
+
path = ::File.join(server.root, *public_path_segments(path))
|
50
|
+
|
51
|
+
if roda_opts[:public_gzip] && env['HTTP_ACCEPT_ENCODING'] =~ /\bgzip\b/
|
52
|
+
gzip_path = path + '.gz'
|
53
|
+
|
54
|
+
if public_file_readable?(gzip_path)
|
55
|
+
res = public_serve(server, gzip_path)
|
56
|
+
headers = res[1]
|
57
|
+
|
58
|
+
if mime_type = ::Rack::Mime.mime_type(::File.extname(path), 'text/plain')
|
59
|
+
headers['Content-Type'] = mime_type
|
60
|
+
end
|
61
|
+
headers['Content-Encoding'] = 'gzip'
|
62
|
+
|
63
|
+
halt res
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
if public_file_readable?(path)
|
68
|
+
halt public_serve(server, path)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
# Return an array of segments for the given path, handling ..
|
76
|
+
# and . components
|
77
|
+
def public_path_segments(path)
|
78
|
+
segments = []
|
79
|
+
|
80
|
+
path.split(SPLIT).each do |seg|
|
81
|
+
next if seg.empty? || seg == '.'
|
82
|
+
seg == '..' ? segments.pop : segments << seg
|
83
|
+
end
|
84
|
+
|
85
|
+
segments
|
86
|
+
end
|
87
|
+
|
88
|
+
# Return whether the given path is a readable regular file.
|
89
|
+
def public_file_readable?(path)
|
90
|
+
::File.file?(path) && ::File.readable?(path)
|
91
|
+
rescue SystemCallError
|
92
|
+
false
|
93
|
+
end
|
94
|
+
|
95
|
+
if ::Rack.release > '2'
|
96
|
+
# :nocov:
|
97
|
+
def public_serve(server, path)
|
98
|
+
server.serving(self, path)
|
99
|
+
end
|
100
|
+
# :nocov:
|
101
|
+
else
|
102
|
+
# Serve the given path using the given Rack::File server.
|
103
|
+
def public_serve(server, path)
|
104
|
+
server = server.dup
|
105
|
+
server.path = path
|
106
|
+
server.serving(env)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
register_plugin(:public, Public)
|
113
|
+
end
|
114
|
+
end
|
@@ -339,9 +339,15 @@ class Roda
|
|
339
339
|
last_modified(lm)
|
340
340
|
end
|
341
341
|
|
342
|
-
file
|
343
|
-
|
344
|
-
|
342
|
+
file = ::Rack::File.new nil
|
343
|
+
s, h, b = if Rack.release > '2'
|
344
|
+
# :nocov:
|
345
|
+
file.serving(self, path)
|
346
|
+
# :nocov:
|
347
|
+
else
|
348
|
+
file.path = path
|
349
|
+
file.serving(@env)
|
350
|
+
end
|
345
351
|
|
346
352
|
res.status = opts[:status] || s
|
347
353
|
headers.delete(CONTENT_LENGTH)
|
data/lib/roda/plugins/static.rb
CHANGED
data/lib/roda/version.rb
CHANGED
data/spec/all.rb
ADDED
@@ -2,12 +2,18 @@ require File.expand_path("spec_helper", File.dirname(File.dirname(__FILE__)))
|
|
2
2
|
|
3
3
|
begin
|
4
4
|
require 'erubis'
|
5
|
+
require 'tilt'
|
5
6
|
require 'tilt/erb'
|
6
7
|
begin
|
7
8
|
require 'tilt/erubis'
|
8
9
|
rescue LoadError
|
9
10
|
# Tilt 1 support
|
10
11
|
end
|
12
|
+
|
13
|
+
if defined?(Tilt::ErubisTemplate) && ::Tilt['erb'] != Tilt::ErubisTemplate
|
14
|
+
# Work around error where erubis isn't set as erb template handler
|
15
|
+
Tilt.register(Tilt::ErubisTemplate, 'erb')
|
16
|
+
end
|
11
17
|
rescue LoadError
|
12
18
|
warn "tilt or erubis not installed, skipping _erubis_escaping plugin test"
|
13
19
|
else
|
data/spec/plugin/assets_spec.rb
CHANGED
@@ -564,15 +564,16 @@ if run_tests
|
|
564
564
|
|
565
565
|
app.opts[:root] = '/foo'
|
566
566
|
app.plugin :assets
|
567
|
-
|
568
|
-
app.assets_opts[:
|
569
|
-
app.assets_opts[:
|
567
|
+
# Work around for Windows
|
568
|
+
app.assets_opts[:path].sub(/\A\w:/, '').must_equal '/foo/assets'
|
569
|
+
app.assets_opts[:js_path].sub(/\A\w:/, '').must_equal '/foo/assets/js/'
|
570
|
+
app.assets_opts[:css_path].sub(/\A\w:/, '').must_equal '/foo/assets/css/'
|
570
571
|
|
571
572
|
app.opts[:root] = '/foo/bar'
|
572
573
|
app.plugin :assets
|
573
|
-
app.assets_opts[:path].must_equal '/foo/bar/assets'
|
574
|
-
app.assets_opts[:js_path].must_equal '/foo/bar/assets/js/'
|
575
|
-
app.assets_opts[:css_path].must_equal '/foo/bar/assets/css/'
|
574
|
+
app.assets_opts[:path].sub(/\A\w:/, '').must_equal '/foo/bar/assets'
|
575
|
+
app.assets_opts[:js_path].sub(/\A\w:/, '').must_equal '/foo/bar/assets/js/'
|
576
|
+
app.assets_opts[:css_path].sub(/\A\w:/, '').must_equal '/foo/bar/assets/css/'
|
576
577
|
|
577
578
|
app.opts[:root] = nil
|
578
579
|
app.plugin :assets
|
@@ -107,4 +107,28 @@ describe "content_for plugin when overriding :engine" do
|
|
107
107
|
body('/a').strip.must_equal "bar\nfoo"
|
108
108
|
end
|
109
109
|
end
|
110
|
+
|
111
|
+
describe "content_for plugin with multiple calls to the same key" do
|
112
|
+
before do
|
113
|
+
app(:bare) do
|
114
|
+
plugin :render, :views => './spec/views'
|
115
|
+
plugin :content_for
|
116
|
+
|
117
|
+
route do |r|
|
118
|
+
r.root do
|
119
|
+
view(:inline => "<% content_for :foo do %>foo<% end %><% content_for :foo do %>baz<% end %>bar", :layout => { :inline => '<%= yield %> <%= content_for(:foo) %>' })
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should replace with multiple calls to the same key by default" do
|
126
|
+
body.strip.must_equal "bar baz"
|
127
|
+
end
|
128
|
+
|
129
|
+
it "should append with multiple calls to the same key if :append plugin option is used" do
|
130
|
+
app.plugin :content_for, :append => true
|
131
|
+
body.strip.must_equal "bar foobaz"
|
132
|
+
end
|
133
|
+
end
|
110
134
|
end
|
@@ -22,22 +22,34 @@ describe "header matcher" do
|
|
22
22
|
end
|
23
23
|
|
24
24
|
body("HTTP_ACCEPT" => "application/xml").must_equal "bar"
|
25
|
+
status("HTTP_HTTP_ACCEPT" => "application/xml").must_equal 404
|
25
26
|
status.must_equal 404
|
26
27
|
end
|
27
28
|
|
28
|
-
it "should yield the header value
|
29
|
+
it "should yield the header value" do
|
30
|
+
app(:header_matchers) do |r|
|
31
|
+
r.on :header=>"http-accept" do |v|
|
32
|
+
"bar-#{v}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
body("HTTP_ACCEPT" => "application/xml").must_equal "bar-application/xml"
|
37
|
+
status.must_equal 404
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should automatically use HTTP prefix for headers if :header_matcher_prefix is set" do
|
29
41
|
app(:bare) do
|
30
42
|
plugin :header_matchers
|
31
|
-
opts[:
|
43
|
+
opts[:header_matcher_prefix] = true
|
32
44
|
route do |r|
|
33
|
-
r.on :header=>"
|
45
|
+
r.on :header=>"accept" do |v|
|
34
46
|
"bar-#{v}"
|
35
47
|
end
|
36
48
|
end
|
37
49
|
end
|
38
50
|
|
39
51
|
body("HTTP_ACCEPT" => "application/xml").must_equal "bar-application/xml"
|
40
|
-
status.must_equal 404
|
52
|
+
status("ACCEPT"=>"application/xml").must_equal 404
|
41
53
|
end
|
42
54
|
end
|
43
55
|
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require File.expand_path("spec_helper", File.dirname(File.dirname(__FILE__)))
|
2
|
+
|
3
|
+
describe "public plugin" do
|
4
|
+
it "adds r.public for serving static files from public folder" do
|
5
|
+
app(:bare) do
|
6
|
+
plugin :public, :root=>'spec/views'
|
7
|
+
|
8
|
+
route do |r|
|
9
|
+
r.public
|
10
|
+
|
11
|
+
r.on 'static' do
|
12
|
+
r.public
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
status("/about/_test.erb\0").must_equal 404
|
18
|
+
body('/about/_test.erb').must_equal File.read('spec/views/about/_test.erb')
|
19
|
+
body('/static/about/_test.erb').must_equal File.read('spec/views/about/_test.erb')
|
20
|
+
body('/foo/.././/about/_test.erb').must_equal File.read('spec/views/about/_test.erb')
|
21
|
+
end
|
22
|
+
|
23
|
+
it "respects the application's :root option" do
|
24
|
+
app(:bare) do
|
25
|
+
opts[:root] = File.expand_path('../../', __FILE__)
|
26
|
+
plugin :public, :root=>'views'
|
27
|
+
|
28
|
+
route do |r|
|
29
|
+
r.public
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
body('/about/_test.erb').must_equal File.read('spec/views/about/_test.erb')
|
34
|
+
end
|
35
|
+
|
36
|
+
it "handles serving gzip files in gzip mode if client supports gzip" do
|
37
|
+
app(:bare) do
|
38
|
+
plugin :public, :root=>'spec/views', :gzip=>true
|
39
|
+
|
40
|
+
route do |r|
|
41
|
+
r.public
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
body('/about/_test.erb').must_equal File.read('spec/views/about/_test.erb')
|
46
|
+
header('Content-Encoding', '/about/_test.erb').must_equal nil
|
47
|
+
|
48
|
+
body('/about.erb').must_equal File.read('spec/views/about.erb')
|
49
|
+
header('Content-Encoding', '/about.erb').must_equal nil
|
50
|
+
|
51
|
+
meth = RUBY_VERSION >= '1.9' ? :binread : :read
|
52
|
+
body('/about/_test.erb', 'HTTP_ACCEPT_ENCODING'=>'deflate, gzip').must_equal File.send(meth, 'spec/views/about/_test.erb.gz')
|
53
|
+
h = req('/about/_test.erb', 'HTTP_ACCEPT_ENCODING'=>'deflate, gzip')[1]
|
54
|
+
h['Content-Encoding'].must_equal 'gzip'
|
55
|
+
h['Content-Type'].must_equal 'text/plain'
|
56
|
+
|
57
|
+
body('/about/_test.css', 'HTTP_ACCEPT_ENCODING'=>'deflate, gzip').must_equal File.send(meth, 'spec/views/about/_test.css.gz')
|
58
|
+
h = req('/about/_test.css', 'HTTP_ACCEPT_ENCODING'=>'deflate, gzip')[1]
|
59
|
+
h['Content-Encoding'].must_equal 'gzip'
|
60
|
+
h['Content-Type'].must_equal 'text/css'
|
61
|
+
end
|
62
|
+
end
|
data/spec/plugin/render_spec.rb
CHANGED
@@ -189,11 +189,12 @@ describe "render plugin" do
|
|
189
189
|
|
190
190
|
app.opts[:root] = '/foo'
|
191
191
|
app.plugin :render
|
192
|
-
|
192
|
+
# Work around for Windows
|
193
|
+
app.render_opts[:views].sub(/\A\w:/, '').must_equal '/foo/views'
|
193
194
|
|
194
195
|
app.opts[:root] = '/foo/bar'
|
195
196
|
app.plugin :render
|
196
|
-
app.render_opts[:views].must_equal '/foo/bar/views'
|
197
|
+
app.render_opts[:views].sub(/\A\w:/, '').must_equal '/foo/bar/views'
|
197
198
|
|
198
199
|
app.opts[:root] = nil
|
199
200
|
app.plugin :render
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: roda
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.15.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Evans
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-06-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -180,6 +180,7 @@ extra_rdoc_files:
|
|
180
180
|
- doc/release_notes/2.12.0.txt
|
181
181
|
- doc/release_notes/2.13.0.txt
|
182
182
|
- doc/release_notes/2.14.0.txt
|
183
|
+
- doc/release_notes/2.15.0.txt
|
183
184
|
files:
|
184
185
|
- CHANGELOG
|
185
186
|
- MIT-LICENSE
|
@@ -197,6 +198,7 @@ files:
|
|
197
198
|
- doc/release_notes/2.12.0.txt
|
198
199
|
- doc/release_notes/2.13.0.txt
|
199
200
|
- doc/release_notes/2.14.0.txt
|
201
|
+
- doc/release_notes/2.15.0.txt
|
200
202
|
- doc/release_notes/2.2.0.txt
|
201
203
|
- doc/release_notes/2.3.0.txt
|
202
204
|
- doc/release_notes/2.4.0.txt
|
@@ -259,6 +261,7 @@ files:
|
|
259
261
|
- lib/roda/plugins/path_rewriter.rb
|
260
262
|
- lib/roda/plugins/per_thread_caching.rb
|
261
263
|
- lib/roda/plugins/precompile_templates.rb
|
264
|
+
- lib/roda/plugins/public.rb
|
262
265
|
- lib/roda/plugins/render.rb
|
263
266
|
- lib/roda/plugins/render_each.rb
|
264
267
|
- lib/roda/plugins/response_request.rb
|
@@ -277,6 +280,7 @@ files:
|
|
277
280
|
- lib/roda/plugins/view_subdirs.rb
|
278
281
|
- lib/roda/plugins/websockets.rb
|
279
282
|
- lib/roda/version.rb
|
283
|
+
- spec/all.rb
|
280
284
|
- spec/assets/css/app.scss
|
281
285
|
- spec/assets/css/no_access.css
|
282
286
|
- spec/assets/css/raw.css
|
@@ -339,6 +343,7 @@ files:
|
|
339
343
|
- spec/plugin/path_spec.rb
|
340
344
|
- spec/plugin/per_thread_caching_spec.rb
|
341
345
|
- spec/plugin/precompile_templates_spec.rb
|
346
|
+
- spec/plugin/public_spec.rb
|
342
347
|
- spec/plugin/render_each_spec.rb
|
343
348
|
- spec/plugin/render_spec.rb
|
344
349
|
- spec/plugin/response_request_spec.rb
|