roda 3.61.0 → 3.63.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +18 -0
- data/doc/release_notes/3.62.0.txt +41 -0
- data/doc/release_notes/3.63.0.txt +36 -0
- data/lib/roda/plugins/Integer_matcher_max.rb +54 -0
- data/lib/roda/plugins/_optimized_matching.rb +4 -4
- data/lib/roda/plugins/autoload_hash_branches.rb +67 -0
- data/lib/roda/plugins/class_matchers.rb +12 -0
- data/lib/roda/plugins/halt.rb +1 -1
- data/lib/roda/plugins/mailer.rb +9 -3
- data/lib/roda/plugins/typecast_params.rb +3 -1
- data/lib/roda/plugins/typecast_params_sized_integers.rb +107 -0
- data/lib/roda/plugins/unescape_path.rb +7 -0
- data/lib/roda/request.rb +14 -3
- data/lib/roda/version.rb +1 -1
- metadata +10 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6e19674abcd02c79572ada44fe13fc8188a4cc91b780a3fbaa39da206cf7457f
|
4
|
+
data.tar.gz: ffd0e850b4aab5e82b3f5cf307145853df9d420389ff8eb6170ec53d3e29ca57
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d91087a996b037de3c0ecc3ca5e029f6b4bb40c5da1618048d70c0aa42ac5dcc581b6ed67e55cd9236da5463c3c224c62b09f85797daeffcb9a8fb98a16bca03
|
7
|
+
data.tar.gz: 62d2e2fdb0efa867299a764d4f7b36fc1a1e680147d32703d29451e29d2e3090a0f337c2c87ac46929a5a504b6461f92d18b50a14c62f422de4c114e43892c91
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
= 3.63.0 (2022-12-16)
|
2
|
+
|
3
|
+
* Make mailer plugin set configured content type for body part for emails with attachments when using mail 2.8+ (jeremyevans)
|
4
|
+
|
5
|
+
* Add autoload_hash_branches plugin for autoloading file for a hash branch when there is a request for that branch (jeremyevans)
|
6
|
+
|
7
|
+
* Add mailer plugin :terminal option to make r.mail use a terminal match when provided arguments (jeremyevans)
|
8
|
+
|
9
|
+
= 3.62.0 (2022-11-14)
|
10
|
+
|
11
|
+
* Add typecast_params_sized_integers plugin for converting parameters to sized integers (jeremyevans)
|
12
|
+
|
13
|
+
* Add Integer_matcher_max plugin for setting maximum integer value matched by the Integer matcher (jeremyevans)
|
14
|
+
|
15
|
+
* Allow class matchers in the class_matchers plugin to skip matching based on regexp match values (jeremyevans)
|
16
|
+
|
17
|
+
* Fix RodaRequest#matched_path when using unescape_path plugin (jeremyevans) (#286)
|
18
|
+
|
1
19
|
= 3.61.0 (2022-10-12)
|
2
20
|
|
3
21
|
* Make Integer matcher limit integer segments to 100 characters by default (jeremyevans)
|
@@ -0,0 +1,41 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* An Integer_matcher_max plugin has been added for setting the
|
4
|
+
maximum value matched by the Integer matcher (the minimum is
|
5
|
+
always 0, since the Integer matcher does not match negative
|
6
|
+
integers). The default maximum value when using the plugin
|
7
|
+
is 2**63-1, the maximum value for a signed 64-bit integer.
|
8
|
+
You can specify a different maximum value by passing an argument
|
9
|
+
when loading the plugin.
|
10
|
+
|
11
|
+
* A typecast_params_sized_integers plugin has been added for
|
12
|
+
converting parameters to integers only if the integer is within a
|
13
|
+
specific size. By default, the plugin supports 8-bit, 16-bit,
|
14
|
+
32-bit, and 64-bit signed and unsigned integer types, with the
|
15
|
+
following typecast_params methods added by the plugin:
|
16
|
+
|
17
|
+
* int8, uint8, pos_int8, pos_uint8, Integer8, Integeru8
|
18
|
+
* int16, uint16, pos_int16, pos_uint16, Integer16, Integeru16
|
19
|
+
* int32, uint32, pos_int32, pos_uint32, Integer32, Integeru32
|
20
|
+
* int64, uint64, pos_int64, pos_uint64, Integer64, Integeru64
|
21
|
+
|
22
|
+
You can override what sizes are added by default by using the
|
23
|
+
:sizes option. You can also specify a :default_size option,
|
24
|
+
in which case the default int, pos_int, and Integer conversions
|
25
|
+
will use the given size. So if you want to change the default
|
26
|
+
typecast_params integer conversion behavior to only support
|
27
|
+
integer values that can fit in 64-bit signed integers, you can
|
28
|
+
use:
|
29
|
+
|
30
|
+
plugin :typecast_params_sized_integers, sizes: [64],
|
31
|
+
default_size: 64
|
32
|
+
|
33
|
+
= Other Improvements
|
34
|
+
|
35
|
+
* The block passed to the class_matcher method in the class_matchers
|
36
|
+
plugin can now return nil/false to signal that it should not match.
|
37
|
+
This is useful when the regexp argument provided matches segments
|
38
|
+
not valid for the class.
|
39
|
+
|
40
|
+
* RodaRequest#matched_path now works correctly when using the
|
41
|
+
unescape_path plugin.
|
@@ -0,0 +1,36 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* An autoload_hash_branches plugin has been added for autoloading
|
4
|
+
route files for each hash branch, instead of requiring the route
|
5
|
+
files be loaded up front. For example, to automatically load a
|
6
|
+
route file for a hash branch on the first request to that branch:
|
7
|
+
|
8
|
+
plugin :autoload_hash_branches
|
9
|
+
autoload_hash_branch('branch_name', '/path/to/file')
|
10
|
+
autoload_hash_branch('namespace', 'branch_name', '/path/to/file')
|
11
|
+
|
12
|
+
The route file loaded should define the expected hash branch.
|
13
|
+
|
14
|
+
It is common to have route files stored in a directory, with the
|
15
|
+
file name matching the branch name. In that case, you can set
|
16
|
+
autoloading for all route files in a given directory:
|
17
|
+
|
18
|
+
plugin :autoload_hash_branches
|
19
|
+
autoload_hash_branch_dir('/path/to/dir')
|
20
|
+
autoload_hash_branch_dir('namespace', '/path/to/dir')
|
21
|
+
|
22
|
+
Note that autoloading hash branches does not work if the application
|
23
|
+
is frozen. This plugin should only be used in development mode for
|
24
|
+
faster startup, or when running tests on a subset of the application
|
25
|
+
in order to avoid loading parts of the application unrelated to what
|
26
|
+
is being tested.
|
27
|
+
|
28
|
+
* The mailer plugin now supports a :terminal plugin option to make
|
29
|
+
the r.mail method force a terminal match, similar to how r.get
|
30
|
+
and other HTTP verb methods work in standard Roda. This behavior
|
31
|
+
will become the default in Roda 4.
|
32
|
+
|
33
|
+
= Other Improvements
|
34
|
+
|
35
|
+
* The mailer plugin now correctly sets the content_type of the body
|
36
|
+
for emails with attachments when using mail 2.8.0+.
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
class Roda
|
5
|
+
module RodaPlugins
|
6
|
+
# The Integer_matcher_max plugin sets the maximum integer value
|
7
|
+
# value that the Integer class matcher will match by default.
|
8
|
+
# By default, loading this plugin sets the maximum value to
|
9
|
+
# 2**63-1, the largest signed 64-bit integer value:
|
10
|
+
#
|
11
|
+
# plugin :Integer_matcher_max
|
12
|
+
# route do |r|
|
13
|
+
# r.is Integer do
|
14
|
+
# # Matches /9223372036854775807
|
15
|
+
# # Does not match /9223372036854775808
|
16
|
+
# end
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# To specify a different maximum value, you can pass a different
|
20
|
+
# maximum value when loading the plugin:
|
21
|
+
#
|
22
|
+
# plugin :Integer_matcher_max, 2**64-1
|
23
|
+
module IntegerMatcherMax
|
24
|
+
def self.configure(app, max=nil)
|
25
|
+
if max
|
26
|
+
app::RodaRequest.class_eval do
|
27
|
+
define_method(:_match_class_max_Integer){max}
|
28
|
+
alias_method :_match_class_max_Integer, :_match_class_max_Integer
|
29
|
+
private :_match_class_max_Integer
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
module RequestMethods
|
35
|
+
private
|
36
|
+
|
37
|
+
# Do not have the Integer matcher max when over the maximum
|
38
|
+
# configured Integer value.
|
39
|
+
def _match_class_convert_Integer(value)
|
40
|
+
value = super
|
41
|
+
value if value <= _match_class_max_Integer
|
42
|
+
end
|
43
|
+
|
44
|
+
# Use 2**63-1 as the default maximum value for the Integer
|
45
|
+
# matcher.
|
46
|
+
def _match_class_max_Integer
|
47
|
+
9223372036854775807
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
register_plugin(:Integer_matcher_max, IntegerMatcherMax)
|
53
|
+
end
|
54
|
+
end
|
@@ -52,9 +52,9 @@ class Roda
|
|
52
52
|
end
|
53
53
|
end
|
54
54
|
elsif matcher == Integer
|
55
|
-
if matchdata = /\A\/(\d{1,100})(?=\/|\z)/.match(@remaining_path)
|
55
|
+
if (matchdata = /\A\/(\d{1,100})(?=\/|\z)/.match(@remaining_path)) && (value = _match_class_convert_Integer(matchdata[1]))
|
56
56
|
@remaining_path = matchdata.post_match
|
57
|
-
always{yield(
|
57
|
+
always{yield(value)}
|
58
58
|
end
|
59
59
|
else
|
60
60
|
path = @remaining_path
|
@@ -151,9 +151,9 @@ class Roda
|
|
151
151
|
always{yield rp[1, len]}
|
152
152
|
end
|
153
153
|
elsif matcher == Integer
|
154
|
-
if matchdata = /\A\/(\d{1,100})\z/.match(@remaining_path)
|
154
|
+
if (matchdata = /\A\/(\d{1,100})\z/.match(@remaining_path)) && (value = _match_class_convert_Integer(matchdata[1]))
|
155
155
|
@remaining_path = ''
|
156
|
-
always{yield(
|
156
|
+
always{yield(value)}
|
157
157
|
end
|
158
158
|
else
|
159
159
|
path = @remaining_path
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
class Roda
|
5
|
+
module RodaPlugins
|
6
|
+
# The autoload_hash_branches plugin builds on the hash_branches plugin and allows for
|
7
|
+
# delaying loading of a file containing a hash branch for an application until there
|
8
|
+
# is a request that uses the hash branch. This can be useful in development
|
9
|
+
# to improvement startup time by not loading all branches up front. It can also be
|
10
|
+
# useful in testing subsets of an application by only loading the hash branches being
|
11
|
+
# tested.
|
12
|
+
#
|
13
|
+
# You can specify a single hash branch for autoloading:
|
14
|
+
#
|
15
|
+
# plugin :autoload_hash_branches
|
16
|
+
# autoload_hash_branch('branch_name', '/path/to/file')
|
17
|
+
# autoload_hash_branch('namespace', 'branch_name', '/path/to/file')
|
18
|
+
#
|
19
|
+
# You can also set the plugin to autoload load all hash branch files in a given directory.
|
20
|
+
# This will look at each .rb file in the directory, and add an autoload for it, using the
|
21
|
+
# filename without the .rb as the branch name:
|
22
|
+
#
|
23
|
+
# autoload_hash_branch_dir('/path/to/dir')
|
24
|
+
# autoload_hash_branch_dir('namespace', '/path/to/dir')
|
25
|
+
#
|
26
|
+
# In both cases, when the autoloaded file is required, it should redefine the same
|
27
|
+
# hash branch. If it does not, requests to the hash branch will result in a 404 error.
|
28
|
+
#
|
29
|
+
# This plugin will not work correctly when freezing applications, because it requires
|
30
|
+
# modifying the class at runtime as hash branches are autoloaded.
|
31
|
+
module AutoloadHashBranches
|
32
|
+
def self.load_dependencies(app)
|
33
|
+
app.plugin :hash_branches
|
34
|
+
end
|
35
|
+
|
36
|
+
module ClassMethods
|
37
|
+
# Autoload the given file when there is request for the hash branch.
|
38
|
+
# The given file should configure the hash branch specified.
|
39
|
+
def autoload_hash_branch(namespace='', segment, file)
|
40
|
+
segment = "/#{segment}"
|
41
|
+
routes = opts[:hash_branches][namespace] ||= {}
|
42
|
+
meth = routes[segment] = define_roda_method(routes[segment] || "hash_branch_#{namespace}_#{segment}", 1) do |r|
|
43
|
+
loc = method(routes[segment]).source_location
|
44
|
+
require file
|
45
|
+
# Avoid infinite loop in case method is not overridden
|
46
|
+
if method(meth).source_location != loc
|
47
|
+
send(meth, r)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
nil
|
51
|
+
end
|
52
|
+
|
53
|
+
# For each .rb file in the given directory, add an autoloaded hash branch
|
54
|
+
# based on the file name.
|
55
|
+
def autoload_hash_branch_dir(namespace='', dir)
|
56
|
+
Dir.new(dir).entries.each do |file|
|
57
|
+
if file =~ /\.rb\z/i
|
58
|
+
autoload_hash_branch(namespace, file.sub(/\.rb\z/i, ''), File.join(dir, file))
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
register_plugin(:autoload_hash_branches, AutoloadHashBranches)
|
66
|
+
end
|
67
|
+
end
|
@@ -28,6 +28,18 @@ class Roda
|
|
28
28
|
# This is useful to DRY up code if you are using the same type of pattern and
|
29
29
|
# type conversion in multiple places in your application.
|
30
30
|
#
|
31
|
+
# If you have a segment match the passed regexp, but decide during block
|
32
|
+
# processing that you do not want to treat it as a match, you can have the
|
33
|
+
# block return nil or false. This is useful if you want to make sure you
|
34
|
+
# are using valid data:
|
35
|
+
#
|
36
|
+
# class_matcher(Date, /(\dd\d)-(\d\d)-(\d\d)/) do |y, m, d|
|
37
|
+
# y = y.to_i
|
38
|
+
# m = m.to_i
|
39
|
+
# d = d.to_i
|
40
|
+
# [Date.new(y, m, d)] if Date.valid_date?(y, m, d)
|
41
|
+
# end
|
42
|
+
#
|
31
43
|
# This plugin does not work with the params_capturing plugin, as it does not
|
32
44
|
# offer the ability to associate block arguments with named keys.
|
33
45
|
module ClassMatchers
|
data/lib/roda/plugins/halt.rb
CHANGED
@@ -56,7 +56,7 @@ class Roda
|
|
56
56
|
# r.halt(:template) if r.params['a']
|
57
57
|
#
|
58
58
|
# # symbol_views plugin, specifying status code, headers, and template file to render as body
|
59
|
-
# r.halt(500, 'header=>'value', :other_template) if r.params['c']
|
59
|
+
# r.halt(500, {'header'=>'value'}, :other_template) if r.params['c']
|
60
60
|
#
|
61
61
|
# # json plugin, specifying status code and JSON body
|
62
62
|
# r.halt(500, [{'error'=>'foo'}]) if r.params['b']
|
data/lib/roda/plugins/mailer.rb
CHANGED
@@ -115,6 +115,11 @@ class Roda
|
|
115
115
|
#
|
116
116
|
# plugin :mailer, content_type: 'text/html'
|
117
117
|
#
|
118
|
+
# For backwards compatibility reasons, the +r.mail+ method does not do
|
119
|
+
# a terminal match by default if provided arguments (unlike +r.get+ and
|
120
|
+
# +r.post+). You can pass the :terminal option to make +r.mail+ enforce
|
121
|
+
# a terminal match if provided arguments.
|
122
|
+
#
|
118
123
|
# The mailer plugin does support being used inside a Roda application
|
119
124
|
# that is handling web requests, where the routing block for mails and
|
120
125
|
# web requests is shared. However, it's recommended that you create a
|
@@ -163,7 +168,8 @@ class Roda
|
|
163
168
|
# any arguments passed to the +mail+ or +sendmail+ Roda class methods.
|
164
169
|
def mail(*args)
|
165
170
|
if @env["REQUEST_METHOD"] == "MAIL"
|
166
|
-
|
171
|
+
# RODA4: Make terminal match the default
|
172
|
+
send(roda_class.opts[:mailer][:terminal] ? :_verb : :if_match, args) do |*vs|
|
167
173
|
yield(*(vs + @env['roda.mail_args']))
|
168
174
|
end
|
169
175
|
end
|
@@ -190,9 +196,9 @@ class Roda
|
|
190
196
|
|
191
197
|
if content_type = header_content_type || roda_class.opts[:mailer][:content_type]
|
192
198
|
if mail.multipart?
|
193
|
-
if
|
199
|
+
if /multipart\/mixed/ =~ mail.content_type &&
|
194
200
|
mail.parts.length >= 2 &&
|
195
|
-
(part = mail.parts.find{|p| !p.attachment && p.
|
201
|
+
(part = mail.parts.find{|p| !p.attachment && (p.encoded; /text\/plain/ =~ p.content_type)})
|
196
202
|
part.content_type = content_type
|
197
203
|
end
|
198
204
|
else
|
@@ -526,9 +526,10 @@ class Roda
|
|
526
526
|
handle_type(:int, :max_input_bytesize=>100) do |v|
|
527
527
|
string_or_numeric!(v) && v.to_i
|
528
528
|
end
|
529
|
+
alias base_convert_int convert_int
|
529
530
|
|
530
531
|
handle_type(:pos_int, :max_input_bytesize=>100) do |v|
|
531
|
-
if (v =
|
532
|
+
if (v = base_convert_int(v)) && v > 0
|
532
533
|
v
|
533
534
|
end
|
534
535
|
end
|
@@ -547,6 +548,7 @@ class Roda
|
|
547
548
|
end
|
548
549
|
end
|
549
550
|
end
|
551
|
+
alias base_convert_Integer convert_Integer
|
550
552
|
|
551
553
|
handle_type(:float, :max_input_bytesize=>1000) do |v|
|
552
554
|
string_or_numeric!(v) && v.to_f
|
@@ -0,0 +1,107 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
class Roda
|
5
|
+
module RodaPlugins
|
6
|
+
# The typecast_params_sized_integers plugin adds sized integer conversion
|
7
|
+
# methods to typecast_params:
|
8
|
+
#
|
9
|
+
# * int8, uint8, pos_int8, pos_uint8, Integer8, Integeru8
|
10
|
+
# * int16, uint16, pos_int16, pos_uint16, Integer16, Integeru16
|
11
|
+
# * int32, uint32, pos_int32, pos_uint32, Integer32, Integeru32
|
12
|
+
# * int64, uint64, pos_int64, pos_uint64, Integer64, Integeru64
|
13
|
+
#
|
14
|
+
# The int*, pos_int*, and Integer* methods operate the same as the
|
15
|
+
# standard int, pos_int, and Integer methods in typecast_params,
|
16
|
+
# except that they will only handle parameter values in the given
|
17
|
+
# range for the signed integer type. The uint*, pos_int*, and
|
18
|
+
# Integeru* methods are similar to the int*, pos_int*, and
|
19
|
+
# Integer* methods, except they use the range of the unsigned
|
20
|
+
# integer type instead of the range of the signed integer type.
|
21
|
+
#
|
22
|
+
# Here are the signed and unsigned integer type ranges:
|
23
|
+
# 8 :: [-128, 127], [0, 255]
|
24
|
+
# 16 :: [-32768, 32767], [0, 65535]
|
25
|
+
# 32 :: [-2147483648, 2147483647], [0, 4294967295]
|
26
|
+
# 64 :: [-9223372036854775808, 9223372036854775807], [0, 18446744073709551615]
|
27
|
+
#
|
28
|
+
# To only create methods for certain integer sizes, you can pass a
|
29
|
+
# :sizes option when loading the plugin, and it will only create
|
30
|
+
# methods for the sizes you specify.
|
31
|
+
#
|
32
|
+
# You can provide a :default_size option when loading the plugin,
|
33
|
+
# in which case the int, uint, pos_int, pos_uint, Integer, and Integeru,
|
34
|
+
# typecast_params conversion methods will be aliases to the conversion
|
35
|
+
# methods for the given sized type:
|
36
|
+
#
|
37
|
+
# plugin :typecast_params_sized_integers, default_size: 64
|
38
|
+
#
|
39
|
+
# route do |r|
|
40
|
+
# # Returns nil unless param.to_i > 0 && param.to_i <= 9223372036854775807
|
41
|
+
# typecast_params.pos_int('param_name')
|
42
|
+
# end
|
43
|
+
module TypecastParamsSizedIntegers
|
44
|
+
def self.load_dependencies(app, opts=OPTS)
|
45
|
+
app.plugin :typecast_params do
|
46
|
+
(opts[:sizes] || [8, 16, 32, 64]).each do |i|
|
47
|
+
# Avoid defining the same methods more than once
|
48
|
+
next if method_defined?(:"pos_int#{i}")
|
49
|
+
|
50
|
+
min_signed = -(2**(i-1))
|
51
|
+
max_signed = 2**(i-1)-1
|
52
|
+
max_unsigned = 2**i-1
|
53
|
+
|
54
|
+
handle_type(:"int#{i}", :max_input_bytesize=>100) do |v|
|
55
|
+
if (v = base_convert_int(v)) && v >= min_signed && v <= max_signed
|
56
|
+
v
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
handle_type(:"uint#{i}", :max_input_bytesize=>100) do |v|
|
61
|
+
if (v = base_convert_int(v)) && v >= 0 && v <= max_unsigned
|
62
|
+
v
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
handle_type(:"pos_int#{i}", :max_input_bytesize=>100) do |v|
|
67
|
+
if (v = base_convert_int(v)) && v > 0 && v <= max_signed
|
68
|
+
v
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
handle_type(:"pos_uint#{i}", :max_input_bytesize=>100) do |v|
|
73
|
+
if (v = base_convert_int(v)) && v > 0 && v <= max_unsigned
|
74
|
+
v
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
handle_type(:"Integer#{i}", :max_input_bytesize=>100) do |v|
|
79
|
+
if (v = base_convert_Integer(v)) && v >= min_signed && v <= max_signed
|
80
|
+
v
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
handle_type(:"Integeru#{i}", :max_input_bytesize=>100) do |v|
|
85
|
+
if (v = base_convert_Integer(v)) && v >= 0 && v <= max_unsigned
|
86
|
+
v
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
if default = opts[:default_size]
|
93
|
+
app::TypecastParams.class_eval do
|
94
|
+
%w[int uint pos_int pos_uint Integer Integeru].each do |type|
|
95
|
+
['', 'convert_', '_convert_array_', '_max_input_bytesize_for_'].each do |prefix|
|
96
|
+
alias_method :"#{prefix}#{type}", :"#{prefix}#{type}#{default}"
|
97
|
+
end
|
98
|
+
alias_method :"#{type}!", :"#{type}#{default}!"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
register_plugin(:typecast_params_sized_integers, TypecastParamsSizedIntegers)
|
106
|
+
end
|
107
|
+
end
|
@@ -20,6 +20,13 @@ class Roda
|
|
20
20
|
# end
|
21
21
|
module UnescapePath
|
22
22
|
module RequestMethods
|
23
|
+
# Make sure the matched path calculation handles the unescaping
|
24
|
+
# of the remaining path.
|
25
|
+
def matched_path
|
26
|
+
e = @env
|
27
|
+
Rack::Utils.unescape(e["SCRIPT_NAME"] + e["PATH_INFO"]).chomp(@remaining_path)
|
28
|
+
end
|
29
|
+
|
23
30
|
private
|
24
31
|
|
25
32
|
# Unescape the path.
|
data/lib/roda/request.rb
CHANGED
@@ -443,7 +443,16 @@ class Roda
|
|
443
443
|
# Match integer segment of up to 100 decimal characters, and yield resulting value as an
|
444
444
|
# integer.
|
445
445
|
def _match_class_Integer
|
446
|
-
consume(/\A\/(\d{1,100})(?=\/|\z)/)
|
446
|
+
consume(/\A\/(\d{1,100})(?=\/|\z)/) do |i|
|
447
|
+
if i = _match_class_convert_Integer(i)
|
448
|
+
[i]
|
449
|
+
end
|
450
|
+
end
|
451
|
+
end
|
452
|
+
|
453
|
+
# Convert the segment matched by the Integer matcher to an integer.
|
454
|
+
def _match_class_convert_Integer(value)
|
455
|
+
value.to_i
|
447
456
|
end
|
448
457
|
|
449
458
|
# Match only if all of the arguments in the given array match.
|
@@ -548,9 +557,11 @@ class Roda
|
|
548
557
|
# path from PATH_INFO, and updates captures with any regex captures.
|
549
558
|
def consume(pattern)
|
550
559
|
if matchdata = pattern.match(@remaining_path)
|
551
|
-
@remaining_path = matchdata.post_match
|
552
560
|
captures = matchdata.captures
|
553
|
-
|
561
|
+
if defined?(yield)
|
562
|
+
return unless captures = yield(*captures)
|
563
|
+
end
|
564
|
+
@remaining_path = matchdata.post_match
|
554
565
|
@captures.concat(captures)
|
555
566
|
end
|
556
567
|
end
|
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.63.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: 2022-
|
11
|
+
date: 2022-12-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -234,6 +234,8 @@ extra_rdoc_files:
|
|
234
234
|
- doc/release_notes/3.6.0.txt
|
235
235
|
- doc/release_notes/3.60.0.txt
|
236
236
|
- doc/release_notes/3.61.0.txt
|
237
|
+
- doc/release_notes/3.62.0.txt
|
238
|
+
- doc/release_notes/3.63.0.txt
|
237
239
|
- doc/release_notes/3.7.0.txt
|
238
240
|
- doc/release_notes/3.8.0.txt
|
239
241
|
- doc/release_notes/3.9.0.txt
|
@@ -302,12 +304,15 @@ files:
|
|
302
304
|
- doc/release_notes/3.6.0.txt
|
303
305
|
- doc/release_notes/3.60.0.txt
|
304
306
|
- doc/release_notes/3.61.0.txt
|
307
|
+
- doc/release_notes/3.62.0.txt
|
308
|
+
- doc/release_notes/3.63.0.txt
|
305
309
|
- doc/release_notes/3.7.0.txt
|
306
310
|
- doc/release_notes/3.8.0.txt
|
307
311
|
- doc/release_notes/3.9.0.txt
|
308
312
|
- lib/roda.rb
|
309
313
|
- lib/roda/cache.rb
|
310
314
|
- lib/roda/plugins.rb
|
315
|
+
- lib/roda/plugins/Integer_matcher_max.rb
|
311
316
|
- lib/roda/plugins/_after_hook.rb
|
312
317
|
- lib/roda/plugins/_before_hook.rb
|
313
318
|
- lib/roda/plugins/_optimized_matching.rb
|
@@ -317,6 +322,7 @@ files:
|
|
317
322
|
- lib/roda/plugins/all_verbs.rb
|
318
323
|
- lib/roda/plugins/assets.rb
|
319
324
|
- lib/roda/plugins/assets_preloading.rb
|
325
|
+
- lib/roda/plugins/autoload_hash_branches.rb
|
320
326
|
- lib/roda/plugins/backtracking_array.rb
|
321
327
|
- lib/roda/plugins/branch_locals.rb
|
322
328
|
- lib/roda/plugins/caching.rb
|
@@ -423,6 +429,7 @@ files:
|
|
423
429
|
- lib/roda/plugins/timestamp_public.rb
|
424
430
|
- lib/roda/plugins/type_routing.rb
|
425
431
|
- lib/roda/plugins/typecast_params.rb
|
432
|
+
- lib/roda/plugins/typecast_params_sized_integers.rb
|
426
433
|
- lib/roda/plugins/unescape_path.rb
|
427
434
|
- lib/roda/plugins/view_options.rb
|
428
435
|
- lib/roda/request.rb
|
@@ -453,7 +460,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
453
460
|
- !ruby/object:Gem::Version
|
454
461
|
version: '0'
|
455
462
|
requirements: []
|
456
|
-
rubygems_version: 3.3.
|
463
|
+
rubygems_version: 3.3.26
|
457
464
|
signing_key:
|
458
465
|
specification_version: 4
|
459
466
|
summary: Routing tree web toolkit
|