roda 3.71.0 → 3.72.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d5460d6cecb4f9b9acfedd05f5b14793bb9aefa2df2a8c29c559da319df87ee4
4
- data.tar.gz: 75c3c8803abef4e27cac592a88597e8f9cd098be39bf1d0c1b1192175fd1f8e2
3
+ metadata.gz: d5c28e38d35f59176f159798f68d82bbd30df62a5907ace3a3750b1daf7b4fe6
4
+ data.tar.gz: cb5fd8d5a9d665bc820c55ccbf1fd6a068873ae3e265a1f877bbdf82b51c4d6e
5
5
  SHA512:
6
- metadata.gz: 6efc49bb205012a7ce50bc3c300d924a149de33416a35870f11efed492251c331804b970c967e47a481b0ddb0a83507c5926c1dc32069941b4edd2bd56df09e5
7
- data.tar.gz: 698b7e7daae4cd0712a20a1e3e274f7ba3cdb9068eefdeb3bb5f043f2d437cdd5dda961ce91d88794e22a8ca3ef5825e3f8bd3f92ff933eab772c352dd17c2ee
6
+ metadata.gz: d8710537511b8f332c443fd41bd279c99de53c0bc9618cd92f763ab7d354f70c4496ba9eafa076438087b5ab52f36e69f649aa00d2fb6f07d5315b7d61aef4a1
7
+ data.tar.gz: e0af216b465facc81e81ab8a495d472685c26aa6b2c1d56c0e48631586555f78f4d5922ac5ee92c6118a08b8162ee35866dc5708155bdbed70d5851b2ff8339b
data/CHANGELOG CHANGED
@@ -1,3 +1,11 @@
1
+ = 3.72.0 (2023-09-12)
2
+
3
+ * Add invalid_request_body plugin for custom handling of invalid request bodies (jeremyevans)
4
+
5
+ * Warn when defining method that expects 1 argument when block requires multiple arguments when :check_arity option is set to :warn (jeremyevans)
6
+
7
+ * Implement the match_hooks plugin using the match_hook_args plugin (jeremyevans)
8
+
1
9
  = 3.71.0 (2023-08-14)
2
10
 
3
11
  * 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,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.configure(app)
18
- app.opts[:match_hooks] ||= []
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
- opts[:match_hooks] << define_roda_method("match_hook", 0, &block)
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
data/lib/roda/version.rb CHANGED
@@ -4,7 +4,7 @@ class Roda
4
4
  RodaMajorVersion = 3
5
5
 
6
6
  # The minor version of Roda, updated for new feature releases of Roda.
7
- RodaMinorVersion = 71
7
+ RodaMinorVersion = 72
8
8
 
9
9
  # The patch version of Roda, updated only for bug fixes from the last
10
10
  # feature release.
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.71.0
4
+ version: 3.72.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-08-14 00:00:00.000000000 Z
11
+ date: 2023-09-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -245,6 +245,7 @@ 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
248
249
  - doc/release_notes/3.8.0.txt
249
250
  - doc/release_notes/3.9.0.txt
250
251
  files:
@@ -323,6 +324,7 @@ files:
323
324
  - doc/release_notes/3.7.0.txt
324
325
  - doc/release_notes/3.70.0.txt
325
326
  - doc/release_notes/3.71.0.txt
327
+ - doc/release_notes/3.72.0.txt
326
328
  - doc/release_notes/3.8.0.txt
327
329
  - doc/release_notes/3.9.0.txt
328
330
  - lib/roda.rb
@@ -386,6 +388,7 @@ files:
386
388
  - lib/roda/plugins/host_authorization.rb
387
389
  - lib/roda/plugins/indifferent_params.rb
388
390
  - lib/roda/plugins/inject_erb.rb
391
+ - lib/roda/plugins/invalid_request_body.rb
389
392
  - lib/roda/plugins/json.rb
390
393
  - lib/roda/plugins/json_parser.rb
391
394
  - lib/roda/plugins/link_to.rb