roda 2.14.0 → 2.15.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.
- 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
|