roda 3.73.0 → 3.74.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: ae3f95331c6c3d69453feb96a7dbd3629a6d5f52bd9d1862edecab893d95a36f
4
+ data.tar.gz: c5457f54b2ca5a9971f93a23db10abe3b6fd16a743e2651749ec14c480c248a3
5
5
  SHA512:
6
- metadata.gz: bdc42cdc9540750195327dac290e3f0bb08c3ed0100b610441b644c85849e7e9f9f974013cea041cdf640f590e2027996d68b62eea9c31d41bd42a57df6530bb
7
- data.tar.gz: 3ab05db704cf45803ad706e78b558ea7798d8d9782a06c7dec79814a4d862582249e5554946c59fff88e1f1d2d360e242268c593a8c9c95fe87b5489e4a4a44c
6
+ metadata.gz: f314713b33ec4400e5ef8849c6a3e30f1b5956b428dea55a5bf45855fef4a965f9b417063182cc4412effa592a7d311715cf4541826781675ca26bd20f202ca3
7
+ data.tar.gz: 735cb4cf3e5480be4462d88ccb0090001e7eca27bfe7338a923f5f190730095037ff0c77e1cbe3c875b137175bc7022b8d0611ccbf8b82426cbbaec5b7802149
data/CHANGELOG CHANGED
@@ -1,3 +1,7 @@
1
+ = 3.74.0 (2023-11-13)
2
+
3
+ * Add redirect_http_to_https plugin, helping to ensure future requests from the browser are submitted via HTTPS (jeremyevans)
4
+
1
5
  = 3.73.0 (2023-10-13)
2
6
 
3
7
  * 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,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 = 74
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.74.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-11-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -247,6 +247,7 @@ 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
250
251
  - doc/release_notes/3.8.0.txt
251
252
  - doc/release_notes/3.9.0.txt
252
253
  files:
@@ -327,6 +328,7 @@ files:
327
328
  - doc/release_notes/3.71.0.txt
328
329
  - doc/release_notes/3.72.0.txt
329
330
  - doc/release_notes/3.73.0.txt
331
+ - doc/release_notes/3.74.0.txt
330
332
  - doc/release_notes/3.8.0.txt
331
333
  - doc/release_notes/3.9.0.txt
332
334
  - lib/roda.rb
@@ -428,6 +430,7 @@ files:
428
430
  - lib/roda/plugins/public.rb
429
431
  - lib/roda/plugins/r.rb
430
432
  - lib/roda/plugins/recheck_precompiled_assets.rb
433
+ - lib/roda/plugins/redirect_http_to_https.rb
431
434
  - lib/roda/plugins/relative_path.rb
432
435
  - lib/roda/plugins/render.rb
433
436
  - lib/roda/plugins/render_coverage.rb