roda 3.81.0 → 3.82.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 +8 -0
- data/doc/release_notes/3.82.0.txt +43 -0
- data/lib/roda/plugins/capture_erb.rb +17 -5
- data/lib/roda/plugins/plain_hash_response_headers.rb +1 -1
- data/lib/roda/plugins/public.rb +49 -19
- data/lib/roda/plugins/render.rb +13 -0
- data/lib/roda/version.rb +1 -1
- metadata +5 -17
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bdf5797c96af1d28dc4d13f0c95ac0468d60eb30b6a128b2cee2c26a08eb0a7f
|
|
4
|
+
data.tar.gz: d687b3cd03657bdcfda6f87a7a7a2a3b55e9a0c4f856cabd3d080865cc7d9ad2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e518b9638e98713ed54fd4c609069edf81a81987adf53ce2b7a09fa7110244f67b109cbe91c9c03d713f824900649d1c4b2ad435823852dcdfd01094f506afae
|
|
7
|
+
data.tar.gz: '00877a1338b70a5b96dab7fb946e21c7c916c776666286f80251b362e29ca6e040ffeb9b7a7258cf3af4c9246de5a6c35c5332385bd3cb926505776102c9112c'
|
data/CHANGELOG
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
= 3.82.0 (2024-07-12)
|
|
2
|
+
|
|
3
|
+
* Add :encodings option to public plugin to support configurable encoding order (jeremyevans)
|
|
4
|
+
|
|
5
|
+
* Add :zstd option to public plugin to supplement it to serve zstd-compressed files with .zst extension (jeremyevans)
|
|
6
|
+
|
|
7
|
+
* Make capture_erb plugin call integrate better with erubi/capture_block (jeremyevans)
|
|
8
|
+
|
|
1
9
|
= 3.81.0 (2024-06-12)
|
|
2
10
|
|
|
3
11
|
* Make assets plugin :early_hints option follow Rack 3 SPEC if using Rack 3 (jeremyevans)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
= New Features
|
|
2
|
+
|
|
3
|
+
* A :zstd option has been added to the public and multi_public
|
|
4
|
+
plugins to support serving zstd-compressed files with a .zst
|
|
5
|
+
extension. This option is similar to the existing :gzip and
|
|
6
|
+
:brotli plugin options. Chrome started supporting zstd encoding
|
|
7
|
+
in March.
|
|
8
|
+
|
|
9
|
+
* An :encodings option has been added to the public and multi_public
|
|
10
|
+
plugins, for more control over how encodings are handled. This
|
|
11
|
+
allows for changing the order in which encodings are attempted, the
|
|
12
|
+
use of custom encodings, and the use of different file extensions
|
|
13
|
+
for encodings. Example:
|
|
14
|
+
|
|
15
|
+
plugin :public, encodings: {'zstd'=>'.zst', 'deflate'=>'.deflate'}
|
|
16
|
+
|
|
17
|
+
If the :encodings option is not provided, the :zstd, :brotli, and
|
|
18
|
+
:gzip options are used to build an equivalent :encodings option.
|
|
19
|
+
|
|
20
|
+
= Other Improvements
|
|
21
|
+
|
|
22
|
+
* The capture_erb plugin now integrates better when using
|
|
23
|
+
erubi/capture_block for <%= method do %> support in ERB templates,
|
|
24
|
+
using the native capture method provided by the buffer object.
|
|
25
|
+
|
|
26
|
+
* Encoding handling has been more optimized in the public plugin.
|
|
27
|
+
Regexps for the encodings are precomputed, avoiding a regexp
|
|
28
|
+
allocation per request per encoding attempted. On Ruby 2.4+
|
|
29
|
+
Regexp#match? is used for better performance. If the
|
|
30
|
+
Accept-Encoding header is not present, no encoding matching
|
|
31
|
+
is attemped.
|
|
32
|
+
|
|
33
|
+
= Backwards Compatibility
|
|
34
|
+
|
|
35
|
+
* The private public_serve_compressed request method in the public
|
|
36
|
+
plugin now assumes it is called after the encoding is already
|
|
37
|
+
valid. If you are calling this method in your own code, you now
|
|
38
|
+
need to perform checks to make sure the client can accept the
|
|
39
|
+
encoding before calling this method.
|
|
40
|
+
|
|
41
|
+
* The :public_gzip and :public_brotli application options are no
|
|
42
|
+
longer set by the public plugin. The :public_encodings option
|
|
43
|
+
is now set.
|
|
@@ -15,6 +15,11 @@ class Roda
|
|
|
15
15
|
# inside templates. It can be combined with the inject_erb plugin
|
|
16
16
|
# to wrap template blocks with arbitrary output and then inject the
|
|
17
17
|
# wrapped output into the template.
|
|
18
|
+
#
|
|
19
|
+
# If the output buffer object responds to +capture+ (e.g. when
|
|
20
|
+
# +erubi/capture_block+ is being used as the template engine),
|
|
21
|
+
# this will call +capture+ on the output buffer object, instead
|
|
22
|
+
# of setting the output buffer object temporarily to a new object.
|
|
18
23
|
module CaptureERB
|
|
19
24
|
def self.load_dependencies(app)
|
|
20
25
|
app.plugin :render
|
|
@@ -25,13 +30,20 @@ class Roda
|
|
|
25
30
|
# with an empty string, and then yield to the block.
|
|
26
31
|
# Return the value of the block, converted to a string.
|
|
27
32
|
# Restore the previous ERB output buffer before returning.
|
|
28
|
-
def capture_erb
|
|
33
|
+
def capture_erb(&block)
|
|
29
34
|
outvar = render_opts[:template_opts][:outvar]
|
|
30
35
|
buf_was = instance_variable_get(outvar)
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
36
|
+
|
|
37
|
+
if buf_was.respond_to?(:capture)
|
|
38
|
+
buf_was.capture(&block)
|
|
39
|
+
else
|
|
40
|
+
begin
|
|
41
|
+
instance_variable_set(outvar, String.new)
|
|
42
|
+
yield.to_s
|
|
43
|
+
ensure
|
|
44
|
+
instance_variable_set(outvar, buf_was) if outvar && buf_was
|
|
45
|
+
end
|
|
46
|
+
end
|
|
35
47
|
end
|
|
36
48
|
end
|
|
37
49
|
end
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
#
|
|
4
4
|
class Roda
|
|
5
5
|
module RodaPlugins
|
|
6
|
-
# The
|
|
6
|
+
# The plain_hash_response_headers plugin will change Roda to
|
|
7
7
|
# use a plain hash for response headers. This is Roda's
|
|
8
8
|
# default behavior on Rack 2, but on Rack 3+, Roda defaults
|
|
9
9
|
# to using Rack::Headers for response headers for backwards
|
data/lib/roda/plugins/public.rb
CHANGED
|
@@ -44,15 +44,30 @@ class Roda
|
|
|
44
44
|
SPLIT = Regexp.union(*[File::SEPARATOR, File::ALT_SEPARATOR].compact)
|
|
45
45
|
PARSER = URI::DEFAULT_PARSER
|
|
46
46
|
RACK_FILES = defined?(Rack::Files) ? Rack::Files : Rack::File
|
|
47
|
+
ENCODING_MAP = {:zstd=>'zstd', :brotli=>'br', :gzip=>'gzip'}.freeze
|
|
48
|
+
ENCODING_EXTENSIONS = {'br'=>'.br', 'gzip'=>'.gz', 'zstd'=>'.zst'}.freeze
|
|
49
|
+
|
|
50
|
+
# :nocov:
|
|
51
|
+
MATCH_METHOD = RUBY_VERSION >= '2.4' ? :match? : :match
|
|
52
|
+
# :nocov:
|
|
47
53
|
|
|
48
54
|
# Use options given to setup a Rack::File instance for serving files. Options:
|
|
55
|
+
# :brotli :: Whether to serve already brotli-compressed files with a .br extension
|
|
56
|
+
# for clients supporting "br" transfer encoding.
|
|
49
57
|
# :default_mime :: The default mime type to use if the mime type is not recognized.
|
|
58
|
+
# :encodings :: An enumerable of pairs to handle accepted encodings. The first
|
|
59
|
+
# element of the pair is the accepted encoding name (e.g. 'gzip'),
|
|
60
|
+
# and the second element of the pair is the file extension (e.g.
|
|
61
|
+
# '.gz'). This allows configuration of the order in which encodings
|
|
62
|
+
# are tried, to prefer brotli to zstd for example, or to support
|
|
63
|
+
# encodings other than zstd, brotli, and gzip. This takes
|
|
64
|
+
# precedence over the :brotli, :gzip, and :zstd options if given.
|
|
50
65
|
# :gzip :: Whether to serve already gzipped files with a .gz extension for clients
|
|
51
|
-
# supporting
|
|
52
|
-
# :brotli :: Whether to serve already brotli-compressed files with a .br extension
|
|
53
|
-
# for clients supporting brotli transfer encoding.
|
|
66
|
+
# supporting "gzip" transfer encoding.
|
|
54
67
|
# :headers :: A hash of headers to use for statically served files
|
|
55
68
|
# :root :: Use this option for the root of the public directory (default: "public")
|
|
69
|
+
# :zstd :: Whether to serve already zstd-compressed files with a .zst extension
|
|
70
|
+
# for clients supporting "zstd" transfer encoding.
|
|
56
71
|
def self.configure(app, opts={})
|
|
57
72
|
if opts[:root]
|
|
58
73
|
app.opts[:public_root] = app.expand_path(opts[:root])
|
|
@@ -60,8 +75,18 @@ class Roda
|
|
|
60
75
|
app.opts[:public_root] = app.expand_path("public")
|
|
61
76
|
end
|
|
62
77
|
app.opts[:public_server] = RACK_FILES.new(app.opts[:public_root], opts[:headers]||{}, opts[:default_mime] || 'text/plain')
|
|
63
|
-
|
|
64
|
-
|
|
78
|
+
|
|
79
|
+
unless encodings = opts[:encodings]
|
|
80
|
+
if ENCODING_MAP.any?{|k,| opts.has_key?(k)}
|
|
81
|
+
encodings = ENCODING_MAP.map{|k, v| [v, ENCODING_EXTENSIONS[v]] if opts[k]}.compact
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
encodings = (encodings || app.opts[:public_encodings] || EMPTY_ARRAY).map(&:dup).freeze
|
|
85
|
+
encodings.each do |a|
|
|
86
|
+
a << /\b#{a[0]}\b/
|
|
87
|
+
end
|
|
88
|
+
encodings.each(&:freeze)
|
|
89
|
+
app.opts[:public_encodings] = encodings
|
|
65
90
|
end
|
|
66
91
|
|
|
67
92
|
module RequestMethods
|
|
@@ -102,8 +127,13 @@ class Roda
|
|
|
102
127
|
roda_opts = roda_class.opts
|
|
103
128
|
path = ::File.join(server.root, *public_path_segments(path))
|
|
104
129
|
|
|
105
|
-
|
|
106
|
-
|
|
130
|
+
if accept_encoding = env['HTTP_ACCEPT_ENCODING']
|
|
131
|
+
roda_opts[:public_encodings].each do |enc, ext, regexp|
|
|
132
|
+
if regexp.send(MATCH_METHOD, accept_encoding)
|
|
133
|
+
public_serve_compressed(server, path, ext, enc)
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
107
137
|
|
|
108
138
|
if public_file_readable?(path)
|
|
109
139
|
s, h, b = public_serve(server, path)
|
|
@@ -113,22 +143,22 @@ class Roda
|
|
|
113
143
|
end
|
|
114
144
|
end
|
|
115
145
|
|
|
146
|
+
# Serve the compressed file if it exists. This should only
|
|
147
|
+
# be called if the client will accept the related encoding.
|
|
116
148
|
def public_serve_compressed(server, path, suffix, encoding)
|
|
117
|
-
|
|
118
|
-
compressed_path = path + suffix
|
|
149
|
+
compressed_path = path + suffix
|
|
119
150
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
unless s == 304
|
|
126
|
-
headers[RodaResponseHeaders::CONTENT_TYPE] = ::Rack::Mime.mime_type(::File.extname(path), 'text/plain')
|
|
127
|
-
headers[RodaResponseHeaders::CONTENT_ENCODING] = encoding
|
|
128
|
-
end
|
|
151
|
+
if public_file_readable?(compressed_path)
|
|
152
|
+
s, h, b = public_serve(server, compressed_path)
|
|
153
|
+
headers = response.headers
|
|
154
|
+
headers.replace(h)
|
|
129
155
|
|
|
130
|
-
|
|
156
|
+
unless s == 304
|
|
157
|
+
headers[RodaResponseHeaders::CONTENT_TYPE] = ::Rack::Mime.mime_type(::File.extname(path), 'text/plain')
|
|
158
|
+
headers[RodaResponseHeaders::CONTENT_ENCODING] = encoding
|
|
131
159
|
end
|
|
160
|
+
|
|
161
|
+
halt [s, headers, b]
|
|
132
162
|
end
|
|
133
163
|
end
|
|
134
164
|
|
data/lib/roda/plugins/render.rb
CHANGED
|
@@ -148,6 +148,19 @@ class Roda
|
|
|
148
148
|
# inject the content into the output. To get similar behavior with Roda, you have
|
|
149
149
|
# a few different options you can use.
|
|
150
150
|
#
|
|
151
|
+
# == Use Erubi::CaptureBlockEngine
|
|
152
|
+
#
|
|
153
|
+
# Roda defaults to using Erubi for erb template rendering. Erubi 1.13.0+ includes
|
|
154
|
+
# support for an erb variant that supports blocks in <tt><%=</tt> and <tt><%==</tt>
|
|
155
|
+
# tags. To use it:
|
|
156
|
+
#
|
|
157
|
+
# require 'erubi/capture_block'
|
|
158
|
+
# plugin :render, template_opts: {engine_class: Erubi::CaptureBlockEngine}
|
|
159
|
+
#
|
|
160
|
+
# See the Erubi documentation for how to capture data inside the block. Make sure
|
|
161
|
+
# the method call (+some_method+ in the example) returns the output you want added
|
|
162
|
+
# to the rendered body.
|
|
163
|
+
#
|
|
151
164
|
# == Directly Inject Template Output
|
|
152
165
|
#
|
|
153
166
|
# You can switch from a <tt><%=</tt> tag to using a <tt><%</tt> tag:
|
data/lib/roda/version.rb
CHANGED
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: 3.
|
|
4
|
+
version: 3.82.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: 2024-
|
|
11
|
+
date: 2024-07-12 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rack
|
|
@@ -122,20 +122,6 @@ dependencies:
|
|
|
122
122
|
- - ">="
|
|
123
123
|
- !ruby/object:Gem::Version
|
|
124
124
|
version: '0'
|
|
125
|
-
- !ruby/object:Gem::Dependency
|
|
126
|
-
name: sassc
|
|
127
|
-
requirement: !ruby/object:Gem::Requirement
|
|
128
|
-
requirements:
|
|
129
|
-
- - ">="
|
|
130
|
-
- !ruby/object:Gem::Version
|
|
131
|
-
version: '0'
|
|
132
|
-
type: :development
|
|
133
|
-
prerelease: false
|
|
134
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
135
|
-
requirements:
|
|
136
|
-
- - ">="
|
|
137
|
-
- !ruby/object:Gem::Version
|
|
138
|
-
version: '0'
|
|
139
125
|
- !ruby/object:Gem::Dependency
|
|
140
126
|
name: json
|
|
141
127
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -256,6 +242,7 @@ extra_rdoc_files:
|
|
|
256
242
|
- doc/release_notes/3.8.0.txt
|
|
257
243
|
- doc/release_notes/3.80.0.txt
|
|
258
244
|
- doc/release_notes/3.81.0.txt
|
|
245
|
+
- doc/release_notes/3.82.0.txt
|
|
259
246
|
- doc/release_notes/3.9.0.txt
|
|
260
247
|
files:
|
|
261
248
|
- CHANGELOG
|
|
@@ -344,6 +331,7 @@ files:
|
|
|
344
331
|
- doc/release_notes/3.8.0.txt
|
|
345
332
|
- doc/release_notes/3.80.0.txt
|
|
346
333
|
- doc/release_notes/3.81.0.txt
|
|
334
|
+
- doc/release_notes/3.82.0.txt
|
|
347
335
|
- doc/release_notes/3.9.0.txt
|
|
348
336
|
- lib/roda.rb
|
|
349
337
|
- lib/roda/cache.rb
|
|
@@ -509,7 +497,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
509
497
|
- !ruby/object:Gem::Version
|
|
510
498
|
version: '0'
|
|
511
499
|
requirements: []
|
|
512
|
-
rubygems_version: 3.5.
|
|
500
|
+
rubygems_version: 3.5.11
|
|
513
501
|
signing_key:
|
|
514
502
|
specification_version: 4
|
|
515
503
|
summary: Routing tree web toolkit
|