roda 3.61.0 → 3.62.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/doc/release_notes/3.62.0.txt +41 -0
- data/lib/roda/plugins/Integer_matcher_max.rb +54 -0
- data/lib/roda/plugins/_optimized_matching.rb +4 -4
- data/lib/roda/plugins/class_matchers.rb +12 -0
- data/lib/roda/plugins/halt.rb +1 -1
- 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 +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 912f354ffcb4440bf7955d4db8546f9eccbee3f3a3f91b77604a91228a2433c4
|
4
|
+
data.tar.gz: 8df8254014b7e8e9b6db623fa2b8269ac5485b5087ee53978080a81ba344a60c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bb43bcbad6e5421935d62a11abc3da27c40559ef1f55b9791d71ab22bd8cc4a73933f85bb68d77feb26efd6bf84f840bd5a202c80938ede330ca67cf9b51ca8b
|
7
|
+
data.tar.gz: 6f3234b37c506e3037864e7a7b79280f5b190758e8dada8f213b141cd1e4826a03a98017ddccb806082fa551580af9683088c94080157811867c0a3a1ec92b04
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
= 3.62.0 (2022-11-14)
|
2
|
+
|
3
|
+
* Add typecast_params_sized_integers plugin for converting parameters to sized integers (jeremyevans)
|
4
|
+
|
5
|
+
* Add Integer_matcher_max plugin for setting maximum integer value matched by the Integer matcher (jeremyevans)
|
6
|
+
|
7
|
+
* Allow class matchers in the class_matchers plugin to skip matching based on regexp match values (jeremyevans)
|
8
|
+
|
9
|
+
* Fix RodaRequest#matched_path when using unescape_path plugin (jeremyevans) (#286)
|
10
|
+
|
1
11
|
= 3.61.0 (2022-10-12)
|
2
12
|
|
3
13
|
* 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,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
|
@@ -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']
|
@@ -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.62.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-11-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -234,6 +234,7 @@ 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
|
237
238
|
- doc/release_notes/3.7.0.txt
|
238
239
|
- doc/release_notes/3.8.0.txt
|
239
240
|
- doc/release_notes/3.9.0.txt
|
@@ -302,12 +303,14 @@ files:
|
|
302
303
|
- doc/release_notes/3.6.0.txt
|
303
304
|
- doc/release_notes/3.60.0.txt
|
304
305
|
- doc/release_notes/3.61.0.txt
|
306
|
+
- doc/release_notes/3.62.0.txt
|
305
307
|
- doc/release_notes/3.7.0.txt
|
306
308
|
- doc/release_notes/3.8.0.txt
|
307
309
|
- doc/release_notes/3.9.0.txt
|
308
310
|
- lib/roda.rb
|
309
311
|
- lib/roda/cache.rb
|
310
312
|
- lib/roda/plugins.rb
|
313
|
+
- lib/roda/plugins/Integer_matcher_max.rb
|
311
314
|
- lib/roda/plugins/_after_hook.rb
|
312
315
|
- lib/roda/plugins/_before_hook.rb
|
313
316
|
- lib/roda/plugins/_optimized_matching.rb
|
@@ -423,6 +426,7 @@ files:
|
|
423
426
|
- lib/roda/plugins/timestamp_public.rb
|
424
427
|
- lib/roda/plugins/type_routing.rb
|
425
428
|
- lib/roda/plugins/typecast_params.rb
|
429
|
+
- lib/roda/plugins/typecast_params_sized_integers.rb
|
426
430
|
- lib/roda/plugins/unescape_path.rb
|
427
431
|
- lib/roda/plugins/view_options.rb
|
428
432
|
- lib/roda/request.rb
|