roda 3.71.0 → 3.73.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 +14 -0
- data/doc/release_notes/3.72.0.txt +48 -0
- data/doc/release_notes/3.73.0.txt +33 -0
- data/lib/roda/plugins/_base64.rb +34 -0
- data/lib/roda/plugins/exception_page.rb +1 -1
- data/lib/roda/plugins/invalid_request_body.rb +107 -0
- data/lib/roda/plugins/match_hook.rb +6 -43
- data/lib/roda/plugins/middleware.rb +46 -0
- data/lib/roda/plugins/route_csrf.rb +7 -4
- data/lib/roda/plugins/sessions.rb +6 -3
- data/lib/roda/version.rb +1 -1
- data/lib/roda.rb +4 -0
- metadata +8 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7a47f703af806a15f523b99b38d084520bada92f23196374d6d9781d5953faa8
|
|
4
|
+
data.tar.gz: 4612153820b89e6dbcfa2370c04269666c49277d8f11256869f6c1f0bb0b571a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bdc42cdc9540750195327dac290e3f0bb08c3ed0100b610441b644c85849e7e9f9f974013cea041cdf640f590e2027996d68b62eea9c31d41bd42a57df6530bb
|
|
7
|
+
data.tar.gz: 3ab05db704cf45803ad706e78b558ea7798d8d9782a06c7dec79814a4d862582249e5554946c59fff88e1f1d2d360e242268c593a8c9c95fe87b5489e4a4a44c
|
data/CHANGELOG
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
= 3.73.0 (2023-10-13)
|
|
2
|
+
|
|
3
|
+
* Support :next_if_not_found option for middleware plugin (jeremyevans) (#334)
|
|
4
|
+
|
|
5
|
+
* Remove dependency on base64 library from sessions and route_csrf plugin, as it will not be part of the standard library in Ruby 3.4+ (jeremyevans)
|
|
6
|
+
|
|
7
|
+
= 3.72.0 (2023-09-12)
|
|
8
|
+
|
|
9
|
+
* Add invalid_request_body plugin for custom handling of invalid request bodies (jeremyevans)
|
|
10
|
+
|
|
11
|
+
* Warn when defining method that expects 1 argument when block requires multiple arguments when :check_arity option is set to :warn (jeremyevans)
|
|
12
|
+
|
|
13
|
+
* Implement the match_hooks plugin using the match_hook_args plugin (jeremyevans)
|
|
14
|
+
|
|
1
15
|
= 3.71.0 (2023-08-14)
|
|
2
16
|
|
|
3
17
|
* Add match_hook_args plugin, similar to match_hooks but support matchers and block args as hook arguments (jeremyevans)
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
= New Features
|
|
2
|
+
|
|
3
|
+
* An invalid_request_body plugin has been added for allowing custom
|
|
4
|
+
handling of invalid request bodies. Roda uses Rack's request body
|
|
5
|
+
parsing, and by default invalid request bodies can result in
|
|
6
|
+
different exceptions based on how the body is invalid and which
|
|
7
|
+
version of Rack is in use.
|
|
8
|
+
|
|
9
|
+
If you want to treat an invalid request body as the submission of
|
|
10
|
+
no parameters, you can use the :empty_hash argument when loading
|
|
11
|
+
the plugin:
|
|
12
|
+
|
|
13
|
+
plugin :invalid_request_body, :empty_hash
|
|
14
|
+
|
|
15
|
+
If you want to return a empty 400 (Bad Request) response if an
|
|
16
|
+
invalid request body is submitted, you can use the :empty_400
|
|
17
|
+
argument when loading the plugin:
|
|
18
|
+
|
|
19
|
+
plugin :invalid_request_body, :empty_400
|
|
20
|
+
|
|
21
|
+
If you want to raise a Roda::RodaPlugins::InvalidRequestBody::Error
|
|
22
|
+
exception if an invalid request body is submitted (which makes it
|
|
23
|
+
easier to handle these exceptions when using the error_handler
|
|
24
|
+
plugin), you can use the :raise argument when loading the plugin:
|
|
25
|
+
|
|
26
|
+
plugin :invalid_request_body, :raise
|
|
27
|
+
|
|
28
|
+
For custom behavior, you can pass a block when loading the plugin
|
|
29
|
+
The block is called with the exception Rack raised when parsing the
|
|
30
|
+
body. The block will be used to define a method in the application's
|
|
31
|
+
RodaRequest class. It can either return a hash of parameters, or
|
|
32
|
+
you can raise a different exception, or you can halt processing and
|
|
33
|
+
return a response:
|
|
34
|
+
|
|
35
|
+
plugin :invalid_request_body do |exception|
|
|
36
|
+
# To treat the exception raised as a submitted parameter
|
|
37
|
+
{body_error: exception}
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
= Other Improvements
|
|
41
|
+
|
|
42
|
+
* When using the check_arity: :warn Roda option, Roda now correctly
|
|
43
|
+
warns when defining a method that expects a single argument when
|
|
44
|
+
the provided block requires multiple arguments.
|
|
45
|
+
|
|
46
|
+
* The match_hooks plugin is now implemented using the match_hook_args
|
|
47
|
+
plugin, simplifying the implementation. This change should be
|
|
48
|
+
transparent unless you were reaching into the internals.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
= New Features
|
|
2
|
+
|
|
3
|
+
* The middleware plugin now accepts a :next_if_not_found option.
|
|
4
|
+
This allows the middleware plugin to pass the request to the next
|
|
5
|
+
application if the current application handles the request but
|
|
6
|
+
ends up calling the not_found handler. With the following
|
|
7
|
+
middleware:
|
|
8
|
+
|
|
9
|
+
class Mid < Roda
|
|
10
|
+
plugin :middleware
|
|
11
|
+
|
|
12
|
+
route do |r|
|
|
13
|
+
r.on "foo" do
|
|
14
|
+
r.get "bar" do
|
|
15
|
+
'bar'
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
Requests for /x would be forwarded to the next application, since
|
|
22
|
+
the application doesn't handle the request, but requests for /foo/x
|
|
23
|
+
would not be, because the middleware is partially handling the
|
|
24
|
+
request in the r.on "foo" block. With the :next_if_not_found
|
|
25
|
+
option, only requests for /foo/bar would be handled by the
|
|
26
|
+
middleware, and all other requests would be forwarded to the next
|
|
27
|
+
application.
|
|
28
|
+
|
|
29
|
+
= Other Improvements
|
|
30
|
+
|
|
31
|
+
* The sessions and route_csrf plugins no longer depend on the base64
|
|
32
|
+
library. base64 will be removed from Ruby's standard library
|
|
33
|
+
starting in Ruby 3.4.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
class Roda
|
|
5
|
+
module RodaPlugins
|
|
6
|
+
module Base64_
|
|
7
|
+
class << self
|
|
8
|
+
if RUBY_VERSION >= '2.4'
|
|
9
|
+
def decode64(str)
|
|
10
|
+
str.unpack1("m0")
|
|
11
|
+
end
|
|
12
|
+
# :nocov:
|
|
13
|
+
else
|
|
14
|
+
def decode64(str)
|
|
15
|
+
str.unpack("m0")[0]
|
|
16
|
+
end
|
|
17
|
+
# :nocov:
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def urlsafe_encode64(bin)
|
|
21
|
+
str = [bin].pack("m0")
|
|
22
|
+
str.tr!("+/", "-_")
|
|
23
|
+
str
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def urlsafe_decode64(str)
|
|
27
|
+
decode64(str.tr("-_", "+/"))
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
register_plugin(:_base64, Base64_)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
class Roda
|
|
5
|
+
module RodaPlugins
|
|
6
|
+
# The invalid_request_body plugin allows for custom handling of invalid request
|
|
7
|
+
# bodies. Roda uses Rack for parsing request bodies, so by default, any
|
|
8
|
+
# invalid request bodies would result in Rack raising an exception, and the
|
|
9
|
+
# exception could change for different reasons the request body is invalid.
|
|
10
|
+
# This plugin overrides RodaRequest#POST (which parses parameters from request
|
|
11
|
+
# bodies), and if parsing raises an exception, it allows for custom behavior.
|
|
12
|
+
#
|
|
13
|
+
# If you want to treat an invalid request body as the submission of no parameters,
|
|
14
|
+
# you can use the :empty_hash argument when loading the plugin:
|
|
15
|
+
#
|
|
16
|
+
# plugin :invalid_request_body, :empty_hash
|
|
17
|
+
#
|
|
18
|
+
# If you want to return a empty 400 (Bad Request) response if an invalid request
|
|
19
|
+
# body is submitted, you can use the :empty_400 argument when loading the plugin:
|
|
20
|
+
#
|
|
21
|
+
# plugin :invalid_request_body, :empty_400
|
|
22
|
+
#
|
|
23
|
+
# If you want to raise a Roda::RodaPlugins::InvalidRequestBody::Error exception
|
|
24
|
+
# if an invalid request body is submitted (which makes it easier to handle these
|
|
25
|
+
# exceptions when using the error_handler plugin), you can use the :raise argument
|
|
26
|
+
# when loading the plugin:
|
|
27
|
+
#
|
|
28
|
+
# plugin :invalid_request_body, :raise
|
|
29
|
+
#
|
|
30
|
+
# For custom behavior, you can pass a block when loading the plugin. The block
|
|
31
|
+
# is called with the exception Rack raised when parsing the body. The block will
|
|
32
|
+
# be used to define a method in the application's RodaRequest class. It can either
|
|
33
|
+
# return a hash of parameters, or you can raise a different exception, or you
|
|
34
|
+
# can halt processing and return a response:
|
|
35
|
+
#
|
|
36
|
+
# plugin :invalid_request_body do |exception|
|
|
37
|
+
# # To treat the exception raised as a submitted parameter
|
|
38
|
+
# {body_error: exception}
|
|
39
|
+
# end
|
|
40
|
+
module InvalidRequestBody
|
|
41
|
+
# Exception class raised for invalid request bodies.
|
|
42
|
+
Error = Class.new(RodaError)
|
|
43
|
+
|
|
44
|
+
# Set the action to use (:empty_400, :empty_hash, :raise) for invalid request bodies,
|
|
45
|
+
# or use a block for custom behavior.
|
|
46
|
+
def self.configure(app, action=nil, &block)
|
|
47
|
+
if action
|
|
48
|
+
if block
|
|
49
|
+
raise RodaError, "cannot provide both block and action when loading invalid_request_body plugin"
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
method = :"handle_invalid_request_body_#{action}"
|
|
53
|
+
unless RequestMethods.private_method_defined?(method)
|
|
54
|
+
raise RodaError, "invalid invalid_request_body action provided: #{action}"
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
app::RodaRequest.send(:alias_method, :handle_invalid_request_body, method)
|
|
58
|
+
elsif block
|
|
59
|
+
app::RodaRequest.class_eval do
|
|
60
|
+
define_method(:handle_invalid_request_body, &block)
|
|
61
|
+
alias handle_invalid_request_body handle_invalid_request_body
|
|
62
|
+
end
|
|
63
|
+
else
|
|
64
|
+
raise RodaError, "must provide block or action when loading invalid_request_body plugin"
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
app::RodaRequest.send(:private, :handle_invalid_request_body)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
module RequestMethods
|
|
71
|
+
# Handle invalid request bodies as configured if the default behavior
|
|
72
|
+
# raises an exception.
|
|
73
|
+
def POST
|
|
74
|
+
super
|
|
75
|
+
rescue => e
|
|
76
|
+
handle_invalid_request_body(e)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
private
|
|
80
|
+
|
|
81
|
+
# Return an empty 400 HTTP response for invalid request bodies.
|
|
82
|
+
def handle_invalid_request_body_empty_400(e)
|
|
83
|
+
response.status = 400
|
|
84
|
+
headers = response.headers
|
|
85
|
+
headers.clear
|
|
86
|
+
headers[RodaResponseHeaders::CONTENT_TYPE] = 'text/html'
|
|
87
|
+
headers[RodaResponseHeaders::CONTENT_LENGTH] ='0'
|
|
88
|
+
throw :halt, response.finish_with_body([])
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Treat invalid request bodies by using an empty hash as the
|
|
92
|
+
# POST params.
|
|
93
|
+
def handle_invalid_request_body_empty_hash(e)
|
|
94
|
+
{}
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Raise a specific error for all invalid request bodies,
|
|
98
|
+
# to allow for easy rescuing using the error_handler plugin.
|
|
99
|
+
def handle_invalid_request_body_raise(e)
|
|
100
|
+
raise Error, e.message
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
register_plugin(:invalid_request_body, InvalidRequestBody)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
@@ -6,7 +6,8 @@ class Roda
|
|
|
6
6
|
# The match_hook plugin adds hooks that are called upon a successful match
|
|
7
7
|
# by any of the matchers. The hooks do not take any arguments. If you would
|
|
8
8
|
# like hooks that pass the arguments/matchers and values yielded to the route block,
|
|
9
|
-
# use the match_hook_args plugin.
|
|
9
|
+
# use the match_hook_args plugin. This uses the match_hook_args plugin internally,
|
|
10
|
+
# but doesn't pass the matchers and values yielded.
|
|
10
11
|
#
|
|
11
12
|
# plugin :match_hook
|
|
12
13
|
#
|
|
@@ -14,56 +15,18 @@ class Roda
|
|
|
14
15
|
# logger.debug("#{request.matched_path} matched. #{request.remaining_path} remaining.")
|
|
15
16
|
# end
|
|
16
17
|
module MatchHook
|
|
17
|
-
def self.
|
|
18
|
-
app.
|
|
18
|
+
def self.load_dependencies(app)
|
|
19
|
+
app.plugin :match_hook_args
|
|
19
20
|
end
|
|
20
21
|
|
|
21
22
|
module ClassMethods
|
|
22
|
-
# Freeze the array of hook methods when freezing the app
|
|
23
|
-
def freeze
|
|
24
|
-
opts[:match_hooks].freeze
|
|
25
|
-
super
|
|
26
|
-
end
|
|
27
|
-
|
|
28
23
|
# Add a match hook.
|
|
29
24
|
def match_hook(&block)
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
if opts[:match_hooks].length == 1
|
|
33
|
-
class_eval("alias _match_hook #{opts[:match_hooks].first}", __FILE__, __LINE__)
|
|
34
|
-
else
|
|
35
|
-
class_eval("def _match_hook; #{opts[:match_hooks].join(';')} end", __FILE__, __LINE__)
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
public :_match_hook
|
|
39
|
-
|
|
25
|
+
meth = define_roda_method("match_hook", 0, &block)
|
|
26
|
+
add_match_hook{|_,_| send(meth)}
|
|
40
27
|
nil
|
|
41
28
|
end
|
|
42
29
|
end
|
|
43
|
-
|
|
44
|
-
module InstanceMethods
|
|
45
|
-
# Default empty method if no match hooks are defined.
|
|
46
|
-
def _match_hook
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
module RequestMethods
|
|
51
|
-
private
|
|
52
|
-
|
|
53
|
-
# Call the match hook if yielding to the block before yielding to the block.
|
|
54
|
-
def if_match(_)
|
|
55
|
-
super do |*a|
|
|
56
|
-
scope._match_hook
|
|
57
|
-
yield(*a)
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
# Call the match hook before yielding to the block
|
|
62
|
-
def always
|
|
63
|
-
scope._match_hook
|
|
64
|
-
super
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
30
|
end
|
|
68
31
|
|
|
69
32
|
register_plugin :match_hook, MatchHook
|
|
@@ -33,6 +33,43 @@ class Roda
|
|
|
33
33
|
#
|
|
34
34
|
# run App
|
|
35
35
|
#
|
|
36
|
+
# By default, when the app is used as middleware and handles the request at
|
|
37
|
+
# all, it does not forward the request to the next middleware. For the
|
|
38
|
+
# following setup:
|
|
39
|
+
#
|
|
40
|
+
# class Mid < Roda
|
|
41
|
+
# plugin :middleware
|
|
42
|
+
#
|
|
43
|
+
# route do |r|
|
|
44
|
+
# r.on "foo" do
|
|
45
|
+
# r.is "mid" do
|
|
46
|
+
# "Mid"
|
|
47
|
+
# end
|
|
48
|
+
# end
|
|
49
|
+
# end
|
|
50
|
+
# end
|
|
51
|
+
#
|
|
52
|
+
# class App < Roda
|
|
53
|
+
# use Mid
|
|
54
|
+
#
|
|
55
|
+
# route do |r|
|
|
56
|
+
# r.on "foo" do
|
|
57
|
+
# r.is "app" do
|
|
58
|
+
# "App"
|
|
59
|
+
# end
|
|
60
|
+
# end
|
|
61
|
+
# end
|
|
62
|
+
# end
|
|
63
|
+
#
|
|
64
|
+
# run App
|
|
65
|
+
#
|
|
66
|
+
# Requests for +/foo/mid will+ return +Mid+, but requests for +/foo/app+
|
|
67
|
+
# will return an empty 404 response, because the middleware handles the
|
|
68
|
+
# +/foo/app+ request in the <tt>r.on "foo" do</tt> block, but does not
|
|
69
|
+
# have the block return a result, which Roda treats as an empty 404 response.
|
|
70
|
+
# If you would like the middleware to forward +/foo/app+ request to the
|
|
71
|
+
# application, you should use the +:next_if_not_found+ plugin option.
|
|
72
|
+
#
|
|
36
73
|
# It is possible to use the Roda app as a regular app even when using
|
|
37
74
|
# the middleware plugin. Using an app as middleware automatically creates
|
|
38
75
|
# a subclass of the app for the middleware. Because a subclass is automatically
|
|
@@ -64,6 +101,9 @@ class Roda
|
|
|
64
101
|
# # Request to App for /mid returns
|
|
65
102
|
# # "foo bar baz"
|
|
66
103
|
module Middleware
|
|
104
|
+
NEXT_PROC = lambda{throw :next, true}
|
|
105
|
+
private_constant :NEXT_PROC
|
|
106
|
+
|
|
67
107
|
# Configure the middleware plugin. Options:
|
|
68
108
|
# :env_var :: Set the environment variable to use to indicate to the roda
|
|
69
109
|
# application that the current request is a middleware request.
|
|
@@ -77,12 +117,15 @@ class Roda
|
|
|
77
117
|
# the middleware's route block should be applied to the
|
|
78
118
|
# final response when the request is forwarded to the app.
|
|
79
119
|
# Defaults to false.
|
|
120
|
+
# :next_if_not_found :: If the middleware handles the request but returns a not found
|
|
121
|
+
# result (404 with no body), forward the result to the next middleware.
|
|
80
122
|
def self.configure(app, opts={}, &block)
|
|
81
123
|
app.opts[:middleware_env_var] = opts[:env_var] if opts.has_key?(:env_var)
|
|
82
124
|
app.opts[:middleware_env_var] ||= 'roda.forward_next'
|
|
83
125
|
app.opts[:middleware_configure] = block if block
|
|
84
126
|
app.opts[:middleware_handle_result] = opts[:handle_result]
|
|
85
127
|
app.opts[:middleware_forward_response_headers] = opts[:forward_response_headers]
|
|
128
|
+
app.opts[:middleware_next_if_not_found] = opts[:next_if_not_found]
|
|
86
129
|
end
|
|
87
130
|
|
|
88
131
|
# Forwarder instances are what is actually used as middleware.
|
|
@@ -91,6 +134,9 @@ class Roda
|
|
|
91
134
|
# and store +app+ as the next middleware to call.
|
|
92
135
|
def initialize(mid, app, *args, &block)
|
|
93
136
|
@mid = Class.new(mid)
|
|
137
|
+
if @mid.opts[:middleware_next_if_not_found]
|
|
138
|
+
@mid.plugin(:not_found, &NEXT_PROC)
|
|
139
|
+
end
|
|
94
140
|
if configure = @mid.opts[:middleware_configure]
|
|
95
141
|
configure.call(@mid, *args, &block)
|
|
96
142
|
elsif block || !args.empty?
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# frozen-string-literal: true
|
|
2
2
|
|
|
3
|
-
require 'base64'
|
|
4
3
|
require 'openssl'
|
|
5
4
|
require 'securerandom'
|
|
6
5
|
require 'uri'
|
|
@@ -163,6 +162,10 @@ class Roda
|
|
|
163
162
|
# a valid CSRF token was not provided.
|
|
164
163
|
class InvalidToken < RodaError; end
|
|
165
164
|
|
|
165
|
+
def self.load_dependencies(app, opts=OPTS)
|
|
166
|
+
app.plugin :_base64
|
|
167
|
+
end
|
|
168
|
+
|
|
166
169
|
def self.configure(app, opts=OPTS, &block)
|
|
167
170
|
options = app.opts[:route_csrf] = (app.opts[:route_csrf] || DEFAULTS).merge(opts)
|
|
168
171
|
if block || opts[:csrf_failure].is_a?(Proc)
|
|
@@ -260,7 +263,7 @@ class Roda
|
|
|
260
263
|
def csrf_token(path=nil, method=('POST' if path))
|
|
261
264
|
token = SecureRandom.random_bytes(31)
|
|
262
265
|
token << csrf_hmac(token, method, path)
|
|
263
|
-
|
|
266
|
+
[token].pack("m0")
|
|
264
267
|
end
|
|
265
268
|
|
|
266
269
|
# Whether request-specific CSRF tokens should be used by default.
|
|
@@ -314,7 +317,7 @@ class Roda
|
|
|
314
317
|
end
|
|
315
318
|
|
|
316
319
|
begin
|
|
317
|
-
submitted_hmac =
|
|
320
|
+
submitted_hmac = Base64_.decode64(encoded_token)
|
|
318
321
|
rescue ArgumentError
|
|
319
322
|
return "encoded token is not valid base64"
|
|
320
323
|
end
|
|
@@ -354,7 +357,7 @@ class Roda
|
|
|
354
357
|
# JSON is used for session serialization).
|
|
355
358
|
def csrf_secret
|
|
356
359
|
key = session[csrf_options[:key]] ||= SecureRandom.base64(32)
|
|
357
|
-
|
|
360
|
+
Base64_.decode64(key)
|
|
358
361
|
end
|
|
359
362
|
end
|
|
360
363
|
end
|
|
@@ -10,7 +10,6 @@ rescue OpenSSL::Cipher::CipherError
|
|
|
10
10
|
# :nocov:
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
-
require 'base64'
|
|
14
13
|
require 'json'
|
|
15
14
|
require 'securerandom'
|
|
16
15
|
require 'zlib'
|
|
@@ -171,6 +170,10 @@ class Roda
|
|
|
171
170
|
[cipher_secret.freeze, hmac_secret.freeze]
|
|
172
171
|
end
|
|
173
172
|
|
|
173
|
+
def self.load_dependencies(app, opts=OPTS)
|
|
174
|
+
app.plugin :_base64
|
|
175
|
+
end
|
|
176
|
+
|
|
174
177
|
# Configure the plugin, see Sessions for details on options.
|
|
175
178
|
def self.configure(app, opts=OPTS)
|
|
176
179
|
opts = (app.opts[:sessions] || DEFAULT_OPTIONS).merge(opts)
|
|
@@ -344,7 +347,7 @@ class Roda
|
|
|
344
347
|
opts = roda_class.opts[:sessions]
|
|
345
348
|
|
|
346
349
|
begin
|
|
347
|
-
data =
|
|
350
|
+
data = Base64_.urlsafe_decode64(data)
|
|
348
351
|
rescue ArgumentError
|
|
349
352
|
return _session_serialization_error("Unable to decode session: invalid base64")
|
|
350
353
|
end
|
|
@@ -493,7 +496,7 @@ class Roda
|
|
|
493
496
|
data << encrypted_data
|
|
494
497
|
data << OpenSSL::HMAC.digest(OpenSSL::Digest::SHA256.new, opts[:hmac_secret], data+opts[:key])
|
|
495
498
|
|
|
496
|
-
data =
|
|
499
|
+
data = Base64_.urlsafe_encode64(data)
|
|
497
500
|
|
|
498
501
|
if data.bytesize >= 4096
|
|
499
502
|
raise CookieTooLarge, "attempted to create cookie larger than 4096 bytes"
|
data/lib/roda/version.rb
CHANGED
data/lib/roda.rb
CHANGED
|
@@ -88,6 +88,7 @@ class Roda
|
|
|
88
88
|
end
|
|
89
89
|
call_meth = meth
|
|
90
90
|
|
|
91
|
+
# RODA4: Switch to false # :warn in last Roda 3 version
|
|
91
92
|
if (check_arity = opts.fetch(:check_arity, true)) && !block.lambda?
|
|
92
93
|
required_args, optional_args, rest, keyword = _define_roda_method_arg_numbers(block)
|
|
93
94
|
|
|
@@ -117,6 +118,9 @@ class Roda
|
|
|
117
118
|
alias_method meth, meth
|
|
118
119
|
meth = :"#{meth}_arity"
|
|
119
120
|
elsif required_args > 1
|
|
121
|
+
if check_arity == :warn
|
|
122
|
+
RodaPlugins.warn "Arity mismatch in block passed to define_roda_method. Expected Arity 1, but multiple arguments required for #{block.inspect}"
|
|
123
|
+
end
|
|
120
124
|
b = block
|
|
121
125
|
block = lambda{|r| instance_exec(r, &b)} # Fallback
|
|
122
126
|
end
|
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.73.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: 2023-
|
|
11
|
+
date: 2023-10-13 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rack
|
|
@@ -245,6 +245,8 @@ extra_rdoc_files:
|
|
|
245
245
|
- doc/release_notes/3.7.0.txt
|
|
246
246
|
- doc/release_notes/3.70.0.txt
|
|
247
247
|
- doc/release_notes/3.71.0.txt
|
|
248
|
+
- doc/release_notes/3.72.0.txt
|
|
249
|
+
- doc/release_notes/3.73.0.txt
|
|
248
250
|
- doc/release_notes/3.8.0.txt
|
|
249
251
|
- doc/release_notes/3.9.0.txt
|
|
250
252
|
files:
|
|
@@ -323,6 +325,8 @@ files:
|
|
|
323
325
|
- doc/release_notes/3.7.0.txt
|
|
324
326
|
- doc/release_notes/3.70.0.txt
|
|
325
327
|
- doc/release_notes/3.71.0.txt
|
|
328
|
+
- doc/release_notes/3.72.0.txt
|
|
329
|
+
- doc/release_notes/3.73.0.txt
|
|
326
330
|
- doc/release_notes/3.8.0.txt
|
|
327
331
|
- doc/release_notes/3.9.0.txt
|
|
328
332
|
- lib/roda.rb
|
|
@@ -330,6 +334,7 @@ files:
|
|
|
330
334
|
- lib/roda/plugins.rb
|
|
331
335
|
- lib/roda/plugins/Integer_matcher_max.rb
|
|
332
336
|
- lib/roda/plugins/_after_hook.rb
|
|
337
|
+
- lib/roda/plugins/_base64.rb
|
|
333
338
|
- lib/roda/plugins/_before_hook.rb
|
|
334
339
|
- lib/roda/plugins/_optimized_matching.rb
|
|
335
340
|
- lib/roda/plugins/_symbol_regexp_matchers.rb
|
|
@@ -386,6 +391,7 @@ files:
|
|
|
386
391
|
- lib/roda/plugins/host_authorization.rb
|
|
387
392
|
- lib/roda/plugins/indifferent_params.rb
|
|
388
393
|
- lib/roda/plugins/inject_erb.rb
|
|
394
|
+
- lib/roda/plugins/invalid_request_body.rb
|
|
389
395
|
- lib/roda/plugins/json.rb
|
|
390
396
|
- lib/roda/plugins/json_parser.rb
|
|
391
397
|
- lib/roda/plugins/link_to.rb
|