roda 3.57.0 → 3.60.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +18 -0
- data/doc/release_notes/3.58.0.txt +16 -0
- data/doc/release_notes/3.59.0.txt +17 -0
- data/doc/release_notes/3.60.0.txt +56 -0
- data/lib/roda/plugins/additional_render_engines.rb +61 -0
- data/lib/roda/plugins/all_verbs.rb +0 -2
- data/lib/roda/plugins/assets.rb +1 -1
- data/lib/roda/plugins/delete_empty_headers.rb +3 -3
- data/lib/roda/plugins/disallow_file_uploads.rb +0 -2
- data/lib/roda/plugins/exception_page.rb +20 -4
- data/lib/roda/plugins/filter_common_logger.rb +46 -0
- data/lib/roda/plugins/heartbeat.rb +5 -10
- data/lib/roda/plugins/indifferent_params.rb +2 -8
- data/lib/roda/plugins/json_parser.rb +1 -3
- data/lib/roda/plugins/link_to.rb +83 -0
- data/lib/roda/plugins/mail_processor.rb +4 -5
- data/lib/roda/plugins/multi_public.rb +0 -4
- data/lib/roda/plugins/not_allowed.rb +0 -2
- data/lib/roda/plugins/public.rb +0 -6
- data/lib/roda/plugins/render.rb +3 -13
- data/lib/roda/plugins/render_each.rb +0 -2
- data/lib/roda/plugins/render_locals.rb +0 -2
- data/lib/roda/plugins/sinatra_helpers.rb +0 -6
- data/lib/roda/plugins/status_handler.rb +1 -3
- data/lib/roda/plugins/view_options.rb +0 -2
- data/lib/roda/request.rb +2 -6
- data/lib/roda/response.rb +0 -4
- data/lib/roda/version.rb +1 -1
- metadata +11 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 970d646c144f53a89f4f79e9d54b6929b7c10b55b1bbe9b2d5e72aea6a8eb3ae
|
4
|
+
data.tar.gz: ec2489d3d668b3abd2787a7f19c13de43c94685dce010d800296eb1194e36e11
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ccc8d09c535a2c6a92ee314ff295ca5b8756b6c942f3224acbabdc6a92de5bf242a928b296c2e410ecf0bf59470a2143ac2c80d118030db5a2f45fb0cf262a8c
|
7
|
+
data.tar.gz: 79114184b64598e3d12d3773c5e7f8d717a05268c63c479758fe3ea1c3c78ccd933531c4e7ef6fd58a6d6af03a150d6e1dde8bf0f27dcc4c0c253482336879f0
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
= 3.60.0 (2022-09-13)
|
2
|
+
|
3
|
+
* Add link_to plugin with link_to method for creating HTML links (jeremyevans)
|
4
|
+
|
5
|
+
= 3.59.0 (2022-08-12)
|
6
|
+
|
7
|
+
* Add additional_render_engines plugin, for considering multiple render engines for templates (jeremyevans)
|
8
|
+
|
9
|
+
* Fix typo in private method name in delete_empty_headers plugin (mculpt) (#279)
|
10
|
+
|
11
|
+
= 3.58.0 (2022-07-13)
|
12
|
+
|
13
|
+
* Add filter_common_logger plugin for skipping the logging of certain requests when using the common_logger plugin (jeremyevans)
|
14
|
+
|
15
|
+
* Make exception_page plugin use Exception#detailed_message on Ruby 3.2+ (jeremyevans)
|
16
|
+
|
17
|
+
* Make heartbeat plugin compatible with recent changes in the rack master branch (jeremyevans)
|
18
|
+
|
1
19
|
= 3.57.0 (2022-06-14)
|
2
20
|
|
3
21
|
* Make static_routing plugin depend on the hash_paths instead of the hash_routes plugin (jeremyevans)
|
@@ -0,0 +1,16 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* A filter_common_logger plugin has been added, allowing you to skip
|
4
|
+
logging of certain requests in the common_logger plugin. This
|
5
|
+
allows you to only log requests for certain paths, or only log
|
6
|
+
requests for certain types of responses.
|
7
|
+
|
8
|
+
= Other Improvements
|
9
|
+
|
10
|
+
* The heartbeat plugin is now compatible with recent changes in the
|
11
|
+
rack master branch (what will be rack 3).
|
12
|
+
|
13
|
+
* The exception_page plugin will now use Exception#detailed_message
|
14
|
+
on Ruby 3.2+, preserving the did_you_mean and error_highlight
|
15
|
+
information. Additionally, the display of exception messages
|
16
|
+
has been improved.
|
@@ -0,0 +1,17 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* An additional_render_engines plugin has been added, for considering
|
4
|
+
multiple render engines for templates. If the template path does not
|
5
|
+
exist for the default render engine, then each additional render
|
6
|
+
engine will be checked, returning the first path that exists:
|
7
|
+
|
8
|
+
plugin :additional_render_engines, ['haml', 'str']
|
9
|
+
|
10
|
+
This is similar to the additional_view_directories plugin added in
|
11
|
+
3.53.0. Both plugins can be used if you want to consider multiple
|
12
|
+
view directories and multiple render engines.
|
13
|
+
|
14
|
+
= Other Improvements
|
15
|
+
|
16
|
+
* A typo in a private method name in the delete_empty_headers plugin
|
17
|
+
has been fixed.
|
@@ -0,0 +1,56 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* A link_to plugin has been added with a link_to method for
|
4
|
+
creating HTML links.
|
5
|
+
|
6
|
+
The simplest usage of link_to is passing the body and the location
|
7
|
+
to link to as strings:
|
8
|
+
|
9
|
+
# Instance level
|
10
|
+
link_to("body", "/path")
|
11
|
+
# => "<a href=\"/path\">body</a>"
|
12
|
+
|
13
|
+
The link_to plugin depends on the path plugin, and allows you to
|
14
|
+
pass symbols for named paths:
|
15
|
+
|
16
|
+
# Class level
|
17
|
+
path :foo, "/path/to/too"
|
18
|
+
|
19
|
+
# Instance level
|
20
|
+
link_to("body", :foo)
|
21
|
+
# => "<a href=\"/path/to/foo\">body</a>"
|
22
|
+
|
23
|
+
It also allows you to pass instances of classes that you have
|
24
|
+
registered with the path plugin:
|
25
|
+
|
26
|
+
# Class level
|
27
|
+
A = Struct.new(:id)
|
28
|
+
path A do
|
29
|
+
"/path/to/a/#{id}"
|
30
|
+
end
|
31
|
+
|
32
|
+
# Instance level
|
33
|
+
link_to("body", A.new(1))
|
34
|
+
# => "<a href=\"/path/to/a/1\">body</a>"
|
35
|
+
|
36
|
+
To set additional HTML attributes on the tag, you can pass them as
|
37
|
+
an options hash:
|
38
|
+
|
39
|
+
link_to("body", "/path", foo: "bar")
|
40
|
+
# => "<a href=\"/path\" foo=\"bar\">body</a>"
|
41
|
+
|
42
|
+
If the body is nil, it will be set to the same as the path:
|
43
|
+
|
44
|
+
link_to(nil, "/path")
|
45
|
+
# => "<a href=\"/path\">/path</a>"
|
46
|
+
|
47
|
+
The plugin will automatically HTML escape the path and any HTML
|
48
|
+
attribute values, using the h plugin:
|
49
|
+
|
50
|
+
link_to("body", "/path?a=1&b=2", foo: '"bar"')
|
51
|
+
# => "<a href=\"/path?a=1&b=2\" foo=\""bar"\">body</a>"
|
52
|
+
|
53
|
+
= Other Improvements
|
54
|
+
|
55
|
+
* Coverage testing has been expanded to multiple rack versions, instead
|
56
|
+
of just the current rack release.
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
class Roda
|
5
|
+
module RodaPlugins
|
6
|
+
# The additional_render_engines plugin allows for specifying additional render
|
7
|
+
# engines to consider for templates. When rendering a template, it will
|
8
|
+
# first try the default template engine specified in the render plugin. If the
|
9
|
+
# template file to be rendered does not exist, it will try each additional render
|
10
|
+
# engine specified in this plugin, in order, using the path to the first
|
11
|
+
# template file that exists in the file system. If no such path is found, it
|
12
|
+
# uses the default path specified by the render plugin.
|
13
|
+
#
|
14
|
+
# Example:
|
15
|
+
#
|
16
|
+
# plugin :render # default engine is 'erb'
|
17
|
+
# plugin :additional_render_engines, ['haml', 'str']
|
18
|
+
#
|
19
|
+
# route do |r|
|
20
|
+
# # Will check the following in order, using path for first
|
21
|
+
# # template file that exists:
|
22
|
+
# # * views/t.erb
|
23
|
+
# # * views/t.haml
|
24
|
+
# # * views/t.str
|
25
|
+
# render :t
|
26
|
+
# end
|
27
|
+
module AdditionalRenderEngines
|
28
|
+
def self.load_dependencies(app, render_engines)
|
29
|
+
app.plugin :render
|
30
|
+
end
|
31
|
+
|
32
|
+
# Set the additional render engines to consider.
|
33
|
+
def self.configure(app, render_engines)
|
34
|
+
app.opts[:additional_render_engines] = render_engines.dup.freeze
|
35
|
+
end
|
36
|
+
|
37
|
+
module InstanceMethods
|
38
|
+
private
|
39
|
+
|
40
|
+
# If the template path does not exist, try looking for the template
|
41
|
+
# using each of the render engines, in order, returning
|
42
|
+
# the first path that exists. If no template path exists for the
|
43
|
+
# default any or any additional engines, return the original path.
|
44
|
+
def template_path(opts)
|
45
|
+
orig_path = super
|
46
|
+
|
47
|
+
unless File.file?(orig_path)
|
48
|
+
self.opts[:additional_render_engines].each do |engine|
|
49
|
+
path = super(opts.merge(:engine=>engine))
|
50
|
+
return path if File.file?(path)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
orig_path
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
register_plugin(:additional_render_engines, AdditionalRenderEngines)
|
60
|
+
end
|
61
|
+
end
|
@@ -34,9 +34,7 @@ class Roda
|
|
34
34
|
module AllVerbs
|
35
35
|
module RequestMethods
|
36
36
|
%w'delete head options link patch put trace unlink'.each do |verb|
|
37
|
-
# :nocov:
|
38
37
|
if ::Rack::Request.method_defined?("#{verb}?")
|
39
|
-
# :nocov:
|
40
38
|
class_eval(<<-END, __FILE__, __LINE__+1)
|
41
39
|
def #{verb}(*args, &block)
|
42
40
|
_verb(args, &block) if #{verb}?
|
data/lib/roda/plugins/assets.rb
CHANGED
@@ -147,7 +147,7 @@ class Roda
|
|
147
147
|
# If you have the yuicompressor gem installed and working, it will be used
|
148
148
|
# automatically to compress your javascript and css assets. For javascript
|
149
149
|
# assets, if yuicompressor is not available, the plugin will check for
|
150
|
-
#
|
150
|
+
# closure-compiler, uglifier, and minjs and use the first one that works.
|
151
151
|
# If no compressors are available, the assets will just be concatenated
|
152
152
|
# together and not compressed during compilation. You can use the
|
153
153
|
# :css_compressor and :js_compressor options to specify the compressor to use.
|
@@ -13,18 +13,18 @@ class Roda
|
|
13
13
|
module ResponseMethods
|
14
14
|
# Delete any empty headers when calling finish
|
15
15
|
def finish
|
16
|
-
|
16
|
+
delete_empty_headers(super)
|
17
17
|
end
|
18
18
|
|
19
19
|
# Delete any empty headers when calling finish_with_body
|
20
20
|
def finish_with_body(_)
|
21
|
-
|
21
|
+
delete_empty_headers(super)
|
22
22
|
end
|
23
23
|
|
24
24
|
private
|
25
25
|
|
26
26
|
# Delete any empty headers from response
|
27
|
-
def
|
27
|
+
def delete_empty_headers(res)
|
28
28
|
res[1].delete_if{|_, v| v.is_a?(String) && v.empty?}
|
29
29
|
res
|
30
30
|
end
|
@@ -127,7 +127,7 @@ div.context ol.context-line li span { float: right; }
|
|
127
127
|
div.commands { margin-left: 40px; }
|
128
128
|
div.commands a { color:black; text-decoration:none; }
|
129
129
|
#summary { background: #ffc; }
|
130
|
-
#summary h2 { font-weight: normal; color: #666; }
|
130
|
+
#summary h2 { font-weight: normal; color: #666; font-family: monospace; white-space: pre-wrap;}
|
131
131
|
#summary ul#quicklinks { list-style-type: none; margin-bottom: 2em; }
|
132
132
|
#summary ul#quicklinks li { float: left; padding: 0 1em; }
|
133
133
|
#summary ul#quicklinks>li+li { border-left: 1px #666 solid; }
|
@@ -196,12 +196,13 @@ END
|
|
196
196
|
# Designed to be used with the +json+ exception, which will
|
197
197
|
# automatically convert the hash to JSON format.
|
198
198
|
def exception_page(exception, opts=OPTS)
|
199
|
+
message = exception_page_exception_message(exception)
|
199
200
|
if opts[:json]
|
200
201
|
@_response['Content-Type'] = "application/json"
|
201
202
|
{
|
202
203
|
"exception"=>{
|
203
204
|
"class"=>exception.class.to_s,
|
204
|
-
"message"=>
|
205
|
+
"message"=>message,
|
205
206
|
"backtrace"=>exception.backtrace.map(&:to_s)
|
206
207
|
}
|
207
208
|
}
|
@@ -319,7 +320,7 @@ END
|
|
319
320
|
|
320
321
|
<div id="summary">
|
321
322
|
<h1>#{h exception.class} at #{h r.path}</h1>
|
322
|
-
<h2>#{h
|
323
|
+
<h2>#{h message}</h2>
|
323
324
|
<table><tr>
|
324
325
|
<th>Ruby</th>
|
325
326
|
<td>
|
@@ -394,7 +395,22 @@ END1
|
|
394
395
|
END
|
395
396
|
else
|
396
397
|
@_response['Content-Type'] = "text/plain"
|
397
|
-
"#{exception.class}: #{
|
398
|
+
"#{exception.class}: #{message}\n#{exception.backtrace.map{|l| "\t#{l}"}.join("\n")}"
|
399
|
+
end
|
400
|
+
end
|
401
|
+
|
402
|
+
private
|
403
|
+
|
404
|
+
# :nocov:
|
405
|
+
if RUBY_VERSION >= '3.2'
|
406
|
+
def exception_page_exception_message(exception)
|
407
|
+
exception.detailed_message(highlight: false).to_s
|
408
|
+
end
|
409
|
+
# :nocov:
|
410
|
+
else
|
411
|
+
# Return message to use for exception.
|
412
|
+
def exception_page_exception_message(exception)
|
413
|
+
exception.message.to_s
|
398
414
|
end
|
399
415
|
end
|
400
416
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
class Roda
|
5
|
+
module RodaPlugins
|
6
|
+
# The skip_common_logger plugin allows for skipping common_logger logging
|
7
|
+
# of some requests. You pass a block when loading the plugin, and the
|
8
|
+
# block will be called before logging each request. The block should return
|
9
|
+
# whether the request should be logged.
|
10
|
+
#
|
11
|
+
# Example:
|
12
|
+
#
|
13
|
+
# # Only log server errors
|
14
|
+
# plugin :filter_common_logger do |result|
|
15
|
+
# result[0] >= 500
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# # Don't log requests to certain paths
|
19
|
+
# plugin :filter_common_logger do |_|
|
20
|
+
# # Block is called in the same context as the route block
|
21
|
+
# !request.path.start_with?('/admin/')
|
22
|
+
# end
|
23
|
+
module FilterCommonLogger
|
24
|
+
def self.load_dependencies(app)
|
25
|
+
app.plugin :common_logger
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.configure(app, &block)
|
29
|
+
app.send(:define_method, :_common_log_request?, &block)
|
30
|
+
app.send(:private, :_common_log_request?)
|
31
|
+
app.send(:alias_method, :_common_log_request?, :_common_log_request?)
|
32
|
+
end
|
33
|
+
|
34
|
+
module InstanceMethods
|
35
|
+
private
|
36
|
+
|
37
|
+
# Log request/response information in common log format to logger.
|
38
|
+
def _roda_after_90__common_logger(result)
|
39
|
+
super if result && _common_log_request?(result)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
register_plugin(:filter_common_logger, FilterCommonLogger)
|
45
|
+
end
|
46
|
+
end
|
@@ -14,13 +14,6 @@ class Roda
|
|
14
14
|
#
|
15
15
|
# plugin :heartbeat, path: '/status'
|
16
16
|
module Heartbeat
|
17
|
-
# :nocov:
|
18
|
-
HEADER_CLASS = (defined?(Rack::Headers) && Rack::Headers.is_a?(Class)) ? Rack::Headers : Hash
|
19
|
-
# :nocov:
|
20
|
-
private_constant :HEADER_CLASS
|
21
|
-
|
22
|
-
HEARTBEAT_RESPONSE = [200, {'Content-Type'=>'text/plain'}.freeze, ['OK'.freeze].freeze].freeze
|
23
|
-
|
24
17
|
# Set the heartbeat path to the given path.
|
25
18
|
def self.configure(app, opts=OPTS)
|
26
19
|
app.opts[:heartbeat_path] = (opts[:path] || app.opts[:heartbeat_path] || "/heartbeat").dup.freeze
|
@@ -32,9 +25,11 @@ class Roda
|
|
32
25
|
# If the request is for a heartbeat path, return the heartbeat response.
|
33
26
|
def _roda_before_20__heartbeat
|
34
27
|
if env['PATH_INFO'] == opts[:heartbeat_path]
|
35
|
-
response =
|
36
|
-
response
|
37
|
-
|
28
|
+
response = @_response
|
29
|
+
response.status = 200
|
30
|
+
response['Content-Type'] = 'text/plain'
|
31
|
+
response.write 'OK'
|
32
|
+
throw :halt, response.finish
|
38
33
|
end
|
39
34
|
end
|
40
35
|
end
|
@@ -52,14 +52,12 @@ class Roda
|
|
52
52
|
end
|
53
53
|
|
54
54
|
class Params < Rack::QueryParser::Params
|
55
|
-
|
56
|
-
if Rack.release >= '2.3'
|
55
|
+
if Rack.release >= '3'
|
57
56
|
def initialize
|
58
57
|
@size = 0
|
59
58
|
@params = Hash.new(&INDIFFERENT_PROC)
|
60
59
|
end
|
61
60
|
else
|
62
|
-
# :nocov:
|
63
61
|
def initialize(limit = Rack::Utils.key_space_limit)
|
64
62
|
@limit = limit
|
65
63
|
@size = 0
|
@@ -71,9 +69,7 @@ class Roda
|
|
71
69
|
end
|
72
70
|
|
73
71
|
module RequestMethods
|
74
|
-
|
75
|
-
query_parser = Rack.release >= '2.3' ? QueryParser.new(QueryParser::Params, 32) : QueryParser.new(QueryParser::Params, 65536, 32)
|
76
|
-
# :nocov:
|
72
|
+
query_parser = Rack.release >= '3' ? QueryParser.new(QueryParser::Params, 32) : QueryParser.new(QueryParser::Params, 65536, 32)
|
77
73
|
QUERY_PARSER = Rack::Utils.default_query_parser = query_parser
|
78
74
|
|
79
75
|
private
|
@@ -89,7 +85,6 @@ class Roda
|
|
89
85
|
end
|
90
86
|
end
|
91
87
|
else
|
92
|
-
# :nocov:
|
93
88
|
module InstanceMethods
|
94
89
|
# A copy of the request params that will automatically
|
95
90
|
# convert symbols to strings.
|
@@ -115,7 +110,6 @@ class Roda
|
|
115
110
|
end
|
116
111
|
end
|
117
112
|
end
|
118
|
-
# :nocov:
|
119
113
|
end
|
120
114
|
end
|
121
115
|
|
@@ -86,12 +86,10 @@ class Roda
|
|
86
86
|
|
87
87
|
|
88
88
|
# Rack 3 dropped requirement that input be rewindable
|
89
|
-
if Rack.release >= '
|
90
|
-
# :nocov:
|
89
|
+
if Rack.release >= '3'
|
91
90
|
def _read_json_input(input)
|
92
91
|
input.read
|
93
92
|
end
|
94
|
-
# :nocov:
|
95
93
|
else
|
96
94
|
def _read_json_input(input)
|
97
95
|
input.rewind
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
class Roda
|
5
|
+
module RodaPlugins
|
6
|
+
# The link_to plugin adds the +link_to+ instance method, which can be used for constructing
|
7
|
+
# HTML links (+a+ tag with +href+ attribute).
|
8
|
+
#
|
9
|
+
# The simplest usage of +link_to+ is passing the body and the location to link to as strings:
|
10
|
+
#
|
11
|
+
# link_to("body", "/path")
|
12
|
+
# # => "<a href=\"/path\">body</a>"
|
13
|
+
#
|
14
|
+
# The link_to plugin depends on the path plugin, and allows you to pass symbols for named paths:
|
15
|
+
#
|
16
|
+
# # Class level
|
17
|
+
# path :foo, "/path/to/too"
|
18
|
+
#
|
19
|
+
# # Instance level
|
20
|
+
# link_to("body", :foo)
|
21
|
+
# # => "<a href=\"/path/to/foo\">body</a>"
|
22
|
+
#
|
23
|
+
# It also allows you to pass instances of classes that you have registered with the path plugin:
|
24
|
+
#
|
25
|
+
# # Class level
|
26
|
+
# A = Struct.new(:id)
|
27
|
+
# path A do
|
28
|
+
# "/path/to/a/#{id}"
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# # Instance level
|
32
|
+
# link_to("body", A.new(1))
|
33
|
+
# # => "<a href=\"/path/to/a/1\">body</a>"
|
34
|
+
#
|
35
|
+
# To set additional HTML attributes on the +a+ tag, you can pass them as an options hash:
|
36
|
+
#
|
37
|
+
# link_to("body", "/path", foo: "bar")
|
38
|
+
# # => "<a href=\"/path\" foo=\"bar\">body</a>"
|
39
|
+
#
|
40
|
+
# If the body is nil, it will be set to the same as the path:
|
41
|
+
#
|
42
|
+
# link_to(nil, "/path")
|
43
|
+
# # => "<a href=\"/path\">/path</a>"
|
44
|
+
#
|
45
|
+
# The plugin will automatically HTML escape the path and any HTML attribute values, using the h plugin:
|
46
|
+
#
|
47
|
+
# link_to("body", "/path?a=1&b=2", foo: '"bar"')
|
48
|
+
# # => "<a href=\"/path?a=1&b=2\" foo=\""bar"\">body</a>"
|
49
|
+
module LinkTo
|
50
|
+
def self.load_dependencies(app)
|
51
|
+
app.plugin :h
|
52
|
+
app.plugin :path
|
53
|
+
end
|
54
|
+
|
55
|
+
module InstanceMethods
|
56
|
+
# Return a string with an HTML +a+ tag with an +href+ attribute. See LinkTo
|
57
|
+
# module documentation for details.
|
58
|
+
def link_to(body, href, attributes=OPTS)
|
59
|
+
case href
|
60
|
+
when Symbol
|
61
|
+
href = public_send(:"#{href}_path")
|
62
|
+
when String
|
63
|
+
# nothing
|
64
|
+
else
|
65
|
+
href = path(href)
|
66
|
+
end
|
67
|
+
|
68
|
+
href = h(href)
|
69
|
+
|
70
|
+
body = href if body.nil?
|
71
|
+
|
72
|
+
buf = String.new << "<a href=\"#{href}\""
|
73
|
+
attributes.each do |k, v|
|
74
|
+
buf << " " << k.to_s << "=\"" << h(v) << "\""
|
75
|
+
end
|
76
|
+
buf << ">" << body << "</a>"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
register_plugin(:link_to, LinkTo)
|
82
|
+
end
|
83
|
+
end
|
@@ -465,7 +465,11 @@ class Roda
|
|
465
465
|
def #{field}(address, &block)
|
466
466
|
on(:#{field}=>address, &block)
|
467
467
|
end
|
468
|
+
END
|
469
|
+
|
470
|
+
next if [:rcpt, :text, :body, :subject].include?(field)
|
468
471
|
|
472
|
+
class_eval(<<-END, __FILE__, __LINE__+1)
|
469
473
|
private
|
470
474
|
|
471
475
|
def match_#{field}(address)
|
@@ -474,11 +478,6 @@ class Roda
|
|
474
478
|
END
|
475
479
|
end
|
476
480
|
|
477
|
-
undef_method :match_rcpt
|
478
|
-
undef_method :match_text
|
479
|
-
undef_method :match_body
|
480
|
-
undef_method :match_subject
|
481
|
-
|
482
481
|
# Same as +header+, but also mark the message as being handled.
|
483
482
|
def handle_header(key, value=nil)
|
484
483
|
header(key, value) do |*args|
|
@@ -3,9 +3,7 @@
|
|
3
3
|
begin
|
4
4
|
require 'rack/files'
|
5
5
|
rescue LoadError
|
6
|
-
# :nocov:
|
7
6
|
require 'rack/file'
|
8
|
-
# :nocov:
|
9
7
|
end
|
10
8
|
|
11
9
|
#
|
@@ -66,9 +64,7 @@ class Roda
|
|
66
64
|
# end
|
67
65
|
# end
|
68
66
|
module MultiPublic
|
69
|
-
# :nocov:
|
70
67
|
RACK_FILES = defined?(Rack::Files) ? Rack::Files : Rack::File
|
71
|
-
# :nocov:
|
72
68
|
|
73
69
|
def self.load_dependencies(app, _, opts=OPTS)
|
74
70
|
app.plugin(:public, opts)
|
@@ -116,9 +116,7 @@ class Roda
|
|
116
116
|
# arguments, record the verb used. If given an argument, add an is
|
117
117
|
# check with the arguments.
|
118
118
|
%w'get post delete head options link patch put trace unlink'.each do |verb|
|
119
|
-
# :nocov:
|
120
119
|
if ::Rack::Request.method_defined?("#{verb}?")
|
121
|
-
# :nocov:
|
122
120
|
class_eval(<<-END, __FILE__, __LINE__+1)
|
123
121
|
def #{verb}(*args, &block)
|
124
122
|
if (empty = args.empty?) && @_is_verbs
|
data/lib/roda/plugins/public.rb
CHANGED
@@ -5,9 +5,7 @@ require 'uri'
|
|
5
5
|
begin
|
6
6
|
require 'rack/files'
|
7
7
|
rescue LoadError
|
8
|
-
# :nocov:
|
9
8
|
require 'rack/file'
|
10
|
-
# :nocov:
|
11
9
|
end
|
12
10
|
|
13
11
|
#
|
@@ -45,9 +43,7 @@ class Roda
|
|
45
43
|
module Public
|
46
44
|
SPLIT = Regexp.union(*[File::SEPARATOR, File::ALT_SEPARATOR].compact)
|
47
45
|
PARSER = URI::DEFAULT_PARSER
|
48
|
-
# :nocov:
|
49
46
|
RACK_FILES = defined?(Rack::Files) ? Rack::Files : Rack::File
|
50
|
-
# :nocov:
|
51
47
|
|
52
48
|
# Use options given to setup a Rack::File instance for serving files. Options:
|
53
49
|
# :default_mime :: The default mime type to use if the mime type is not recognized.
|
@@ -142,13 +138,11 @@ class Roda
|
|
142
138
|
server.serving(self, path)
|
143
139
|
end
|
144
140
|
else
|
145
|
-
# :nocov:
|
146
141
|
def public_serve(server, path)
|
147
142
|
server = server.dup
|
148
143
|
server.path = path
|
149
144
|
server.serving(env)
|
150
145
|
end
|
151
|
-
# :nocov:
|
152
146
|
end
|
153
147
|
end
|
154
148
|
end
|
data/lib/roda/plugins/render.rb
CHANGED
@@ -214,18 +214,18 @@ class Roda
|
|
214
214
|
tilt_compiled_method_support = defined?(Tilt::VERSION) && Tilt::VERSION >= '1.2' &&
|
215
215
|
([1, -2].include?(((compiled_method_arity = Tilt::Template.instance_method(:compiled_method).arity) rescue false)))
|
216
216
|
NO_CACHE = {:cache=>false}.freeze
|
217
|
-
COMPILED_METHOD_SUPPORT = RUBY_VERSION >= '2.3' && tilt_compiled_method_support
|
217
|
+
COMPILED_METHOD_SUPPORT = RUBY_VERSION >= '2.3' && tilt_compiled_method_support && ENV['RODA_RENDER_COMPILED_METHOD_SUPPORT'] != 'no'
|
218
218
|
|
219
219
|
if compiled_method_arity == -2
|
220
220
|
def self.tilt_template_compiled_method(template, locals_keys, scope_class)
|
221
221
|
template.send(:compiled_method, locals_keys, scope_class)
|
222
222
|
end
|
223
|
+
# :nocov:
|
223
224
|
else
|
224
|
-
# :nocov:
|
225
225
|
def self.tilt_template_compiled_method(template, locals_keys, scope_class)
|
226
226
|
template.send(:compiled_method, locals_keys)
|
227
227
|
end
|
228
|
-
|
228
|
+
# :nocov:
|
229
229
|
end
|
230
230
|
|
231
231
|
# Setup default rendering options. See Render for details.
|
@@ -366,9 +366,7 @@ class Roda
|
|
366
366
|
false
|
367
367
|
end
|
368
368
|
|
369
|
-
# :nocov:
|
370
369
|
if COMPILED_METHOD_SUPPORT
|
371
|
-
# :nocov:
|
372
370
|
# Compile a method in the given module with the given name that will
|
373
371
|
# call the compiled template method, updating the compiled template method
|
374
372
|
def define_compiled_method(roda_class, method_name, locals_keys=EMPTY_ARRAY)
|
@@ -412,9 +410,7 @@ class Roda
|
|
412
410
|
end
|
413
411
|
|
414
412
|
module ClassMethods
|
415
|
-
# :nocov:
|
416
413
|
if COMPILED_METHOD_SUPPORT
|
417
|
-
# :nocov:
|
418
414
|
# If using compiled methods and there is an optimized layout, speed up
|
419
415
|
# access to the layout method to improve the performance of view.
|
420
416
|
def freeze
|
@@ -437,9 +433,7 @@ class Roda
|
|
437
433
|
def inherited(subclass)
|
438
434
|
super
|
439
435
|
opts = subclass.opts[:render] = subclass.opts[:render].dup
|
440
|
-
# :nocov:
|
441
436
|
if COMPILED_METHOD_SUPPORT
|
442
|
-
# :nocov:
|
443
437
|
opts[:template_method_cache] = (opts[:cache_class] || RodaCache).new
|
444
438
|
end
|
445
439
|
opts[:cache] = opts[:cache].dup
|
@@ -459,9 +453,7 @@ class Roda
|
|
459
453
|
instance = allocate
|
460
454
|
instance.send(:retrieve_template, instance.send(:view_layout_opts, OPTS))
|
461
455
|
|
462
|
-
# :nocov:
|
463
456
|
if COMPILED_METHOD_SUPPORT
|
464
|
-
# :nocov:
|
465
457
|
if (layout_template = render_opts[:optimize_layout]) && !opts[:render][:optimized_layout_method_created]
|
466
458
|
instance.send(:retrieve_template, :template=>layout_template, :cache_key=>nil, :template_method_cache_key => :_roda_layout)
|
467
459
|
layout_method = opts[:render][:template_method_cache][:_roda_layout]
|
@@ -610,7 +602,6 @@ class Roda
|
|
610
602
|
end
|
611
603
|
end
|
612
604
|
else
|
613
|
-
# :nocov:
|
614
605
|
def _cached_template_method(_)
|
615
606
|
nil
|
616
607
|
end
|
@@ -630,7 +621,6 @@ class Roda
|
|
630
621
|
def _optimized_view_content(template)
|
631
622
|
nil
|
632
623
|
end
|
633
|
-
# :nocov:
|
634
624
|
end
|
635
625
|
|
636
626
|
|
@@ -43,9 +43,7 @@ class Roda
|
|
43
43
|
module InstanceMethods
|
44
44
|
private
|
45
45
|
|
46
|
-
# :nocov:
|
47
46
|
if Render::COMPILED_METHOD_SUPPORT
|
48
|
-
# :nocov:
|
49
47
|
# Disable use of cached templates, since it assumes a render/view call with no
|
50
48
|
# options will have no locals.
|
51
49
|
def _cached_template_method(template)
|
@@ -4,9 +4,7 @@ require 'rack/mime'
|
|
4
4
|
begin
|
5
5
|
require 'rack/files'
|
6
6
|
rescue LoadError
|
7
|
-
# :nocov:
|
8
7
|
require 'rack/file'
|
9
|
-
# :nocov:
|
10
8
|
end
|
11
9
|
|
12
10
|
|
@@ -225,9 +223,7 @@ class Roda
|
|
225
223
|
ISO88591_ENCODING = Encoding.find('ISO-8859-1')
|
226
224
|
BINARY_ENCODING = Encoding.find('BINARY')
|
227
225
|
|
228
|
-
# :nocov:
|
229
226
|
RACK_FILES = defined?(Rack::Files) ? Rack::Files : Rack::File
|
230
|
-
# :nocov:
|
231
227
|
|
232
228
|
# Depend on the status_303 plugin.
|
233
229
|
def self.load_dependencies(app, _opts = nil)
|
@@ -351,10 +347,8 @@ class Roda
|
|
351
347
|
s, h, b = if Rack.release > '2'
|
352
348
|
file.serving(self, path)
|
353
349
|
else
|
354
|
-
# :nocov:
|
355
350
|
file.path = path
|
356
351
|
file.serving(@env)
|
357
|
-
# :nocov:
|
358
352
|
end
|
359
353
|
|
360
354
|
res.status = opts[:status] || s
|
@@ -45,11 +45,9 @@ class Roda
|
|
45
45
|
when nil, false
|
46
46
|
CLEAR_HEADERS
|
47
47
|
when Array
|
48
|
-
|
49
|
-
if Rack.release >= '2.3'
|
48
|
+
if Rack.release >= '3'
|
50
49
|
keep_headers = keep_headers.map(&:downcase)
|
51
50
|
end
|
52
|
-
# :nocov:
|
53
51
|
lambda{|headers| headers.delete_if{|k,_| !keep_headers.include?(k)}}
|
54
52
|
else
|
55
53
|
raise RodaError, "Invalid :keep_headers option"
|
@@ -126,9 +126,7 @@ class Roda
|
|
126
126
|
|
127
127
|
private
|
128
128
|
|
129
|
-
# :nocov:
|
130
129
|
if Render::COMPILED_METHOD_SUPPORT
|
131
|
-
# :nocov:
|
132
130
|
# Return nil if using custom view or layout options.
|
133
131
|
# If using a view subdir, prefix the template key with the subdir.
|
134
132
|
def _cached_template_method_key(template)
|
data/lib/roda/request.rb
CHANGED
@@ -1,18 +1,16 @@
|
|
1
1
|
# frozen-string-literal: true
|
2
2
|
|
3
|
-
# :nocov:
|
4
3
|
begin
|
5
4
|
require "rack/version"
|
6
5
|
rescue LoadError
|
7
6
|
require "rack"
|
8
7
|
else
|
9
|
-
if Rack.release >= '
|
8
|
+
if Rack.release >= '3'
|
10
9
|
require "rack/request"
|
11
10
|
else
|
12
11
|
require "rack"
|
13
12
|
end
|
14
13
|
end
|
15
|
-
# :nocov:
|
16
14
|
|
17
15
|
require_relative "cache"
|
18
16
|
|
@@ -129,8 +127,7 @@ class Roda
|
|
129
127
|
"#<#{self.class.inspect} #{@env["REQUEST_METHOD"]} #{path}>"
|
130
128
|
end
|
131
129
|
|
132
|
-
|
133
|
-
if Rack.release >= '2.3'
|
130
|
+
if Rack.release >= '3'
|
134
131
|
def http_version
|
135
132
|
# Prefer SERVER_PROTOCOL as it is required in Rack 3.
|
136
133
|
# Still fall back to HTTP_VERSION if SERVER_PROTOCOL
|
@@ -139,7 +136,6 @@ class Roda
|
|
139
136
|
@env['SERVER_PROTOCOL'] || @env['HTTP_VERSION']
|
140
137
|
end
|
141
138
|
else
|
142
|
-
# :nocov:
|
143
139
|
# What HTTP version the request was submitted with.
|
144
140
|
def http_version
|
145
141
|
# Prefer HTTP_VERSION as it is backwards compatible
|
data/lib/roda/response.rb
CHANGED
@@ -42,7 +42,6 @@ class Roda
|
|
42
42
|
# code for non-empty responses and a 404 code for empty responses.
|
43
43
|
attr_accessor :status
|
44
44
|
|
45
|
-
# :nocov:
|
46
45
|
if defined?(Rack::Headers) && Rack::Headers.is_a?(Class)
|
47
46
|
# Set the default headers when creating a response.
|
48
47
|
def initialize
|
@@ -51,7 +50,6 @@ class Roda
|
|
51
50
|
@length = 0
|
52
51
|
end
|
53
52
|
else
|
54
|
-
# :nocov:
|
55
53
|
# Set the default headers when creating a response.
|
56
54
|
def initialize
|
57
55
|
@headers = {}
|
@@ -173,7 +171,6 @@ class Roda
|
|
173
171
|
|
174
172
|
private
|
175
173
|
|
176
|
-
# :nocov:
|
177
174
|
if Rack.release < '2.0.2'
|
178
175
|
# Don't use a content length for empty 205 responses on
|
179
176
|
# rack 1, as it violates Rack::Lint in that version.
|
@@ -181,7 +178,6 @@ class Roda
|
|
181
178
|
headers.delete("Content-Type")
|
182
179
|
headers.delete("Content-Length")
|
183
180
|
end
|
184
|
-
# :nocov:
|
185
181
|
else
|
186
182
|
# Set the content length for empty 205 responses to 0
|
187
183
|
def empty_205_headers(headers)
|
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.60.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: 2022-
|
11
|
+
date: 2022-09-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -229,7 +229,10 @@ extra_rdoc_files:
|
|
229
229
|
- doc/release_notes/3.55.0.txt
|
230
230
|
- doc/release_notes/3.56.0.txt
|
231
231
|
- doc/release_notes/3.57.0.txt
|
232
|
+
- doc/release_notes/3.58.0.txt
|
233
|
+
- doc/release_notes/3.59.0.txt
|
232
234
|
- doc/release_notes/3.6.0.txt
|
235
|
+
- doc/release_notes/3.60.0.txt
|
233
236
|
- doc/release_notes/3.7.0.txt
|
234
237
|
- doc/release_notes/3.8.0.txt
|
235
238
|
- doc/release_notes/3.9.0.txt
|
@@ -293,7 +296,10 @@ files:
|
|
293
296
|
- doc/release_notes/3.55.0.txt
|
294
297
|
- doc/release_notes/3.56.0.txt
|
295
298
|
- doc/release_notes/3.57.0.txt
|
299
|
+
- doc/release_notes/3.58.0.txt
|
300
|
+
- doc/release_notes/3.59.0.txt
|
296
301
|
- doc/release_notes/3.6.0.txt
|
302
|
+
- doc/release_notes/3.60.0.txt
|
297
303
|
- doc/release_notes/3.7.0.txt
|
298
304
|
- doc/release_notes/3.8.0.txt
|
299
305
|
- doc/release_notes/3.9.0.txt
|
@@ -304,6 +310,7 @@ files:
|
|
304
310
|
- lib/roda/plugins/_before_hook.rb
|
305
311
|
- lib/roda/plugins/_optimized_matching.rb
|
306
312
|
- lib/roda/plugins/_symbol_regexp_matchers.rb
|
313
|
+
- lib/roda/plugins/additional_render_engines.rb
|
307
314
|
- lib/roda/plugins/additional_view_directories.rb
|
308
315
|
- lib/roda/plugins/all_verbs.rb
|
309
316
|
- lib/roda/plugins/assets.rb
|
@@ -336,6 +343,7 @@ files:
|
|
336
343
|
- lib/roda/plugins/error_handler.rb
|
337
344
|
- lib/roda/plugins/error_mail.rb
|
338
345
|
- lib/roda/plugins/exception_page.rb
|
346
|
+
- lib/roda/plugins/filter_common_logger.rb
|
339
347
|
- lib/roda/plugins/flash.rb
|
340
348
|
- lib/roda/plugins/h.rb
|
341
349
|
- lib/roda/plugins/halt.rb
|
@@ -353,6 +361,7 @@ files:
|
|
353
361
|
- lib/roda/plugins/inject_erb.rb
|
354
362
|
- lib/roda/plugins/json.rb
|
355
363
|
- lib/roda/plugins/json_parser.rb
|
364
|
+
- lib/roda/plugins/link_to.rb
|
356
365
|
- lib/roda/plugins/mail_processor.rb
|
357
366
|
- lib/roda/plugins/mailer.rb
|
358
367
|
- lib/roda/plugins/match_affix.rb
|