roda 3.80.0 → 3.81.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0cebe935d536e1f903b212075108ba9cbcade4aa2e8d2abf1c5e0d6e6f539ce8
4
- data.tar.gz: 9b0c576aaa36c5a05596c1bc1bec23d3ab0f37c56dc72342bfa962b10442928f
3
+ metadata.gz: a9d94f31e568bd2774c3e582152f0bcdbffdf3fcd7e5a95241e73b3fd5b7ac3c
4
+ data.tar.gz: b9ad44642acdbaa0035cbd6ece521ca3432d2e7c23d75a331172ecd6c6288c60
5
5
  SHA512:
6
- metadata.gz: 0e83d0fe8e1f70bb196ea5f285f7a00590ab1669e4b1d686f859d1e5c65a8e760d1320b345306740d00c7d063f0f6bada1af88433b3b04c6b429f439bb7e2521
7
- data.tar.gz: e9b0ffd5b5fb7e976a971f11fbed4f0beb35868dcb7aa70c41c005046a9053cb6c62caf29f669c02cd53e67cd5db51a28076f058824c90a1c1b917a9b7f0f4fb
6
+ metadata.gz: 1cd64e84b47a1a7a01d9165d16e14d95d2c43287b58f2557d9492a201832c1388157152eab1fd12052c7691e3969e5ce1cb9c0ad706e73ad6de822dcc29e1590
7
+ data.tar.gz: 86320c603d0c9b90e2c82f16cc5229b76afe66dde5bdbccce9b28ce076e80808a35410098fe0eae5cb3f5b3180b79f4265b3d525e7861a9dd65890315d274fad
data/CHANGELOG CHANGED
@@ -1,3 +1,11 @@
1
+ = 3.81.0 (2024-06-12)
2
+
3
+ * Make assets plugin :early_hints option follow Rack 3 SPEC if using Rack 3 (jeremyevans)
4
+
5
+ * Correctly parse Ruby 3.4 backtraces in exception_page plugin (jeremyevans)
6
+
7
+ * Support :until and :seconds option in hmac_paths plugin, for paths valid only until a specific time (jeremyevans)
8
+
1
9
  = 3.80.0 (2024-05-10)
2
10
 
3
11
  * Support :namespace option in hmac_paths plugin, allowing for easy per-user/per-group HMAC paths (jeremyevans)
@@ -0,0 +1,24 @@
1
+ = New Features
2
+
3
+ * The hmac_paths plugin now supports :until and :seconds options for
4
+ hmac_path, to create a path that is only valid for a specific amount of
5
+ time. :until sets a specific time that the path will be valid until,
6
+ and :seconds makes the path only valid for the given number of seconds.
7
+
8
+ hmac_path('/widget/1', until: Time.utc(2100))
9
+ # => "/dc8b6e56e4cbe7815df7880d42f0e02956b2e4c49881b6060ceb0e49745a540d/t/4102444800/widget/1"
10
+
11
+ Requests for the path after the given time will not be matched by
12
+ r.hmac_path.
13
+
14
+ = Other Improvements
15
+
16
+ * The early_hints plugin now correctly follows the Rack 3 SPEC when
17
+ using Rack 3. This was not caught previously because Rack only
18
+ added official support for early_hints in the last month.
19
+
20
+ * Ruby 3.4 backtraces are now parsed correctly in the exception_page
21
+ plugin.
22
+
23
+ * Some plugins that accept a block no longer issue an unused block
24
+ warning on Ruby 3.4.
@@ -736,7 +736,9 @@ class Roda
736
736
  paths = assets_paths(type)
737
737
  if o[:early_hints]
738
738
  early_hint_as = ltype == :js ? 'script' : 'style'
739
- send_early_hints('Link'=>paths.map{|p| "<#{p}>; rel=preload; as=#{early_hint_as}"}.join("\n"))
739
+ early_hints = paths.map{|p| "<#{p}>; rel=preload; as=#{early_hint_as}"}
740
+ early_hints = early_hints.join("\n") if Rack.release < '3'
741
+ send_early_hints(RodaResponseHeaders::LINK=>early_hints)
740
742
  end
741
743
  paths.map{|p| "#{tag_start}#{h(p)}#{tag_end}"}.join("\n")
742
744
  end
@@ -245,7 +245,7 @@ END
245
245
 
246
246
  frames = exception.backtrace.map.with_index do |line, i|
247
247
  frame = {:id=>i}
248
- if line =~ /\A(.*?):(\d+)(?::in `(.*)')?\Z/
248
+ if line =~ /\A(.*?):(\d+)(?::in [`'](.*)')?\Z/
249
249
  filename = frame[:filename] = $1
250
250
  lineno = frame[:lineno] = $2.to_i
251
251
  frame[:function] = $3
@@ -21,7 +21,7 @@ class Roda
21
21
  # !request.path.start_with?('/admin/')
22
22
  # end
23
23
  module FilterCommonLogger
24
- def self.load_dependencies(app)
24
+ def self.load_dependencies(app, &_)
25
25
  app.plugin :common_logger
26
26
  end
27
27
 
@@ -112,6 +112,16 @@ class Roda
112
112
  # this for POST requests (or other HTTP verbs that can have request bodies), use +r.GET+
113
113
  # instead of +r.params+ to specifically check query string parameters.
114
114
  #
115
+ # The generated paths can be timestamped, so that they are only valid until a given time
116
+ # or for a given number of seconds after they are generated, using the :until or :seconds
117
+ # options:
118
+ #
119
+ # hmac_path('/widget/1', until: Time.utc(2100))
120
+ # # => "/dc8b6e56e4cbe7815df7880d42f0e02956b2e4c49881b6060ceb0e49745a540d/t/4102444800/widget/1"
121
+ #
122
+ # hmac_path('/widget/1', seconds: Time.utc(2100).to_i - Time.now.to_i)
123
+ # # => "/dc8b6e56e4cbe7815df7880d42f0e02956b2e4c49881b6060ceb0e49745a540d/t/4102444800/widget/1"
124
+ #
115
125
  # The :namespace option, if provided, should be a string, and it modifies the generated HMACs
116
126
  # to only match those in the same namespace. This can be used to provide different paths to
117
127
  # different users or groups of users.
@@ -190,6 +200,11 @@ class Roda
190
200
  # r.hmac_path('/1', params: {k: 2})
191
201
  # HMAC_hex(HMAC_hex(secret, ''), '/p/1?k=2')
192
202
  #
203
+ # The +:until+ and +:seconds+ option include the timestamp in the HMAC:
204
+ #
205
+ # r.hmac_path('/1', until: Time.utc(2100))
206
+ # HMAC_hex(HMAC_hex(secret, ''), '/t/4102444800/1')
207
+ #
193
208
  # If a +:namespace+ option is provided, the original secret used before the +:root+ option is
194
209
  # an HMAC of the +:secret+ plugin option and the given namespace.
195
210
  #
@@ -232,6 +247,8 @@ class Roda
232
247
  # the already matched path of the routing tree using r.hmac_path. Defaults
233
248
  # to the empty string, which will returns paths valid for r.hmac_path at
234
249
  # the top level of the routing tree.
250
+ # :seconds :: Make the given path valid for the given integer number of seconds.
251
+ # :until :: Make the given path valid until the given Time.
235
252
  def hmac_path(path, opts=OPTS)
236
253
  unless path.is_a?(String) && path.getbyte(0) == 47
237
254
  raise RodaError, "path must be a string starting with /"
@@ -242,6 +259,12 @@ class Roda
242
259
  raise RodaError, "root must be empty string or string starting with /"
243
260
  end
244
261
 
262
+ if valid_until = opts[:until]
263
+ valid_until = valid_until.to_i
264
+ elsif seconds = opts[:seconds]
265
+ valid_until = Time.now.to_i + seconds
266
+ end
267
+
245
268
  flags = String.new
246
269
  path = path.dup
247
270
 
@@ -258,6 +281,11 @@ class Roda
258
281
  flags << 'n'
259
282
  end
260
283
 
284
+ if valid_until
285
+ flags << 't'
286
+ path = "/#{valid_until}#{path}"
287
+ end
288
+
261
289
  flags << '0' if flags.empty?
262
290
 
263
291
  hmac_path = if method
@@ -335,7 +363,19 @@ class Roda
335
363
  end
336
364
 
337
365
  if hmac_path_valid?(mpath, rpath, submitted_hmac, opts)
338
- always(&block)
366
+ if flags.include?('t')
367
+ on Integer do |int|
368
+ if int >= Time.now.to_i
369
+ always(&block)
370
+ else
371
+ # Return from method without matching
372
+ @remaining_path = orig_path
373
+ return
374
+ end
375
+ end
376
+ else
377
+ always(&block)
378
+ end
339
379
  end
340
380
  end
341
381
 
@@ -53,13 +53,10 @@ class Roda
53
53
 
54
54
  class Params < Rack::QueryParser::Params
55
55
  if Rack.release >= '3'
56
- # rack main branch compatibility
57
- # :nocov:
58
56
  if Params < Hash
59
57
  def initialize
60
58
  super(&INDIFFERENT_PROC)
61
59
  end
62
- # :nocov:
63
60
  else
64
61
  def initialize
65
62
  @size = 0
@@ -31,7 +31,7 @@ class Roda
31
31
  # still exists mainly for backward compatibility.
32
32
  module NotFound
33
33
  # Require the status_handler plugin
34
- def self.load_dependencies(app)
34
+ def self.load_dependencies(app, &_)
35
35
  app.plugin :status_handler
36
36
  end
37
37
 
@@ -172,7 +172,7 @@ class Roda
172
172
  # a valid CSRF token was not provided.
173
173
  class InvalidToken < RodaError; end
174
174
 
175
- def self.load_dependencies(app, opts=OPTS)
175
+ def self.load_dependencies(app, opts=OPTS, &_)
176
176
  app.plugin :_base64
177
177
  end
178
178
 
@@ -476,7 +476,7 @@ class Roda
476
476
  serialized_data << json_data
477
477
 
478
478
  cipher_secret = opts[:cipher_secret]
479
- if per_cookie_secret = opts[:per_cookie_cipher_secret]
479
+ if opts[:per_cookie_cipher_secret]
480
480
  version = "\1"
481
481
  per_cookie_secret_base = SecureRandom.random_bytes(32)
482
482
  cipher_secret = OpenSSL::HMAC.digest(OpenSSL::Digest::SHA256.new, cipher_secret, per_cookie_secret_base)
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 = 80
7
+ RodaMinorVersion = 81
8
8
 
9
9
  # The patch version of Roda, updated only for bug fixes from the last
10
10
  # feature release.
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.80.0
4
+ version: 3.81.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: 2024-05-10 00:00:00.000000000 Z
11
+ date: 2024-06-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -255,6 +255,7 @@ extra_rdoc_files:
255
255
  - doc/release_notes/3.79.0.txt
256
256
  - doc/release_notes/3.8.0.txt
257
257
  - doc/release_notes/3.80.0.txt
258
+ - doc/release_notes/3.81.0.txt
258
259
  - doc/release_notes/3.9.0.txt
259
260
  files:
260
261
  - CHANGELOG
@@ -342,6 +343,7 @@ files:
342
343
  - doc/release_notes/3.79.0.txt
343
344
  - doc/release_notes/3.8.0.txt
344
345
  - doc/release_notes/3.80.0.txt
346
+ - doc/release_notes/3.81.0.txt
345
347
  - doc/release_notes/3.9.0.txt
346
348
  - lib/roda.rb
347
349
  - lib/roda/cache.rb