roda 3.109.0 → 3.110.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/lib/roda/cache.rb +0 -2
- data/lib/roda/opts.rb +1 -1
- data/lib/roda/plugins/_symbol_class_matchers.rb +2 -4
- data/lib/roda/plugins/additional_view_directories.rb +2 -2
- data/lib/roda/plugins/assets.rb +173 -142
- data/lib/roda/plugins/assets_preloading.rb +26 -10
- data/lib/roda/plugins/backtracking_array.rb +2 -2
- data/lib/roda/plugins/branch_locals.rb +4 -4
- data/lib/roda/plugins/break.rb +2 -2
- data/lib/roda/plugins/caching.rb +27 -17
- data/lib/roda/plugins/capture_erb.rb +15 -12
- data/lib/roda/plugins/chunked.rb +32 -30
- data/lib/roda/plugins/class_level_routing.rb +5 -2
- data/lib/roda/plugins/class_matchers.rb +11 -6
- data/lib/roda/plugins/common_logger.rb +21 -3
- data/lib/roda/plugins/conditional_sessions.rb +3 -3
- data/lib/roda/plugins/content_for.rb +7 -6
- data/lib/roda/plugins/content_security_policy.rb +11 -12
- data/lib/roda/plugins/cookie_flags.rb +12 -6
- data/lib/roda/plugins/cookies.rb +7 -5
- data/lib/roda/plugins/csrf.rb +2 -1
- data/lib/roda/plugins/custom_block_results.rb +6 -7
- data/lib/roda/plugins/default_headers.rb +2 -2
- data/lib/roda/plugins/delay_build.rb +1 -1
- data/lib/roda/plugins/delegate.rb +7 -6
- data/lib/roda/plugins/direct_call.rb +5 -1
- data/lib/roda/plugins/disallow_file_uploads.rb +2 -3
- data/lib/roda/plugins/drop_body.rb +3 -6
- data/lib/roda/plugins/each_part.rb +4 -6
- data/lib/roda/plugins/early_hints.rb +4 -4
- data/lib/roda/plugins/empty_root.rb +5 -5
- data/lib/roda/plugins/environments.rb +8 -8
- data/lib/roda/plugins/erb_h.rb +4 -4
- data/lib/roda/plugins/error_email.rb +16 -17
- data/lib/roda/plugins/error_handler.rb +24 -32
- data/lib/roda/plugins/error_mail.rb +26 -15
- data/lib/roda/plugins/exception_page.rb +41 -35
- data/lib/roda/plugins/filter_common_logger.rb +6 -4
- data/lib/roda/plugins/flash.rb +16 -13
- data/lib/roda/plugins/freeze_request_response.rb +24 -0
- data/lib/roda/plugins/hash_routes.rb +1 -1
- data/lib/roda/plugins/permissions_policy.rb +14 -16
- data/lib/roda/plugins/public.rb +11 -0
- data/lib/roda/plugins/recheck_precompiled_assets.rb +30 -8
- data/lib/roda/plugins/render.rb +3 -0
- data/lib/roda/plugins/render_locals.rb +1 -1
- data/lib/roda/plugins/sessions.rb +158 -137
- data/lib/roda/plugins/symbol_matchers.rb +8 -5
- data/lib/roda/plugins/unescape_path.rb +22 -4
- data/lib/roda/plugins.rb +24 -0
- data/lib/roda/request.rb +8 -7
- data/lib/roda/response.rb +9 -7
- data/lib/roda/version.rb +1 -1
- data/lib/roda.rb +12 -9
- metadata +2 -1
|
@@ -41,7 +41,7 @@ class Roda
|
|
|
41
41
|
# end
|
|
42
42
|
#
|
|
43
43
|
# The following methods are available for configuring the content security policy,
|
|
44
|
-
# which specify the setting (substituting _ with
|
|
44
|
+
# which specify the setting (substituting +_+ with +-+):
|
|
45
45
|
#
|
|
46
46
|
# * base_uri
|
|
47
47
|
# * child_src
|
|
@@ -92,7 +92,7 @@ class Roda
|
|
|
92
92
|
# content_security_policy.get_script_src
|
|
93
93
|
# # => [:self, :unsafe_eval, 'example.com', [:nonce, 'foobarbaz']]
|
|
94
94
|
#
|
|
95
|
-
# The clear method can be used to remove all settings from the policy. Empty policies
|
|
95
|
+
# The +clear+ method can be used to remove all settings from the policy. Empty policies
|
|
96
96
|
# do not set any headers. You can use +response.skip_content_security_policy!+ to skip
|
|
97
97
|
# setting a policy. This is faster than calling +content_security_policy.clear+, since
|
|
98
98
|
# it does not duplicate the default policy.
|
|
@@ -115,7 +115,7 @@ class Roda
|
|
|
115
115
|
|
|
116
116
|
# Represents a content security policy.
|
|
117
117
|
class Policy
|
|
118
|
-
'
|
|
118
|
+
%w'
|
|
119
119
|
base-uri
|
|
120
120
|
child-src
|
|
121
121
|
connect-src
|
|
@@ -136,7 +136,7 @@ class Roda
|
|
|
136
136
|
script-src
|
|
137
137
|
style-src
|
|
138
138
|
worker-src
|
|
139
|
-
'.
|
|
139
|
+
'.each(&:freeze).each do |setting|
|
|
140
140
|
meth = setting.tr('-', '_').freeze
|
|
141
141
|
|
|
142
142
|
# Setting method name sets the setting value, or removes it if no args are given.
|
|
@@ -153,9 +153,12 @@ class Roda
|
|
|
153
153
|
# are given.
|
|
154
154
|
define_method("add_#{meth}") do |*args|
|
|
155
155
|
unless args.empty?
|
|
156
|
-
@opts[setting]
|
|
157
|
-
|
|
158
|
-
|
|
156
|
+
if @opts[setting]
|
|
157
|
+
@opts[setting] += args
|
|
158
|
+
@opts[setting].freeze
|
|
159
|
+
else
|
|
160
|
+
@opts[setting] = args.freeze
|
|
161
|
+
end
|
|
159
162
|
end
|
|
160
163
|
nil
|
|
161
164
|
end
|
|
@@ -187,16 +190,13 @@ class Roda
|
|
|
187
190
|
end
|
|
188
191
|
end
|
|
189
192
|
|
|
190
|
-
def initialize
|
|
191
|
-
clear
|
|
192
|
-
end
|
|
193
|
-
|
|
194
193
|
# Clear all settings, useful to remove any inherited settings.
|
|
195
194
|
def clear
|
|
196
195
|
@opts = {}
|
|
197
196
|
@report_only = nil
|
|
198
197
|
@header_value = nil
|
|
199
198
|
end
|
|
199
|
+
alias initialize clear
|
|
200
200
|
|
|
201
201
|
# Do not allow future modifications to any settings.
|
|
202
202
|
def freeze
|
|
@@ -276,7 +276,6 @@ class Roda
|
|
|
276
276
|
end
|
|
277
277
|
end
|
|
278
278
|
|
|
279
|
-
|
|
280
279
|
# Yield the current Content Security Policy to the block.
|
|
281
280
|
def self.configure(app)
|
|
282
281
|
policy = app.opts[:content_security_policy] = if policy = app.opts[:content_security_policy]
|
|
@@ -60,7 +60,11 @@ class Roda
|
|
|
60
60
|
class Error < RodaError
|
|
61
61
|
end
|
|
62
62
|
|
|
63
|
+
Config = Struct.new(*DEFAULTS.keys, :same_site_string)
|
|
64
|
+
private_constant :Config
|
|
65
|
+
|
|
63
66
|
def self.configure(app, opts=OPTS)
|
|
67
|
+
RodaPlugins.check_supported_opts("the cookie_flags plugin", opts, DEFAULTS.keys)
|
|
64
68
|
previous = app.cookie_flags || DEFAULTS
|
|
65
69
|
opts = app.opts[:cookie_flags] = previous.merge(opts)
|
|
66
70
|
|
|
@@ -72,24 +76,26 @@ class Roda
|
|
|
72
76
|
end
|
|
73
77
|
|
|
74
78
|
opts.freeze
|
|
79
|
+
app.opts[:cookie_flags_config] = Config.new(*opts.values_at(*Config.members)).freeze
|
|
75
80
|
end
|
|
76
81
|
|
|
77
82
|
module ClassMethods
|
|
78
83
|
RodaPlugins.opt_attr_reader(self, :cookie_flags)
|
|
84
|
+
RodaPlugins.opt_attr_reader(self, :cookie_flags_config)
|
|
79
85
|
end
|
|
80
86
|
|
|
81
87
|
module InstanceMethods
|
|
82
88
|
private
|
|
83
89
|
|
|
84
90
|
def _handle_cookie_flags_array(cookies)
|
|
85
|
-
opts = self.class.
|
|
86
|
-
needs_secure = opts
|
|
87
|
-
needs_httponly = opts
|
|
88
|
-
if needs_same_site = opts
|
|
89
|
-
same_site_string = opts
|
|
91
|
+
opts = self.class.cookie_flags_config
|
|
92
|
+
needs_secure = opts.secure
|
|
93
|
+
needs_httponly = opts.httponly
|
|
94
|
+
if needs_same_site = opts.same_site
|
|
95
|
+
same_site_string = opts.same_site_string
|
|
90
96
|
same_site_regexp = /;\s*samesite\s*=\s*(\S+)\s*(?:\z|;)/i
|
|
91
97
|
end
|
|
92
|
-
action = opts
|
|
98
|
+
action = opts.action
|
|
93
99
|
|
|
94
100
|
cookies.map do |cookie|
|
|
95
101
|
if needs_secure
|
data/lib/roda/plugins/cookies.rb
CHANGED
|
@@ -19,8 +19,8 @@ class Roda
|
|
|
19
19
|
# plugin :cookies, domain: 'example.com', path: '/api'
|
|
20
20
|
module Cookies
|
|
21
21
|
# Allow setting default cookie options when loading the cookies plugin.
|
|
22
|
-
def self.configure(app, opts=
|
|
23
|
-
app.opts[:cookies_opts] = (app.cookies_opts||
|
|
22
|
+
def self.configure(app, opts=OPTS)
|
|
23
|
+
app.opts[:cookies_opts] = (app.cookies_opts||OPTS).merge(opts).freeze
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
module ClassMethods
|
|
@@ -28,15 +28,17 @@ class Roda
|
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
module ResponseMethods
|
|
31
|
-
# Modify the headers to include a Set-Cookie value that
|
|
31
|
+
# Modify the headers to include a <tt>Set-Cookie</tt> value that
|
|
32
32
|
# deletes the cookie. A value hash can be provided to
|
|
33
33
|
# override the default one used to delete the cookie.
|
|
34
34
|
# Example:
|
|
35
35
|
#
|
|
36
36
|
# response.delete_cookie('foo')
|
|
37
37
|
# response.delete_cookie('foo', domain: 'example.org')
|
|
38
|
-
def delete_cookie(key, value =
|
|
39
|
-
|
|
38
|
+
def delete_cookie(key, value = OPTS)
|
|
39
|
+
opts = roda_class.cookies_opts
|
|
40
|
+
value = value.empty? ? opts : opts.merge(value)
|
|
41
|
+
::Rack::Utils.delete_cookie_header!(@headers, key, value)
|
|
40
42
|
end
|
|
41
43
|
|
|
42
44
|
# Set the cookie with the given key in the headers.
|
data/lib/roda/plugins/csrf.rb
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
# frozen-string-literal: true
|
|
2
2
|
|
|
3
|
-
# RODA4: Remove plugin
|
|
4
3
|
|
|
5
4
|
require 'rack/csrf'
|
|
6
5
|
|
|
7
6
|
class Roda
|
|
8
7
|
module RodaPlugins
|
|
8
|
+
warn("The csrf plugin is deprecated and will be removed in Roda 4. Switch to the route_csrf or sec_fetch_site_csrf plugin, or use the Rack::Csrf middleware directly.", uplevel: 1)
|
|
9
|
+
|
|
9
10
|
# This plugin is no longer recommended for use, it exists only for
|
|
10
11
|
# backwards compatibility. Consider using the route_csrf plugin
|
|
11
12
|
# instead, as that provides stronger CSRF protection.
|
|
@@ -5,12 +5,11 @@ class Roda
|
|
|
5
5
|
module RodaPlugins
|
|
6
6
|
# The custom_block_results plugin allows you to specify handling
|
|
7
7
|
# for different block results. By default, Roda only supports
|
|
8
|
-
# nil
|
|
8
|
+
# +nil+, +false+, and string block results, but using this plugin,
|
|
9
9
|
# you can support other block results.
|
|
10
10
|
#
|
|
11
|
-
# For example, if you wanted to support
|
|
12
|
-
#
|
|
13
|
-
# you could do:
|
|
11
|
+
# For example, if you wanted to support Integer block results, and
|
|
12
|
+
# have the integer set the response status code, you could do:
|
|
14
13
|
#
|
|
15
14
|
# plugin :custom_block_results
|
|
16
15
|
#
|
|
@@ -23,12 +22,12 @@ class Roda
|
|
|
23
22
|
# end
|
|
24
23
|
#
|
|
25
24
|
# The expected use case for this is to customize behavior by
|
|
26
|
-
# class, but matching uses
|
|
27
|
-
# objects that respond to
|
|
25
|
+
# class, but matching uses <tt>===</tt>, so it is possible to use non-class
|
|
26
|
+
# objects that respond to <tt>===</tt> appropriately.
|
|
28
27
|
#
|
|
29
28
|
# Note that custom block result handling only occurs if the types
|
|
30
29
|
# are not handled by Roda itself. You cannot use this to modify
|
|
31
|
-
# the handling of nil
|
|
30
|
+
# the handling of +nil+, +false+, or string results. Additionally,
|
|
32
31
|
# if the response body has already been written to before the the
|
|
33
32
|
# route block exits, then the result of the block is ignored,
|
|
34
33
|
# and the related +handle_block_result+ block will not be called
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
class Roda
|
|
5
5
|
module RodaPlugins
|
|
6
6
|
# The default_headers plugin accepts a hash of headers,
|
|
7
|
-
# and overrides the default_headers method in the
|
|
7
|
+
# and overrides the +default_headers+ method in the
|
|
8
8
|
# response class to be a copy of the headers.
|
|
9
9
|
#
|
|
10
10
|
# Note that when using this module, you should not
|
|
@@ -22,7 +22,7 @@ class Roda
|
|
|
22
22
|
# plugin :default_headers, 'Bar'=>'baz'
|
|
23
23
|
module DefaultHeaders
|
|
24
24
|
# Merge the given headers into the existing default headers, if any.
|
|
25
|
-
def self.configure(app, headers=
|
|
25
|
+
def self.configure(app, headers=OPTS)
|
|
26
26
|
app.opts[:default_headers] = (app.default_headers || app::RodaResponse::DEFAULT_HEADERS).merge(headers).freeze
|
|
27
27
|
end
|
|
28
28
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
#
|
|
4
4
|
class Roda
|
|
5
5
|
module RodaPlugins
|
|
6
|
-
warn("The delay_build plugin no longer has an effect. It will be removed in Roda 4.")
|
|
6
|
+
warn("The delay_build plugin no longer has an effect. It will be removed in Roda 4.", uplevel: 1)
|
|
7
7
|
|
|
8
8
|
module DelayBuild
|
|
9
9
|
module ClassMethods
|
|
@@ -5,10 +5,10 @@ class Roda
|
|
|
5
5
|
module RodaPlugins
|
|
6
6
|
# The delegate plugin allows you to easily setup instance methods in
|
|
7
7
|
# the scope of the route block that call methods on the related
|
|
8
|
-
# request, response, or class which may offer a simpler API in some cases.
|
|
8
|
+
# request, response, or class, which may offer a simpler API in some cases.
|
|
9
9
|
# Roda doesn't automatically setup such delegate methods because
|
|
10
|
-
# it pollutes the application's method namespace,
|
|
11
|
-
#
|
|
10
|
+
# it pollutes the application's method namespace, and doing so should be
|
|
11
|
+
# the user's choice.
|
|
12
12
|
#
|
|
13
13
|
# Here's an example based on the README's initial example, using the
|
|
14
14
|
# request_delegate method to simplify the DSL:
|
|
@@ -49,26 +49,27 @@ class Roda
|
|
|
49
49
|
# end
|
|
50
50
|
module Delegate
|
|
51
51
|
module ClassMethods
|
|
52
|
-
# Delegate the given methods to the class
|
|
52
|
+
# Delegate the given instance methods to the class
|
|
53
53
|
def class_delegate(*meths)
|
|
54
54
|
meths.each do |meth|
|
|
55
55
|
define_method(meth){|*a, &block| self.class.public_send(meth, *a, &block)}
|
|
56
56
|
end
|
|
57
57
|
end
|
|
58
58
|
|
|
59
|
-
# Delegate the given methods to the request
|
|
59
|
+
# Delegate the given instance methods to the request
|
|
60
60
|
def request_delegate(*meths)
|
|
61
61
|
meths.each do |meth|
|
|
62
62
|
define_method(meth){|*a, &block| @_request.public_send(meth, *a, &block)}
|
|
63
63
|
end
|
|
64
64
|
end
|
|
65
65
|
|
|
66
|
-
# Delegate the given methods to the response
|
|
66
|
+
# Delegate the given instance methods to the response
|
|
67
67
|
def response_delegate(*meths)
|
|
68
68
|
meths.each do |meth|
|
|
69
69
|
define_method(meth){|*a, &block| @_response.public_send(meth, *a, &block)}
|
|
70
70
|
end
|
|
71
71
|
end
|
|
72
|
+
# RODA4: Switch the above calls to ...
|
|
72
73
|
end
|
|
73
74
|
end
|
|
74
75
|
|
|
@@ -7,6 +7,11 @@ class Roda
|
|
|
7
7
|
# (app.call will still call the middleware).
|
|
8
8
|
# This can be used as an optimization, as the Roda class itself can be used
|
|
9
9
|
# as the callable, which is faster than using a lambda.
|
|
10
|
+
#
|
|
11
|
+
# This plugin is used automatically by Roda when freezing an app, if Roda
|
|
12
|
+
# determines that doing so is safe (where there is no middleware). However,
|
|
13
|
+
# it can be used manually for unfrozen apps, or in cases where middleware
|
|
14
|
+
# is used.
|
|
10
15
|
module DirectCall
|
|
11
16
|
def self.configure(app)
|
|
12
17
|
app.send(:build_rack_app)
|
|
@@ -35,4 +40,3 @@ class Roda
|
|
|
35
40
|
register_plugin(:direct_call, DirectCall)
|
|
36
41
|
end
|
|
37
42
|
end
|
|
38
|
-
|
|
@@ -12,7 +12,7 @@ class Roda
|
|
|
12
12
|
#
|
|
13
13
|
# plugin :disallow_file_uploads
|
|
14
14
|
#
|
|
15
|
-
# This plugin is
|
|
15
|
+
# This plugin is supported on Rack 1.6+. This plugin does not technically
|
|
16
16
|
# block users from uploading files, it only blocks the parsing of request bodies containing
|
|
17
17
|
# multipart file uploads. So if you do not call +r.POST+ (or something that calls it such as
|
|
18
18
|
# +r.params+), then Roda will not attempt to parse the request body, and an exception will not
|
|
@@ -24,7 +24,7 @@ class Roda
|
|
|
24
24
|
NO_TEMPFILE = lambda{|_,_| raise Error, "Support for uploading files has been disabled"}
|
|
25
25
|
|
|
26
26
|
module RequestMethods
|
|
27
|
-
#
|
|
27
|
+
# Raise an error if there is an attempt to use a tempfile.
|
|
28
28
|
def initialize(_, env)
|
|
29
29
|
env['rack.multipart.tempfile_factory'] = NO_TEMPFILE
|
|
30
30
|
super
|
|
@@ -35,4 +35,3 @@ class Roda
|
|
|
35
35
|
register_plugin(:disallow_file_uploads, DisallowFileUploads)
|
|
36
36
|
end
|
|
37
37
|
end
|
|
38
|
-
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
class Roda
|
|
5
5
|
module RodaPlugins
|
|
6
6
|
# The drop_body plugin automatically drops the body and
|
|
7
|
-
# Content-Type
|
|
7
|
+
# +Content-Type+/+Content-Length+ headers from the response if
|
|
8
8
|
# the response status indicates that the response should
|
|
9
|
-
# not include a body (response statuses 100,
|
|
9
|
+
# not include a body (response statuses 100-199, 204,
|
|
10
10
|
# and 304). For response status 205, the body and Content-Type
|
|
11
11
|
# headers are dropped, but the Content-length header is set to
|
|
12
12
|
# '0' instead of being dropped.
|
|
@@ -15,16 +15,13 @@ class Roda
|
|
|
15
15
|
DROP_BODY_STATUSES = [100, 101, 102, 204, 205, 304].freeze
|
|
16
16
|
RodaPlugins.deprecate_constant(self, :DROP_BODY_STATUSES)
|
|
17
17
|
|
|
18
|
-
DROP_BODY_RANGE = 100..199
|
|
19
|
-
private_constant :DROP_BODY_RANGE
|
|
20
|
-
|
|
21
18
|
# If the response status indicates a body should not be
|
|
22
19
|
# returned, use an empty body and remove the Content-Length
|
|
23
20
|
# and Content-Type headers.
|
|
24
21
|
def finish
|
|
25
22
|
r = super
|
|
26
23
|
case r[0]
|
|
27
|
-
when
|
|
24
|
+
when 100..199, 204, 304
|
|
28
25
|
r[2] = EMPTY_ARRAY
|
|
29
26
|
h = r[1]
|
|
30
27
|
h.delete(RodaResponseHeaders::CONTENT_LENGTH)
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
#
|
|
4
4
|
class Roda
|
|
5
5
|
module RodaPlugins
|
|
6
|
-
# The each_part plugin adds an each_part method, which is
|
|
7
|
-
# render_each
|
|
6
|
+
# The each_part plugin adds an +each_part+ method, which is similar to
|
|
7
|
+
# +render_each+, but treats all keywords as locals.
|
|
8
8
|
#
|
|
9
9
|
# # Can replace this:
|
|
10
10
|
# render_each(enum, :template, locals: {foo: 'bar'})
|
|
@@ -15,7 +15,7 @@ class Roda
|
|
|
15
15
|
# On Ruby 2.7+, the part method takes a keyword splat, so you
|
|
16
16
|
# must pass keywords and not a positional hash for the locals.
|
|
17
17
|
#
|
|
18
|
-
# If you are using the
|
|
18
|
+
# If you are using the +:assume_fixed_locals+ render plugin option,
|
|
19
19
|
# template caching is enabled, you are using Ruby 3+, and you
|
|
20
20
|
# are freezing your Roda application, in addition to providing a
|
|
21
21
|
# simpler API, this also provides a performance improvement.
|
|
@@ -51,9 +51,7 @@ class Roda
|
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
module AssumeFixedLocalsInstanceMethods
|
|
54
|
-
# simplecov:disable
|
|
55
|
-
if RUBY_VERSION >= '3.0'
|
|
56
|
-
# simplecov:enable
|
|
54
|
+
if RUBY_VERSION >= '3.0' # simplecov:disable
|
|
57
55
|
def each_part(enum, template, **locals, &block)
|
|
58
56
|
if optimized_method = _cached_render_each_template_method(template)
|
|
59
57
|
optimized_method = optimized_method[0]
|
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
#
|
|
4
4
|
class Roda
|
|
5
5
|
module RodaPlugins
|
|
6
|
-
# The early_hints plugin
|
|
7
|
-
# using the rack.early_hints environment variable.
|
|
6
|
+
# The early_hints plugin adds the +send_early_hints+ method for sending
|
|
7
|
+
# 103 Early Hints responses using the +rack.early_hints+ environment variable.
|
|
8
8
|
# Early hints allow clients to preload necessary files before receiving
|
|
9
9
|
# the response.
|
|
10
10
|
module EarlyHints
|
|
11
11
|
module InstanceMethods
|
|
12
|
-
# Send given hash of Early Hints using the rack.early_hints environment variable,
|
|
13
|
-
# currenly
|
|
12
|
+
# Send given hash of Early Hints using the +rack.early_hints+ environment variable,
|
|
13
|
+
# currenly supported by puma and falcon. hash given should generally have the single
|
|
14
14
|
# key 'Link', and a string or array of strings for each of the early hints.
|
|
15
15
|
def send_early_hints(hash)
|
|
16
16
|
if eh_proc = env['rack.early_hints']
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
#
|
|
4
4
|
class Roda
|
|
5
5
|
module RodaPlugins
|
|
6
|
-
# The empty_root plugin makes +r.root+ match both
|
|
7
|
-
#
|
|
8
|
-
# rack applications, where the initial PATH_INFO has been moved
|
|
9
|
-
# to SCRIPT_NAME
|
|
6
|
+
# The empty_root plugin makes +r.root+ match both +/+ and
|
|
7
|
+
# the empty string. This is mostly useful when using multiple
|
|
8
|
+
# rack applications, where the initial +PATH_INFO+ has been moved
|
|
9
|
+
# to +SCRIPT_NAME+. For example, if you have the following
|
|
10
10
|
# applications:
|
|
11
11
|
#
|
|
12
12
|
# class App1 < Roda
|
|
@@ -28,7 +28,7 @@ class Roda
|
|
|
28
28
|
# Then requests for both +/albums/+ and +/albums+ will return
|
|
29
29
|
# "root". Without this plugin loaded into App2, only requests
|
|
30
30
|
# for +/albums/+ will return "root", since by default, +r.root+
|
|
31
|
-
# matches only when the current PATH_INFO is +/+ and not when
|
|
31
|
+
# matches only when the current +PATH_INFO+ is +/+ and not when
|
|
32
32
|
# it is empty.
|
|
33
33
|
module EmptyRoot
|
|
34
34
|
module RequestMethods
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
#
|
|
4
4
|
class Roda
|
|
5
5
|
module RodaPlugins
|
|
6
|
-
# The environments plugin adds a environment class accessor to get
|
|
7
|
-
# the environment for the application,
|
|
8
|
-
# to check for the current environment (development
|
|
9
|
-
# production
|
|
6
|
+
# The environments plugin adds a +environment+ class accessor to get
|
|
7
|
+
# the environment for the application, predicate class methods
|
|
8
|
+
# to check for the current environment (+development?+, +test?+ and
|
|
9
|
+
# +production?+), and a class +configure+ method that takes environment(s)
|
|
10
10
|
# and yields to the block if the given environment(s) match the
|
|
11
11
|
# current environment.
|
|
12
12
|
#
|
|
@@ -40,8 +40,8 @@ class Roda
|
|
|
40
40
|
# end
|
|
41
41
|
# end
|
|
42
42
|
module Environments
|
|
43
|
-
# Set the environment to use for the app. Default to ENV['RACK_ENV']
|
|
44
|
-
# if no environment is given. If ENV['RACK_ENV'] is not set and
|
|
43
|
+
# Set the environment to use for the app. Default to <tt>ENV['RACK_ENV']</tt>
|
|
44
|
+
# if no environment is given. If <tt>ENV['RACK_ENV']</tt> is not set and
|
|
45
45
|
# no environment is given, assume the development environment.
|
|
46
46
|
def self.configure(app, env=ENV["RACK_ENV"])
|
|
47
47
|
app.opts[:environment] = (env || 'development').to_sym
|
|
@@ -53,13 +53,13 @@ class Roda
|
|
|
53
53
|
# If no environments are given or one of the given environments
|
|
54
54
|
# matches the current environment, yield the receiver to the block.
|
|
55
55
|
def configure(*envs)
|
|
56
|
-
if envs.empty? || envs.
|
|
56
|
+
if envs.empty? || envs.include?(environment)
|
|
57
57
|
yield self
|
|
58
58
|
end
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
# Override the environment for the application, instead of using
|
|
62
|
-
# RACK_ENV
|
|
62
|
+
# <tt>ENV['RACK_ENV']</tt>.
|
|
63
63
|
def environment=(v)
|
|
64
64
|
opts[:environment] = v
|
|
65
65
|
end
|
data/lib/roda/plugins/erb_h.rb
CHANGED
|
@@ -12,9 +12,9 @@ class Roda
|
|
|
12
12
|
#
|
|
13
13
|
# To make sure that this speeds up applications using the h
|
|
14
14
|
# plugin, this depends on the h plugin, and overrides the
|
|
15
|
-
# h method.
|
|
15
|
+
# +h+ method.
|
|
16
16
|
#
|
|
17
|
-
# The following example will return "<foo>" as the body.
|
|
17
|
+
# The following example will return <tt>"<foo>"</tt> as the body.
|
|
18
18
|
#
|
|
19
19
|
# plugin :erb_h
|
|
20
20
|
#
|
|
@@ -25,8 +25,8 @@ class Roda
|
|
|
25
25
|
# The faster performance offered by the erb_h plugin is due
|
|
26
26
|
# to erb/escape avoiding allocations if not needed (returning the
|
|
27
27
|
# input object if no escaping is needed). That behavior change
|
|
28
|
-
# can cause problems if you mutate the result of the h method
|
|
29
|
-
# (which can mutate the input), or mutate the input of the h
|
|
28
|
+
# can cause problems if you mutate the result of the +h+ method
|
|
29
|
+
# (which can mutate the input), or mutate the input of the +h+
|
|
30
30
|
# method after calling it (which can mutate the result).
|
|
31
31
|
module ErbH
|
|
32
32
|
def self.load_dependencies(app)
|
|
@@ -5,8 +5,8 @@ require 'net/smtp'
|
|
|
5
5
|
class Roda
|
|
6
6
|
module RodaPlugins
|
|
7
7
|
# The error_email plugin adds an +error_email+ instance method that
|
|
8
|
-
#
|
|
9
|
-
#
|
|
8
|
+
# sends an email related to the exception. This is designed for use in
|
|
9
|
+
# combination with the error_handler plugin:
|
|
10
10
|
#
|
|
11
11
|
# plugin :error_email, to: 'to@example.com', from: 'from@example.com'
|
|
12
12
|
# plugin :error_handler do |e|
|
|
@@ -16,19 +16,19 @@ class Roda
|
|
|
16
16
|
#
|
|
17
17
|
# It is similar to the error_mail plugin, except that it uses net/smtp
|
|
18
18
|
# directly instead of using the mail library. If you are not already using the
|
|
19
|
-
# mail library in your application,
|
|
20
|
-
#
|
|
19
|
+
# mail library in your application, using error_email may be preferable over
|
|
20
|
+
# error_mail in terms of limiting the number of dependencies.
|
|
21
21
|
#
|
|
22
22
|
# Options:
|
|
23
23
|
#
|
|
24
|
-
#
|
|
25
|
-
#
|
|
26
|
-
#
|
|
27
|
-
#
|
|
28
|
-
#
|
|
29
|
-
#
|
|
30
|
-
#
|
|
31
|
-
#
|
|
24
|
+
# +:filter+ :: Callable called with the key and value for each parameter, environment
|
|
25
|
+
# variable, and session value. If it returns true, the value of the
|
|
26
|
+
# parameter is filtered in the email.
|
|
27
|
+
# +:from+ :: The From address to use in the email (required)
|
|
28
|
+
# +:headers+ :: A hash of additional headers to use in the email (default: empty hash)
|
|
29
|
+
# +:host+ :: The SMTP server to use to send the email (default: localhost)
|
|
30
|
+
# +:prefix+ :: A prefix to use in the email's subject line (default: no prefix)
|
|
31
|
+
# +:to+ :: The To address to use in the email (required)
|
|
32
32
|
#
|
|
33
33
|
# The subject of the error email shows the exception class and message.
|
|
34
34
|
# The body of the error email shows the backtrace of the error and the
|
|
@@ -111,17 +111,16 @@ END
|
|
|
111
111
|
end
|
|
112
112
|
}.freeze
|
|
113
113
|
|
|
114
|
-
# Set default opts for plugin. See ErrorEmail module RDoc for options.
|
|
115
114
|
def self.configure(app, opts=OPTS)
|
|
115
|
+
RodaPlugins.check_supported_opts("the error_email plugin", opts, [*DEFAULTS.keys, :prefix, :to, :from])
|
|
116
|
+
|
|
116
117
|
email_opts = app.opts[:error_email] ||= DEFAULTS
|
|
117
118
|
email_opts = email_opts.merge(opts)
|
|
118
|
-
email_opts[:headers] = email_opts[:headers].dup
|
|
119
|
+
email_opts[:headers] = email_opts[:headers].dup.freeze
|
|
119
120
|
unless email_opts[:to] && email_opts[:from]
|
|
120
121
|
raise RodaError, "must provide :to and :from options to error_email plugin"
|
|
121
122
|
end
|
|
122
|
-
app.opts[:error_email] = email_opts
|
|
123
|
-
app.error_email_opts[:headers].freeze
|
|
124
|
-
app.error_email_opts.freeze
|
|
123
|
+
app.opts[:error_email] = email_opts.freeze
|
|
125
124
|
end
|
|
126
125
|
|
|
127
126
|
module ClassMethods
|