roda 3.73.0 → 3.75.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: 7a47f703af806a15f523b99b38d084520bada92f23196374d6d9781d5953faa8
4
- data.tar.gz: 4612153820b89e6dbcfa2370c04269666c49277d8f11256869f6c1f0bb0b571a
3
+ metadata.gz: 4ebdbc5b5707ba21044b5f4c83445ff8fca6a3925488c72a5176cc662c2ad15b
4
+ data.tar.gz: ac528e50bfe1e778b5b4d32d16d12e117e87dc55b2f7cad1170b682e2f979586
5
5
  SHA512:
6
- metadata.gz: bdc42cdc9540750195327dac290e3f0bb08c3ed0100b610441b644c85849e7e9f9f974013cea041cdf640f590e2027996d68b62eea9c31d41bd42a57df6530bb
7
- data.tar.gz: 3ab05db704cf45803ad706e78b558ea7798d8d9782a06c7dec79814a4d862582249e5554946c59fff88e1f1d2d360e242268c593a8c9c95fe87b5489e4a4a44c
6
+ metadata.gz: b7d13975d6c7705f1d7b184f27430320e1dfd5fea96e532f119f86b4c09fdb5c7e460107033d8d099c6ef8da354a514289981163d74cdb293b89074299a57eda
7
+ data.tar.gz: d16c1b3a2edd401a73b104bf9458fcb865e441f4de649dcfcb8144eb3102abcd6abee741ecbbbf1cad3b13d8efca7260d7785b7e5a2505f29541ad001de9b1e4
data/CHANGELOG CHANGED
@@ -1,3 +1,11 @@
1
+ = 3.75.0 (2023-12-14)
2
+
3
+ * Add cookie_flags plugin, for overriding, warning, or raising for incorrect cookie flags (jeremyevans)
4
+
5
+ = 3.74.0 (2023-11-13)
6
+
7
+ * Add redirect_http_to_https plugin, helping to ensure future requests from the browser are submitted via HTTPS (jeremyevans)
8
+
1
9
  = 3.73.0 (2023-10-13)
2
10
 
3
11
  * Support :next_if_not_found option for middleware plugin (jeremyevans) (#334)
data/README.rdoc CHANGED
@@ -723,7 +723,7 @@ Note that when subclassing, Roda only does a shallow clone of the settings.
723
723
 
724
724
  If you store nested structures and plan to mutate them in subclasses,
725
725
  it is your responsibility to dup the nested structures inside +Roda.inherited+
726
- (making sure to call +super+). This should be is done so that that modifications
726
+ (making sure to call +super+). This should be is done so that modifications
727
727
  to the parent class made after subclassing do _not_ affect the subclass, and
728
728
  vice-versa.
729
729
 
@@ -851,9 +851,8 @@ should use an appropriate external middleware.
851
851
  It is possible to use other session cookie middleware such as
852
852
  <tt>Rack::Session::Cookie</tt>, but other middleware may not have the same security
853
853
  features that Roda's session support does. For example, the session cookies used by
854
- the <tt>Rack::Session::Cookie</tt> middleware are not encrypted, just signed to
855
- prevent tampering. This means you should not store any secret data in the session
856
- when using <tt>Rack::Session::Cookie</tt>.
854
+ the <tt>Rack::Session::Cookie</tt> middleware provided by Rack before Rack 3 are not
855
+ encrypted, just signed to prevent tampering.
857
856
 
858
857
  For any cookie-based sessions, make sure that the necessary secrets (+:secret+ option)
859
858
  are not disclosed to an attacker. Knowledge of the
@@ -960,17 +959,17 @@ application level using using the +default_headers+ plugin:
960
959
  Strict-Transport-Security :: Enforces SSL/TLS Connections to the application.
961
960
  X-Content-Type-Options :: Forces some browsers to respect a declared Content-Type header.
962
961
  X-Frame-Options :: Provides click-jacking protection by not allowing usage inside a frame.
963
- X-XSS-Protection :: Enables an XSS mitigation filter in some browsers.
962
+ Only include this if you want to support and protect old browsers that
963
+ do not support Content-Security-Policy.
964
964
 
965
965
  Example:
966
966
 
967
967
  class App < Roda
968
968
  plugin :default_headers,
969
969
  'Content-Type'=>'text/html',
970
- 'Strict-Transport-Security'=>'max-age=16070400;',
970
+ 'Strict-Transport-Security'=>'max-age=63072000; includeSubDomains',
971
971
  'X-Content-Type-Options'=>'nosniff',
972
- 'X-Frame-Options'=>'deny',
973
- 'X-XSS-Protection'=>'1; mode=block'
972
+ 'X-Frame-Options'=>'deny'
974
973
  end
975
974
 
976
975
  === Rendering Templates Derived From User Input
@@ -1007,25 +1006,16 @@ constants and removing them when any of the reloadable loaded files changes. It
1007
1006
  +require+ and +require_relative+ when activated (usually in the development environment). No
1008
1007
  configurations other than +reloadable_paths+ are required.
1009
1008
 
1010
- Both {rerun}[https://github.com/alexch/rerun] and
1011
- {shotgun}[https://github.com/rtomayko/shotgun] use a fork/exec approach for loading new
1012
- versions of your app. rerun is faster as it only reloads the app on changes, whereas
1013
- shotgun reloads the app on every request. Both work without any changes to application
1009
+ {rerun}[https://github.com/alexch/rerun] uses a fork/exec approach for loading new
1010
+ versions of your app. It work without any changes to application
1014
1011
  code, but may be slower as they have to reload the entire application on every change.
1015
- However, for small apps that load quickly, either may be a good approach.
1016
-
1017
- {Rack::Reloader}[https://github.com/rack/rack/blob/master/lib/rack/reloader.rb] ships
1018
- with rack and just reloads monitored files when they change, without unloading constants.
1019
- It's fast but may cause issues in cases where you remove classes, constants, or methods,
1020
- or when you are not clearing out cached data manually when files are reloaded.
1012
+ However, for small apps that load quickly, it may be a good approach.
1021
1013
 
1022
1014
  There is no one reloading solution that is the best for all applications and development
1023
1015
  approaches. Consider your needs and the tradeoffs of each of the reloading approaches,
1024
- and pick the one you think will work best.
1025
-
1026
- If you are unsure where to start, it may be best to start with rerun or shotgun
1027
- (unless you're running on JRuby or Windows), and only consider other options if rerun or
1028
- shotgun are not fast enough.
1016
+ and pick the one you think will work best. If you are unsure where to start,
1017
+ it may be best to start with Zeitwerk, and only consider other options if it does not
1018
+ work well for you.
1029
1019
 
1030
1020
  == Plugins
1031
1021
 
@@ -1144,4 +1134,3 @@ MIT
1144
1134
  == Maintainer
1145
1135
 
1146
1136
  Jeremy Evans <code@jeremyevans.net>
1147
-
data/doc/conventions.rdoc CHANGED
@@ -55,7 +55,7 @@ via <tt>irb -r ./models</tt>, without loading the Roda application.
55
55
  migrations.
56
56
 
57
57
  +spec/+ (or +test/+ should contain your specifications/tests. For a small application, it's recommended
58
- to a have a single file for your model tests, and a single file for your web/integration tests.
58
+ to have a single file for your model tests, and a single file for your web/integration tests.
59
59
 
60
60
  +Rakefile+ should contain the rake tasks for the application. The convention is that the
61
61
  default rake task will run all specs/tests related to the application. If you are using
@@ -0,0 +1,28 @@
1
+ = New Features
2
+
3
+ * A redirect_http_to_https plugin has been added, redirecting HTTP
4
+ requests to the same path on an HTTPS site. Using the routing tree,
5
+ you can control where to do the redirection, which allows you to
6
+ easily have part of your site accessible via HTTP, with sensitive
7
+ sections requiring HTTPS:
8
+
9
+ plugin :redirect_http_to_https
10
+
11
+ route do |r|
12
+ # routes available via both HTTP and HTTPS
13
+ r.redirect_http_to_https
14
+ # routes available only via HTTPS
15
+ end
16
+
17
+ If you want to redirect to HTTPS for all routes in the routing tree, you
18
+ can have r.redirect_http_to_https as the very first method call in the
19
+ routing tree. Note that in Roda it is possible to handle routing before
20
+ the normal routing tree using before hooks. The static_routing and
21
+ heartbeat plugins use this feature. If you would like to handle routes
22
+ before the normal routing tree, you can setup a before hook:
23
+
24
+ plugin :hooks
25
+
26
+ before do
27
+ request.redirect_http_to_https
28
+ end
@@ -0,0 +1,19 @@
1
+ = New Features
2
+
3
+ * A cookie_flags plugin has been added, for overriding, warning, or
4
+ raising for incorrect cookie flags. The plugin by default checks
5
+ whether the secure, httponly, and samesite=strict flags are set.
6
+ The default behavior is to add the appropriate flags if they are
7
+ not set, and change the samesite flag to strict if it is set to
8
+ something else. You can configure the flag checking behavior
9
+ via the :httponly, :same_site, and :secure options.
10
+
11
+ You can configure the action the plugin takes via the :action option.
12
+ The default action is to modify the flags, but the :action option can
13
+ be set to :raise, :warn, or :warn_and_modify to override the behavior.
14
+
15
+ The recommended way to use the plugin is to use it during testing,
16
+ and specify action: :raise, so you can catch places where cookies
17
+ are set with the wrong flags. Then you can fix those places to
18
+ use the correct flags, which is better than relying on the plugin
19
+ at runtime in production to fix incorrect flags.
@@ -0,0 +1,157 @@
1
+ # frozen-string-literal: true
2
+
3
+ #
4
+ class Roda
5
+ module RodaPlugins
6
+ # The cookie_flags plugin allows users to force specific cookie flags for
7
+ # all cookies set by the application. It can also be used to warn or
8
+ # raise for unexpected cookie flags.
9
+ #
10
+ # The cookie_flags plugin deals with the following cookie flags:
11
+ #
12
+ # httponly :: Disallows access to the cookie from client-side scripts.
13
+ # samesite :: Restricts to which domains the cookie is sent.
14
+ # secure :: Instructs the browser to only transmit the cookie over HTTPS.
15
+ #
16
+ # This plugin ships in secure-by-default mode, where it enforces
17
+ # secure, httponly, samesite=strict cookies. You can disable enforcing
18
+ # specific flags using the following options:
19
+ #
20
+ # :httponly :: Set to false to not enforce httponly flag.
21
+ # :same_site :: Set to symbol or string to enforce a different samesite
22
+ # setting, or false to not enforce a specific samesite setting.
23
+ # :secure :: Set to false to not enforce secure flag.
24
+ #
25
+ # For example, to enforce secure cookies and enforce samesite=lax, but not enforce
26
+ # an httponly flag:
27
+ #
28
+ # plugin :cookie_flags, httponly: false, same_site: 'lax'
29
+ #
30
+ # In general, overriding cookie flags using this plugin should be considered a
31
+ # stop-gap solution. Instead of overriding cookie flags, it's better to fix
32
+ # whatever is setting the cookie flags incorrectly. You can use the :action
33
+ # option to modify the behavior:
34
+ #
35
+ # # Issue warnings when modifying cookie flags
36
+ # plugin :cookie_flags, action: :warn_and_modify
37
+ #
38
+ # # Issue warnings for incorrect cookie flags without modifying cookie flags
39
+ # plugin :cookie_flags, action: :warn
40
+ #
41
+ # # Raise errors for incorrect cookie flags
42
+ # plugin :cookie_flags, action: :raise
43
+ #
44
+ # The recommended way to use the plugin is to use it only during testing with
45
+ # <tt>action: :raise</tt>. Then as long as you have fully covering tests, you
46
+ # can be sure the cookies set by your application use the correct flags.
47
+ #
48
+ # Note that this plugin only affects cookies set by the application, and does not
49
+ # affect cookies set by middleware the application is using.
50
+ module CookieFlags
51
+ # :nocov:
52
+ MATCH_METH = RUBY_VERSION >= '2.4' ? :match? : :match
53
+ # :nocov:
54
+ private_constant :MATCH_METH
55
+
56
+ DEFAULTS = {:secure=>true, :httponly=>true, :same_site=>'strict', :action=>:modify}.freeze
57
+ private_constant :DEFAULTS
58
+
59
+ # Error class raised for action: :raise when incorrect cookie flags are used.
60
+ class Error < RodaError
61
+ end
62
+
63
+ def self.configure(app, opts=OPTS)
64
+ previous = app.opts[:cookie_flags] || DEFAULTS
65
+ opts = app.opts[:cookie_flags] = previous.merge(opts)
66
+
67
+ case opts[:same_site]
68
+ when String, Symbol
69
+ opts[:same_site] = opts[:same_site].to_s.downcase.freeze
70
+ opts[:same_site_string] = "; samesite=#{opts[:same_site]}".freeze
71
+ opts[:secure] = true if opts[:same_site] == 'none'
72
+ end
73
+
74
+ opts.freeze
75
+ end
76
+
77
+ module InstanceMethods
78
+ private
79
+
80
+ def _handle_cookie_flags_array(cookies)
81
+ opts = self.class.opts[:cookie_flags]
82
+ needs_secure = opts[:secure]
83
+ needs_httponly = opts[:httponly]
84
+ if needs_same_site = opts[:same_site]
85
+ same_site_string = opts[:same_site_string]
86
+ same_site_regexp = /;\s*samesite\s*=\s*(\S+)\s*(?:\z|;)/i
87
+ end
88
+ action = opts[:action]
89
+
90
+ cookies.map do |cookie|
91
+ if needs_secure
92
+ add_secure = !/;\s*secure\s*(?:\z|;)/i.send(MATCH_METH, cookie)
93
+ end
94
+
95
+ if needs_httponly
96
+ add_httponly = !/;\s*httponly\s*(?:\z|;)/i.send(MATCH_METH, cookie)
97
+ end
98
+
99
+ if needs_same_site
100
+ has_same_site = same_site_regexp.match(cookie)
101
+ unless add_same_site = !has_same_site
102
+ update_same_site = needs_same_site != has_same_site[1].downcase
103
+ end
104
+ end
105
+
106
+ next cookie unless add_secure || add_httponly || add_same_site || update_same_site
107
+
108
+ case action
109
+ when :raise, :warn, :warn_and_modify
110
+ message = "Response contains cookie with unexpected flags: #{cookie.inspect}." \
111
+ "Expecting the following cookie flags: "\
112
+ "#{'secure ' if add_secure}#{'httponly ' if add_httponly}#{same_site_string[2..-1] if add_same_site || update_same_site}"
113
+
114
+ if action == :raise
115
+ raise Error, message
116
+ else
117
+ warn(message)
118
+ next cookie if action == :warn
119
+ end
120
+ end
121
+
122
+ if update_same_site
123
+ cookie = cookie.gsub(same_site_regexp, same_site_string)
124
+ else
125
+ cookie = cookie.dup
126
+ cookie << same_site_string if add_same_site
127
+ end
128
+
129
+ cookie << '; secure' if add_secure
130
+ cookie << '; httponly' if add_httponly
131
+
132
+ cookie
133
+ end
134
+ end
135
+
136
+ if Rack.release >= '3'
137
+ def _handle_cookie_flags(cookies)
138
+ cookies = [cookies] if cookies.is_a?(String)
139
+ _handle_cookie_flags_array(cookies)
140
+ end
141
+ else
142
+ def _handle_cookie_flags(cookie_string)
143
+ _handle_cookie_flags_array(cookie_string.split("\n")).join("\n")
144
+ end
145
+ end
146
+
147
+ # Handle cookie flags in response
148
+ def _roda_after_85__cookie_flags(res)
149
+ return unless res && (headers = res[1]) && (value = headers[RodaResponseHeaders::SET_COOKIE])
150
+ headers[RodaResponseHeaders::SET_COOKIE] = _handle_cookie_flags(value)
151
+ end
152
+ end
153
+ end
154
+
155
+ register_plugin(:cookie_flags, CookieFlags)
156
+ end
157
+ end
@@ -0,0 +1,99 @@
1
+ # frozen-string-literal: true
2
+
3
+ #
4
+ class Roda
5
+ module RodaPlugins
6
+ # The redirect_http_to_https plugin exposes a +redirect_http_to_https+
7
+ # request method that redirects HTTP requests to HTTPS, helping to ensure
8
+ # that future requests by the same browser will be submitted securely.
9
+ #
10
+ # You should use this plugin if you have an application that can receive
11
+ # requests using both HTTP and HTTPS, and you want to make sure that all
12
+ # or a subset of routes are only handled for HTTPS requests.
13
+ #
14
+ # The reason this exposes a request method is so that you can choose where
15
+ # in your routing tree to do the redirection:
16
+ #
17
+ # route do |r|
18
+ # # routes available via both HTTP and HTTPS
19
+ # r.redirect_http_to_https
20
+ # # routes available only via HTTPS
21
+ # end
22
+ #
23
+ # If you want to redirect to HTTPS for all routes in the routing tree, you
24
+ # can have this as the very first method call in the routing tree. Note that
25
+ # in Roda it is possible to handle routing before the normal routing tree
26
+ # using before hooks. The static_routing and heartbeat plugins use this
27
+ # feature. If you would like to handle routes before the normal routing tree,
28
+ # you can setup a before hook:
29
+ #
30
+ # plugin :hooks
31
+ #
32
+ # before do
33
+ # request.redirect_http_to_https
34
+ # end
35
+ module RedirectHttpToHttps
36
+ status_map = Hash.new(307)
37
+ status_map['GET'] = status_map['HEAD'] = 301
38
+ status_map.freeze
39
+ DEFAULTS = {:status_map => status_map}.freeze
40
+ private_constant :DEFAULTS
41
+
42
+ # Configures redirection from HTTP to HTTPS. Available options:
43
+ #
44
+ # :body :: The body used in the redirect. If not set, uses an empty body.
45
+ # :headers :: Any additional headers used in the redirect response. By default,
46
+ # no additional headers are set, the only header used is the Location header.
47
+ # :host :: The host to redirect to. If not set, redirects to the same host as the HTTP
48
+ # requested to. It is highly recommended that you set this if requests with
49
+ # arbitrary Host headers can be submitted to the application.
50
+ # :port :: The port to use in the redirect. By default, will not set an explicit port,
51
+ # so that it will implicitly use the HTTPS default port of 443.
52
+ # :status_map :: A hash mapping request methods to response status codes. By default,
53
+ # uses a hash that redirects GET and HEAD requests with a 301 status,
54
+ # and other request methods with a 307 status.
55
+ def self.configure(app, opts=OPTS)
56
+ previous = app.opts[:redirect_http_to_https] || DEFAULTS
57
+ opts = app.opts[:redirect_http_to_https] = previous.merge(opts)
58
+ opts[:port_string] = opts[:port] ? ":#{opts[:port]}".freeze : "".freeze
59
+ opts[:prefix] = opts[:host] ? "https://#{opts[:host]}#{opts[:port_string]}".freeze : nil
60
+ opts.freeze
61
+ end
62
+
63
+ module RequestMethods
64
+ # Redirect HTTP requests to HTTPS. While this doesn't secure the
65
+ # current request, it makes it more likely that the browser will submit
66
+ # future requests securely via HTTPS.
67
+ def redirect_http_to_https
68
+ return if ssl?
69
+
70
+ opts = roda_class.opts[:redirect_http_to_https]
71
+
72
+ res = response
73
+
74
+ if body = opts[:body]
75
+ res.write(body)
76
+ end
77
+
78
+ if headers = opts[:headers]
79
+ res.headers.merge!(headers)
80
+ end
81
+
82
+ path = if prefix = opts[:prefix]
83
+ prefix + fullpath
84
+ else
85
+ "https://#{host}#{opts[:port_string]}#{fullpath}"
86
+ end
87
+
88
+ unless status = opts[:status_map][@env['REQUEST_METHOD']]
89
+ raise RodaError, "redirect_http_to_https :status_map provided does not support #{@env['REQUEST_METHOD']}"
90
+ end
91
+
92
+ redirect(path, status)
93
+ end
94
+ end
95
+ end
96
+
97
+ register_plugin(:redirect_http_to_https, RedirectHttpToHttps)
98
+ end
99
+ end
@@ -22,9 +22,11 @@ class Roda
22
22
  # and request path even if they have access to a token that is not
23
23
  # specific to request method and request path. To get this security
24
24
  # benefit, you must ensure an attacker does not have access to the
25
- # session. Rack::Session::Cookie uses signed sessions, not encrypted
25
+ # session. Rack::Session::Cookie versions shipped with Rack before
26
+ # Rack 3 use signed sessions, not encrypted
26
27
  # sessions, so if the attacker has the ability to read cookie data
27
- # and you are using Rack::Session::Cookie, it will still be possible
28
+ # and you are using one of those Rack::Session::Cookie versions,
29
+ # it will still be possible
28
30
  # for an attacker to generate valid CSRF tokens specific to arbitrary
29
31
  # request method and request path. Roda's session plugin uses
30
32
  # encrypted sessions and therefore is safe even if the attacker can
@@ -40,7 +40,8 @@ class Roda
40
40
  #
41
41
  # Session secrets can be rotated. See options below.
42
42
  #
43
- # The sessions plugin can transparently upgrade sessions from Rack::Session::Cookie
43
+ # The sessions plugin can transparently upgrade sessions from versions of Rack::Session::Cookie
44
+ # shipped with Rack before Rack 3,
44
45
  # if the default Rack::Session::Cookie coder and HMAC are used, see options below.
45
46
  # It is recommended to only enable transparent upgrades for a brief transition period,
46
47
  # and remove support for them once old sessions have converted or timed out.
data/lib/roda/response.rb CHANGED
@@ -10,19 +10,15 @@ class Roda
10
10
  # headers used internally by Roda can be lower case on Rack 3, so that it is
11
11
  # possible to use a plain hash of response headers instead of using Rack::Headers.
12
12
  module RodaResponseHeaders
13
- headers = %w'Allow Cache-Control Content-Disposition Content-Encoding Content-Length
14
- Content-Security-Policy Content-Security-Policy-Report-Only Content-Type
15
- ETag Expires Last-Modified Link Location Set-Cookie Transfer-Encoding Vary'.freeze.each(&:freeze)
13
+ downcase = defined?(Rack::Headers) && Rack::Headers.is_a?(Class)
16
14
 
17
- if defined?(Rack::Headers) && Rack::Headers.is_a?(Class)
18
- headers.each do |mixed_case|
19
- const_set(mixed_case.gsub('-', '_').upcase!.to_sym, mixed_case.downcase.freeze)
20
- end
21
- else
22
- headers.each do |mixed_case|
23
- const_set(mixed_case.gsub('-', '_').upcase!.to_sym, mixed_case.freeze)
15
+ %w'Allow Cache-Control Content-Disposition Content-Encoding Content-Length
16
+ Content-Security-Policy Content-Security-Policy-Report-Only Content-Type
17
+ ETag Expires Last-Modified Link Location Set-Cookie Transfer-Encoding Vary'.
18
+ each do |value|
19
+ value = value.downcase if downcase
20
+ const_set(value.gsub('-', '_').upcase!.to_sym, value.freeze)
24
21
  end
25
- end
26
22
  end
27
23
 
28
24
  # Base class used for Roda responses. The instance methods for this
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 = 73
7
+ RodaMinorVersion = 75
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.73.0
4
+ version: 3.75.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-10-13 00:00:00.000000000 Z
11
+ date: 2023-12-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -247,6 +247,8 @@ extra_rdoc_files:
247
247
  - doc/release_notes/3.71.0.txt
248
248
  - doc/release_notes/3.72.0.txt
249
249
  - doc/release_notes/3.73.0.txt
250
+ - doc/release_notes/3.74.0.txt
251
+ - doc/release_notes/3.75.0.txt
250
252
  - doc/release_notes/3.8.0.txt
251
253
  - doc/release_notes/3.9.0.txt
252
254
  files:
@@ -327,6 +329,8 @@ files:
327
329
  - doc/release_notes/3.71.0.txt
328
330
  - doc/release_notes/3.72.0.txt
329
331
  - doc/release_notes/3.73.0.txt
332
+ - doc/release_notes/3.74.0.txt
333
+ - doc/release_notes/3.75.0.txt
330
334
  - doc/release_notes/3.8.0.txt
331
335
  - doc/release_notes/3.9.0.txt
332
336
  - lib/roda.rb
@@ -355,6 +359,7 @@ files:
355
359
  - lib/roda/plugins/common_logger.rb
356
360
  - lib/roda/plugins/content_for.rb
357
361
  - lib/roda/plugins/content_security_policy.rb
362
+ - lib/roda/plugins/cookie_flags.rb
358
363
  - lib/roda/plugins/cookies.rb
359
364
  - lib/roda/plugins/csrf.rb
360
365
  - lib/roda/plugins/custom_block_results.rb
@@ -428,6 +433,7 @@ files:
428
433
  - lib/roda/plugins/public.rb
429
434
  - lib/roda/plugins/r.rb
430
435
  - lib/roda/plugins/recheck_precompiled_assets.rb
436
+ - lib/roda/plugins/redirect_http_to_https.rb
431
437
  - lib/roda/plugins/relative_path.rb
432
438
  - lib/roda/plugins/render.rb
433
439
  - lib/roda/plugins/render_coverage.rb