roda 3.73.0 → 3.75.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 +8 -0
- data/README.rdoc +13 -24
- data/doc/conventions.rdoc +1 -1
- data/doc/release_notes/3.74.0.txt +28 -0
- data/doc/release_notes/3.75.0.txt +19 -0
- data/lib/roda/plugins/cookie_flags.rb +157 -0
- data/lib/roda/plugins/redirect_http_to_https.rb +99 -0
- data/lib/roda/plugins/route_csrf.rb +4 -2
- data/lib/roda/plugins/sessions.rb +2 -1
- data/lib/roda/response.rb +7 -11
- data/lib/roda/version.rb +1 -1
- 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: 4ebdbc5b5707ba21044b5f4c83445ff8fca6a3925488c72a5176cc662c2ad15b
|
|
4
|
+
data.tar.gz: ac528e50bfe1e778b5b4d32d16d12e117e87dc55b2f7cad1170b682e2f979586
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
|
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
|
|
855
|
-
|
|
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
|
-
|
|
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=
|
|
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
|
-
|
|
1011
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
|
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
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
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.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-
|
|
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
|