roda 3.61.0 → 3.63.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 +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
|