ultra-lite-hub 0.0.1

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.
Files changed (162) hide show
  1. checksums.yaml +7 -0
  2. data/roda-3.105.0/MIT-LICENSE +21 -0
  3. data/roda-3.105.0/lib/roda/cache.rb +42 -0
  4. data/roda-3.105.0/lib/roda/plugins/Integer_matcher_max.rb +55 -0
  5. data/roda-3.105.0/lib/roda/plugins/_after_hook.rb +11 -0
  6. data/roda-3.105.0/lib/roda/plugins/_base64.rb +34 -0
  7. data/roda-3.105.0/lib/roda/plugins/_before_hook.rb +41 -0
  8. data/roda-3.105.0/lib/roda/plugins/_optimized_matching.rb +227 -0
  9. data/roda-3.105.0/lib/roda/plugins/_symbol_class_matchers.rb +108 -0
  10. data/roda-3.105.0/lib/roda/plugins/_symbol_regexp_matchers.rb +24 -0
  11. data/roda-3.105.0/lib/roda/plugins/additional_render_engines.rb +61 -0
  12. data/roda-3.105.0/lib/roda/plugins/additional_view_directories.rb +66 -0
  13. data/roda-3.105.0/lib/roda/plugins/all_verbs.rb +50 -0
  14. data/roda-3.105.0/lib/roda/plugins/assets.rb +902 -0
  15. data/roda-3.105.0/lib/roda/plugins/assets_preloading.rb +89 -0
  16. data/roda-3.105.0/lib/roda/plugins/assume_ssl.rb +28 -0
  17. data/roda-3.105.0/lib/roda/plugins/autoload_hash_branches.rb +79 -0
  18. data/roda-3.105.0/lib/roda/plugins/autoload_named_routes.rb +65 -0
  19. data/roda-3.105.0/lib/roda/plugins/backtracking_array.rb +88 -0
  20. data/roda-3.105.0/lib/roda/plugins/bearer_token.rb +28 -0
  21. data/roda-3.105.0/lib/roda/plugins/branch_locals.rb +74 -0
  22. data/roda-3.105.0/lib/roda/plugins/break.rb +43 -0
  23. data/roda-3.105.0/lib/roda/plugins/caching.rb +206 -0
  24. data/roda-3.105.0/lib/roda/plugins/capture_erb.rb +94 -0
  25. data/roda-3.105.0/lib/roda/plugins/chunked.rb +331 -0
  26. data/roda-3.105.0/lib/roda/plugins/class_level_routing.rb +111 -0
  27. data/roda-3.105.0/lib/roda/plugins/class_matchers.rb +155 -0
  28. data/roda-3.105.0/lib/roda/plugins/common_logger.rb +80 -0
  29. data/roda-3.105.0/lib/roda/plugins/conditional_sessions.rb +67 -0
  30. data/roda-3.105.0/lib/roda/plugins/content_for.rb +103 -0
  31. data/roda-3.105.0/lib/roda/plugins/content_security_policy.rb +329 -0
  32. data/roda-3.105.0/lib/roda/plugins/cookie_flags.rb +157 -0
  33. data/roda-3.105.0/lib/roda/plugins/cookies.rb +51 -0
  34. data/roda-3.105.0/lib/roda/plugins/csrf.rb +81 -0
  35. data/roda-3.105.0/lib/roda/plugins/custom_block_results.rb +85 -0
  36. data/roda-3.105.0/lib/roda/plugins/custom_matchers.rb +89 -0
  37. data/roda-3.105.0/lib/roda/plugins/default_headers.rb +64 -0
  38. data/roda-3.105.0/lib/roda/plugins/default_status.rb +35 -0
  39. data/roda-3.105.0/lib/roda/plugins/delay_build.rb +18 -0
  40. data/roda-3.105.0/lib/roda/plugins/delegate.rb +77 -0
  41. data/roda-3.105.0/lib/roda/plugins/delete_empty_headers.rb +36 -0
  42. data/roda-3.105.0/lib/roda/plugins/direct_call.rb +38 -0
  43. data/roda-3.105.0/lib/roda/plugins/disallow_file_uploads.rb +38 -0
  44. data/roda-3.105.0/lib/roda/plugins/drop_body.rb +43 -0
  45. data/roda-3.105.0/lib/roda/plugins/each_part.rb +87 -0
  46. data/roda-3.105.0/lib/roda/plugins/early_hints.rb +25 -0
  47. data/roda-3.105.0/lib/roda/plugins/empty_root.rb +49 -0
  48. data/roda-3.105.0/lib/roda/plugins/environments.rb +79 -0
  49. data/roda-3.105.0/lib/roda/plugins/erb_h.rb +43 -0
  50. data/roda-3.105.0/lib/roda/plugins/error_email.rb +152 -0
  51. data/roda-3.105.0/lib/roda/plugins/error_handler.rb +133 -0
  52. data/roda-3.105.0/lib/roda/plugins/error_mail.rb +149 -0
  53. data/roda-3.105.0/lib/roda/plugins/exception_page.rb +445 -0
  54. data/roda-3.105.0/lib/roda/plugins/filter_common_logger.rb +46 -0
  55. data/roda-3.105.0/lib/roda/plugins/flash.rb +117 -0
  56. data/roda-3.105.0/lib/roda/plugins/h.rb +59 -0
  57. data/roda-3.105.0/lib/roda/plugins/halt.rb +108 -0
  58. data/roda-3.105.0/lib/roda/plugins/hash_branch_view_subdir.rb +76 -0
  59. data/roda-3.105.0/lib/roda/plugins/hash_branches.rb +145 -0
  60. data/roda-3.105.0/lib/roda/plugins/hash_matcher.rb +39 -0
  61. data/roda-3.105.0/lib/roda/plugins/hash_paths.rb +128 -0
  62. data/roda-3.105.0/lib/roda/plugins/hash_public.rb +125 -0
  63. data/roda-3.105.0/lib/roda/plugins/hash_public_cache.rb +91 -0
  64. data/roda-3.105.0/lib/roda/plugins/hash_routes.rb +304 -0
  65. data/roda-3.105.0/lib/roda/plugins/head.rb +99 -0
  66. data/roda-3.105.0/lib/roda/plugins/header_matchers.rb +88 -0
  67. data/roda-3.105.0/lib/roda/plugins/heartbeat.rb +41 -0
  68. data/roda-3.105.0/lib/roda/plugins/hmac_paths.rb +413 -0
  69. data/roda-3.105.0/lib/roda/plugins/hooks.rb +92 -0
  70. data/roda-3.105.0/lib/roda/plugins/host_authorization.rb +155 -0
  71. data/roda-3.105.0/lib/roda/plugins/host_routing.rb +190 -0
  72. data/roda-3.105.0/lib/roda/plugins/hsts.rb +35 -0
  73. data/roda-3.105.0/lib/roda/plugins/indifferent_params.rb +124 -0
  74. data/roda-3.105.0/lib/roda/plugins/inject_erb.rb +33 -0
  75. data/roda-3.105.0/lib/roda/plugins/invalid_request_body.rb +107 -0
  76. data/roda-3.105.0/lib/roda/plugins/ip_from_header.rb +34 -0
  77. data/roda-3.105.0/lib/roda/plugins/json.rb +119 -0
  78. data/roda-3.105.0/lib/roda/plugins/json_parser.rb +107 -0
  79. data/roda-3.105.0/lib/roda/plugins/link_to.rb +83 -0
  80. data/roda-3.105.0/lib/roda/plugins/mail_processor.rb +629 -0
  81. data/roda-3.105.0/lib/roda/plugins/mailer.rb +283 -0
  82. data/roda-3.105.0/lib/roda/plugins/map_matcher.rb +48 -0
  83. data/roda-3.105.0/lib/roda/plugins/match_affix.rb +64 -0
  84. data/roda-3.105.0/lib/roda/plugins/match_hook.rb +34 -0
  85. data/roda-3.105.0/lib/roda/plugins/match_hook_args.rb +93 -0
  86. data/roda-3.105.0/lib/roda/plugins/middleware.rb +225 -0
  87. data/roda-3.105.0/lib/roda/plugins/middleware_stack.rb +101 -0
  88. data/roda-3.105.0/lib/roda/plugins/module_include.rb +96 -0
  89. data/roda-3.105.0/lib/roda/plugins/multi_public.rb +95 -0
  90. data/roda-3.105.0/lib/roda/plugins/multi_route.rb +156 -0
  91. data/roda-3.105.0/lib/roda/plugins/multi_run.rb +144 -0
  92. data/roda-3.105.0/lib/roda/plugins/multi_view.rb +83 -0
  93. data/roda-3.105.0/lib/roda/plugins/multibyte_string_matcher.rb +57 -0
  94. data/roda-3.105.0/lib/roda/plugins/named_routes.rb +167 -0
  95. data/roda-3.105.0/lib/roda/plugins/named_templates.rb +102 -0
  96. data/roda-3.105.0/lib/roda/plugins/not_allowed.rb +149 -0
  97. data/roda-3.105.0/lib/roda/plugins/not_found.rb +55 -0
  98. data/roda-3.105.0/lib/roda/plugins/optimized_segment_matchers.rb +53 -0
  99. data/roda-3.105.0/lib/roda/plugins/optimized_string_matchers.rb +50 -0
  100. data/roda-3.105.0/lib/roda/plugins/padrino_render.rb +42 -0
  101. data/roda-3.105.0/lib/roda/plugins/param_matchers.rb +83 -0
  102. data/roda-3.105.0/lib/roda/plugins/params_capturing.rb +116 -0
  103. data/roda-3.105.0/lib/roda/plugins/part.rb +76 -0
  104. data/roda-3.105.0/lib/roda/plugins/partials.rb +74 -0
  105. data/roda-3.105.0/lib/roda/plugins/pass.rb +47 -0
  106. data/roda-3.105.0/lib/roda/plugins/path.rb +255 -0
  107. data/roda-3.105.0/lib/roda/plugins/path_matchers.rb +54 -0
  108. data/roda-3.105.0/lib/roda/plugins/path_rewriter.rb +111 -0
  109. data/roda-3.105.0/lib/roda/plugins/permissions_policy.rb +336 -0
  110. data/roda-3.105.0/lib/roda/plugins/placeholder_string_matchers.rb +48 -0
  111. data/roda-3.105.0/lib/roda/plugins/plain_hash_response_headers.rb +32 -0
  112. data/roda-3.105.0/lib/roda/plugins/precompile_templates.rb +156 -0
  113. data/roda-3.105.0/lib/roda/plugins/public.rb +182 -0
  114. data/roda-3.105.0/lib/roda/plugins/r.rb +35 -0
  115. data/roda-3.105.0/lib/roda/plugins/recheck_precompiled_assets.rb +107 -0
  116. data/roda-3.105.0/lib/roda/plugins/redirect_http_to_https.rb +99 -0
  117. data/roda-3.105.0/lib/roda/plugins/redirect_path.rb +59 -0
  118. data/roda-3.105.0/lib/roda/plugins/relative_path.rb +74 -0
  119. data/roda-3.105.0/lib/roda/plugins/render.rb +998 -0
  120. data/roda-3.105.0/lib/roda/plugins/render_coverage.rb +105 -0
  121. data/roda-3.105.0/lib/roda/plugins/render_each.rb +224 -0
  122. data/roda-3.105.0/lib/roda/plugins/render_locals.rb +102 -0
  123. data/roda-3.105.0/lib/roda/plugins/request_aref.rb +77 -0
  124. data/roda-3.105.0/lib/roda/plugins/request_headers.rb +81 -0
  125. data/roda-3.105.0/lib/roda/plugins/response_attachment.rb +94 -0
  126. data/roda-3.105.0/lib/roda/plugins/response_content_type.rb +79 -0
  127. data/roda-3.105.0/lib/roda/plugins/response_request.rb +29 -0
  128. data/roda-3.105.0/lib/roda/plugins/route_block_args.rb +50 -0
  129. data/roda-3.105.0/lib/roda/plugins/route_csrf.rb +388 -0
  130. data/roda-3.105.0/lib/roda/plugins/run_append_slash.rb +51 -0
  131. data/roda-3.105.0/lib/roda/plugins/run_handler.rb +51 -0
  132. data/roda-3.105.0/lib/roda/plugins/run_require_slash.rb +46 -0
  133. data/roda-3.105.0/lib/roda/plugins/sec_fetch_site_csrf.rb +131 -0
  134. data/roda-3.105.0/lib/roda/plugins/send_file.rb +127 -0
  135. data/roda-3.105.0/lib/roda/plugins/sessions.rb +537 -0
  136. data/roda-3.105.0/lib/roda/plugins/shared_vars.rb +86 -0
  137. data/roda-3.105.0/lib/roda/plugins/sinatra_helpers.rb +443 -0
  138. data/roda-3.105.0/lib/roda/plugins/slash_path_empty.rb +26 -0
  139. data/roda-3.105.0/lib/roda/plugins/static.rb +42 -0
  140. data/roda-3.105.0/lib/roda/plugins/static_routing.rb +89 -0
  141. data/roda-3.105.0/lib/roda/plugins/status_303.rb +34 -0
  142. data/roda-3.105.0/lib/roda/plugins/status_handler.rb +86 -0
  143. data/roda-3.105.0/lib/roda/plugins/streaming.rb +170 -0
  144. data/roda-3.105.0/lib/roda/plugins/strip_path_prefix.rb +33 -0
  145. data/roda-3.105.0/lib/roda/plugins/symbol_matchers.rb +188 -0
  146. data/roda-3.105.0/lib/roda/plugins/symbol_status.rb +32 -0
  147. data/roda-3.105.0/lib/roda/plugins/symbol_views.rb +37 -0
  148. data/roda-3.105.0/lib/roda/plugins/timestamp_public.rb +78 -0
  149. data/roda-3.105.0/lib/roda/plugins/type_routing.rb +215 -0
  150. data/roda-3.105.0/lib/roda/plugins/typecast_params.rb +1183 -0
  151. data/roda-3.105.0/lib/roda/plugins/typecast_params_sized_integers.rb +108 -0
  152. data/roda-3.105.0/lib/roda/plugins/unescape_path.rb +41 -0
  153. data/roda-3.105.0/lib/roda/plugins/view_options.rb +201 -0
  154. data/roda-3.105.0/lib/roda/plugins/view_subdir_leading_slash.rb +49 -0
  155. data/roda-3.105.0/lib/roda/plugins.rb +68 -0
  156. data/roda-3.105.0/lib/roda/request.rb +722 -0
  157. data/roda-3.105.0/lib/roda/response.rb +221 -0
  158. data/roda-3.105.0/lib/roda/session_middleware.rb +183 -0
  159. data/roda-3.105.0/lib/roda/version.rb +18 -0
  160. data/roda-3.105.0/lib/roda.rb +586 -0
  161. data/ultra-lite-hub.gemspec +12 -0
  162. metadata +201 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: fbbe1c7f2a3c43738c8c98358cc1ec12d792d3eef166171033f72c9404e5ae13
4
+ data.tar.gz: bb3d4c405cc6934a3f226af3bf21922b5d9ed39b33df4560cadc00eac183f0d9
5
+ SHA512:
6
+ metadata.gz: a4ee47127536f906c9ac92d330a60201444777884dd3055a798828994f4136911f6d0fd6b3c0d33fd4f62e066234d66e4cfaef9ab4101527a3571a4f2a858a7a
7
+ data.tar.gz: 9e85f412c5e1681ae67b2b26469525752b2fe4548abd8f53e7151bd18491ee150eae77b4812165b8ac6e9a680aed05abec3c2e43906ced905bb1e36f50b833fd
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2014-2026 Jeremy Evans and contributors
2
+ Copyright (c) 2010-2014 Michel Martens, Damian Janowski and Cyril David
3
+ Copyright (c) 2008-2009 Christian Neukirchen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,42 @@
1
+ # frozen-string-literal: true
2
+
3
+ require "thread"
4
+
5
+ class Roda
6
+ # A thread safe cache class, offering only #[] and #[]= methods,
7
+ # each protected by a mutex.
8
+ class RodaCache
9
+ # Create a new thread safe cache.
10
+ def initialize
11
+ @mutex = Mutex.new
12
+ @hash = {}
13
+ end
14
+
15
+ # Make getting value from underlying hash thread safe.
16
+ def [](key)
17
+ @mutex.synchronize{@hash[key]}
18
+ end
19
+
20
+ # Make setting value in underlying hash thread safe.
21
+ def []=(key, value)
22
+ @mutex.synchronize{@hash[key] = value}
23
+ end
24
+
25
+ # Return the frozen internal hash. The internal hash can then
26
+ # be accessed directly since it is frozen and there are no
27
+ # thread safety issues.
28
+ def freeze
29
+ @hash.freeze
30
+ end
31
+
32
+ private
33
+
34
+ # Create a copy of the cache with a separate mutex.
35
+ def initialize_copy(other)
36
+ @mutex = Mutex.new
37
+ other.instance_variable_get(:@mutex).synchronize do
38
+ @hash = other.instance_variable_get(:@hash).dup
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,55 @@
1
+ # frozen-string-literal: true
2
+
3
+ #
4
+ class Roda
5
+ module RodaPlugins
6
+ # The Integer_matcher_max plugin sets the maximum integer value
7
+ # value that the Integer class matcher will match by default.
8
+ # By default, loading this plugin sets the maximum value to
9
+ # 2**63-1, the largest signed 64-bit integer value:
10
+ #
11
+ # plugin :Integer_matcher_max
12
+ # route do |r|
13
+ # r.is Integer do
14
+ # # Matches /9223372036854775807
15
+ # # Does not match /9223372036854775808
16
+ # end
17
+ # end
18
+ #
19
+ # To specify a different maximum value, you can pass a different
20
+ # maximum value when loading the plugin:
21
+ #
22
+ # plugin :Integer_matcher_max, 2**64-1
23
+ module IntegerMatcherMax
24
+ def self.configure(app, max=nil)
25
+ if max
26
+ app.class_eval do
27
+ meth = :_max_value_convert_class_Integer
28
+ define_method(meth){max}
29
+ alias_method meth, meth
30
+ private meth
31
+ end
32
+ end
33
+ end
34
+
35
+ module InstanceMethods
36
+ private
37
+
38
+ # Do not have the Integer matcher max when over the maximum
39
+ # configured Integer value.
40
+ def _convert_class_Integer(value)
41
+ value = super
42
+ value if value <= _max_value_convert_class_Integer
43
+ end
44
+
45
+ # Use 2**63-1 as the default maximum value for the Integer
46
+ # matcher.
47
+ def _max_value_convert_class_Integer
48
+ 9223372036854775807
49
+ end
50
+ end
51
+ end
52
+
53
+ register_plugin(:Integer_matcher_max, IntegerMatcherMax)
54
+ end
55
+ end
@@ -0,0 +1,11 @@
1
+ # frozen-string-literal: true
2
+
3
+ require_relative 'error_handler'
4
+
5
+ #
6
+ class Roda
7
+ module RodaPlugins
8
+ # RODA4: Remove
9
+ register_plugin(:_after_hook, ErrorHandler)
10
+ end
11
+ end
@@ -0,0 +1,34 @@
1
+ # frozen-string-literal: true
2
+
3
+ #
4
+ class Roda
5
+ module RodaPlugins
6
+ module Base64_
7
+ class << self
8
+ if RUBY_VERSION >= '2.4'
9
+ def decode64(str)
10
+ str.unpack1("m0")
11
+ end
12
+ # :nocov:
13
+ else
14
+ def decode64(str)
15
+ str.unpack("m0")[0]
16
+ end
17
+ # :nocov:
18
+ end
19
+
20
+ def urlsafe_encode64(bin)
21
+ str = [bin].pack("m0")
22
+ str.tr!("+/", "-_")
23
+ str
24
+ end
25
+
26
+ def urlsafe_decode64(str)
27
+ decode64(str.tr("-_", "+/"))
28
+ end
29
+ end
30
+ end
31
+
32
+ register_plugin(:_base64, Base64_)
33
+ end
34
+ end
@@ -0,0 +1,41 @@
1
+ # frozen-string-literal: true
2
+
3
+ #
4
+ class Roda
5
+ module RodaPlugins
6
+ # Internal before hook module, not for external use.
7
+ # Allows for plugins to configure the order in which
8
+ # before processing is done by using _roda_before_*
9
+ # private instance methods that are called in sorted order.
10
+ # Loaded automatically by the base library if any _roda_before_*
11
+ # methods are defined.
12
+ module BeforeHook # :nodoc:
13
+ module InstanceMethods
14
+ # Run internal before hooks - Old Dispatch API.
15
+ def call(&block)
16
+ # RODA4: Remove
17
+ super do
18
+ _roda_before
19
+ instance_exec(@_request, &block) # call Fallback
20
+ end
21
+ end
22
+
23
+ # Run internal before hooks before running the main
24
+ # roda route.
25
+ def _roda_run_main_route(r)
26
+ _roda_before
27
+ super
28
+ end
29
+
30
+ private
31
+
32
+ # Default empty implementation of _roda_before, usually
33
+ # overridden by Roda.def_roda_before.
34
+ def _roda_before
35
+ end
36
+ end
37
+ end
38
+
39
+ register_plugin(:_before_hook, BeforeHook)
40
+ end
41
+ end
@@ -0,0 +1,227 @@
1
+ # frozen-string-literal: true
2
+
3
+ #
4
+ class Roda
5
+ module RodaPlugins
6
+ # The _optimized_matching plugin is automatically used internally to speed
7
+ # up matching when a single argument String instance, String class, Integer
8
+ # class, or Regexp matcher is passed to +r.on+, +r.is_+, or a verb method
9
+ # such as +r.get+ or +r.post+.
10
+ #
11
+ # The optimization works by avoiding the +if_match+ method if possible.
12
+ # Instead of clearing the captures array on every call, and having the
13
+ # matching append to the captures, it checks directly for the match,
14
+ # and on succesful match, it yields directly to the block without using
15
+ # the captures array.
16
+ module OptimizedMatching
17
+ TERM = Base::RequestMethods::TERM
18
+
19
+ module RequestMethods
20
+ # Optimize the r.is method handling of a single string, String, Integer,
21
+ # regexp, or true, argument.
22
+ def is(*args, &block)
23
+ case args.length
24
+ when 1
25
+ _is1(args, &block)
26
+ when 0
27
+ always(&block) if @remaining_path.empty?
28
+ else
29
+ if_match(args << TERM, &block)
30
+ end
31
+ end
32
+
33
+ # Optimize the r.on method handling of a single string, String, Integer,
34
+ # or regexp argument. Inline the related matching code to avoid the
35
+ # need to modify @captures.
36
+ def on(*args, &block)
37
+ case args.length
38
+ when 1
39
+ case matcher = args[0]
40
+ when String
41
+ always{yield} if _match_string(matcher)
42
+ when Class
43
+ if matcher == String
44
+ rp = @remaining_path
45
+ if rp.getbyte(0) == 47
46
+ if last = rp.index('/', 1)
47
+ @remaining_path = rp[last, rp.length]
48
+ always{yield rp[1, last-1]}
49
+ elsif (len = rp.length) > 1
50
+ @remaining_path = ""
51
+ always{yield rp[1, len]}
52
+ end
53
+ end
54
+ elsif matcher == Integer
55
+ rp = @remaining_path
56
+ if /\A\/(\d{1,100})(?=\/|\z)/.match?(rp)
57
+ if last = rp.index('/', 1)
58
+ value = rp[1, last-1]
59
+ rp = rp[last, rp.length]
60
+ else
61
+ value = rp[1, rp.length]
62
+ rp = ""
63
+ end
64
+
65
+ if value = scope.send(:_convert_class_Integer, value)
66
+ @remaining_path = rp
67
+ always{yield(value)}
68
+ end
69
+ end
70
+ else
71
+ path = @remaining_path
72
+ captures = @captures.clear
73
+ meth = :"_match_class_#{matcher}"
74
+ if respond_to?(meth, true)
75
+ # Allow calling private methods, as match methods are generally private
76
+ if send(meth, &block)
77
+ block_result(yield(*captures))
78
+ throw :halt, response.finish
79
+ else
80
+ @remaining_path = path
81
+ false
82
+ end
83
+ else
84
+ unsupported_matcher(matcher)
85
+ end
86
+ end
87
+ when Regexp
88
+ if matchdata = self.class.cached_matcher(matcher){matcher}.match(@remaining_path)
89
+ @remaining_path = matchdata.post_match
90
+ always{yield(*matchdata.captures)}
91
+ end
92
+ when true
93
+ always(&block)
94
+ when false, nil
95
+ # nothing
96
+ else
97
+ path = @remaining_path
98
+ captures = @captures.clear
99
+
100
+ matched = case matcher
101
+ when Array
102
+ _match_array(matcher)
103
+ when Hash
104
+ _match_hash(matcher)
105
+ when Symbol
106
+ _match_symbol(matcher)
107
+ when Proc
108
+ matcher.call
109
+ else
110
+ unsupported_matcher(matcher)
111
+ end
112
+
113
+ if matched
114
+ block_result(yield(*captures))
115
+ throw :halt, response.finish
116
+ else
117
+ @remaining_path = path
118
+ false
119
+ end
120
+ end
121
+ when 0
122
+ always(&block)
123
+ else
124
+ if_match(args, &block)
125
+ end
126
+ end
127
+
128
+ private
129
+
130
+ # Optimize the r.get/r.post method handling of a single string, String, Integer,
131
+ # regexp, or true, argument.
132
+ def _verb(args, &block)
133
+ case args.length
134
+ when 0
135
+ always(&block)
136
+ when 1
137
+ _is1(args, &block)
138
+ else
139
+ if_match(args << TERM, &block)
140
+ end
141
+ end
142
+
143
+ # Internals of r.is/r.get/r.post optimization. Inline the related matching
144
+ # code to avoid the need to modify @captures.
145
+ def _is1(args, &block)
146
+ case matcher = args[0]
147
+ when String
148
+ rp = @remaining_path
149
+ if _match_string(matcher)
150
+ if @remaining_path.empty?
151
+ always{yield}
152
+ else
153
+ @remaining_path = rp
154
+ nil
155
+ end
156
+ end
157
+ when Class
158
+ if matcher == String
159
+ rp = @remaining_path
160
+ if rp.getbyte(0) == 47 && !rp.index('/', 1) && (len = rp.length) > 1
161
+ @remaining_path = ''
162
+ always{yield rp[1, len]}
163
+ end
164
+ elsif matcher == Integer
165
+ rp = @remaining_path
166
+ if /\A\/(\d{1,100})\z/.match?(rp) && (value = scope.send(:_convert_class_Integer, rp[1, 101]))
167
+ @remaining_path = ''
168
+ always{yield(value)}
169
+ end
170
+ else
171
+ path = @remaining_path
172
+ captures = @captures.clear
173
+ meth = :"_match_class_#{matcher}"
174
+ if respond_to?(meth, true)
175
+ # Allow calling private methods, as match methods are generally private
176
+ if send(meth, &block) && @remaining_path.empty?
177
+ block_result(yield(*captures))
178
+ throw :halt, response.finish
179
+ else
180
+ @remaining_path = path
181
+ false
182
+ end
183
+ else
184
+ unsupported_matcher(matcher)
185
+ end
186
+ end
187
+ when Regexp
188
+ if (matchdata = self.class.cached_matcher(matcher){matcher}.match(@remaining_path)) && matchdata.post_match.empty?
189
+ @remaining_path = ''
190
+ always{yield(*matchdata.captures)}
191
+ end
192
+ when true
193
+ always(&block) if @remaining_path.empty?
194
+ when false, nil
195
+ # nothing
196
+ else
197
+ path = @remaining_path
198
+ captures = @captures.clear
199
+
200
+ matched = case matcher
201
+ when Array
202
+ _match_array(matcher)
203
+ when Hash
204
+ _match_hash(matcher)
205
+ when Symbol
206
+ _match_symbol(matcher)
207
+ when Proc
208
+ matcher.call
209
+ else
210
+ unsupported_matcher(matcher)
211
+ end
212
+
213
+ if matched && @remaining_path.empty?
214
+ block_result(yield(*captures))
215
+ throw :halt, response.finish
216
+ else
217
+ @remaining_path = path
218
+ false
219
+ end
220
+ end
221
+ end
222
+ end
223
+ end
224
+
225
+ register_plugin(:_optimized_matching, OptimizedMatching)
226
+ end
227
+ end
@@ -0,0 +1,108 @@
1
+ # frozen-string-literal: true
2
+
3
+ #
4
+ class Roda
5
+ module RodaPlugins
6
+ module SymbolClassMatchers_
7
+ module ClassMethods
8
+ private
9
+
10
+ # Backend of symbol_matcher and class_matcher.
11
+ def _symbol_class_matcher(expected_class, obj, matcher, block, options=OPTS, &request_class_block)
12
+ unless obj.is_a?(expected_class)
13
+ raise RodaError, "Invalid type passed to class_matcher or symbol_matcher: #{matcher.inspect}"
14
+ end
15
+
16
+ if obj.is_a?(Symbol)
17
+ type = "symbol"
18
+ meth = :"match_symbol_#{obj}"
19
+ else
20
+ type = "class"
21
+ meth = :"_match_class_#{obj}"
22
+ end
23
+
24
+ case matcher
25
+ when Regexp
26
+ regexp = matcher
27
+ consume_regexp = self::RodaRequest.send(:consume_pattern, regexp)
28
+ when Symbol
29
+ unless opts[:symbol_matchers]
30
+ raise RodaError, "cannot provide Symbol matcher to class_matcher unless using symbol_matchers plugin: #{matcher.inspect}"
31
+ end
32
+
33
+ regexp, consume_regexp, convert_meth, consume_meth = opts[:symbol_matchers][matcher]
34
+
35
+ unless regexp
36
+ raise RodaError, "unregistered symbol matcher given to #{type}_matcher: #{matcher.inspect}"
37
+ end
38
+
39
+ block = _merge_matcher_blocks(type, obj, block, convert_meth)
40
+ when Class
41
+ unless opts[:class_matchers]
42
+ raise RodaError, "cannot provide Class matcher to symbol_matcher unless using class_matchers plugin: #{matcher.inspect}"
43
+ end
44
+
45
+ regexp, consume_regexp, convert_meth, consume_meth = opts[:class_matchers][matcher]
46
+ unless regexp
47
+ raise RodaError, "unregistered class matcher given to #{type}_matcher: #{matcher.inspect}"
48
+ end
49
+ block = _merge_matcher_blocks(type, obj, block, convert_meth)
50
+ else
51
+ raise RodaError, "unsupported matcher given to #{type}_matcher: #{matcher.inspect}"
52
+ end
53
+
54
+ if block.is_a?(Symbol)
55
+ convert_meth = block
56
+ elsif block
57
+ convert_meth = :"_convert_#{type}_#{obj}"
58
+ define_method(convert_meth, &block)
59
+ private convert_meth
60
+ end
61
+
62
+ consume_meth ||= options[:segment] ? :_consume_single_segment : :consume
63
+ array = opts[:"#{type}_matchers"][obj] = [regexp, consume_regexp, convert_meth, consume_meth].freeze
64
+
65
+ self::RodaRequest.class_eval do
66
+ class_exec(meth, array, &request_class_block)
67
+ private meth
68
+ end
69
+
70
+ nil
71
+ end
72
+
73
+ # If both block and convert_meth are given,
74
+ # define a method for block, and then return a
75
+ # proc that calls convert_meth first, and only calls
76
+ # the newly defined method with the return values of convert_meth
77
+ # if matcher_method returns a truthy value.
78
+ # Otherwise, return convert_meth or block.
79
+ def _merge_matcher_blocks(type, obj, block, convert_meth)
80
+ if convert_meth
81
+ if block
82
+ convert_merge_meth = :"_convert_merge_#{type}_#{obj}"
83
+ define_method(convert_merge_meth, &block)
84
+ private convert_merge_meth
85
+
86
+ proc do |*a|
87
+ if captures = send(convert_meth, *a)
88
+ if captures.is_a?(Array)
89
+ send(convert_merge_meth, *captures)
90
+ else
91
+ send(convert_merge_meth, captures)
92
+ end
93
+ end
94
+ end
95
+ else
96
+ convert_meth
97
+ end
98
+ else
99
+ block
100
+ end
101
+ end
102
+ end
103
+ end
104
+
105
+ register_plugin(:_symbol_class_matchers, SymbolClassMatchers_)
106
+ end
107
+ end
108
+
@@ -0,0 +1,24 @@
1
+ # frozen-string-literal: true
2
+
3
+ #
4
+ class Roda
5
+ module RodaPlugins
6
+ # The _symbol_regexp_matchers plugin is designed for internal use by other plugins,
7
+ # for the historical behavior of a symbol matching an arbitrary segment by default
8
+ # using a regexp.
9
+ module SymbolRegexpMatchers
10
+ module RequestMethods
11
+ private
12
+
13
+ # The regular expression to use for matching symbols. By default, any non-empty
14
+ # segment matches.
15
+ def _match_symbol_regexp(s)
16
+ "([^\\/]+)"
17
+ end
18
+ end
19
+ end
20
+
21
+ register_plugin(:_symbol_regexp_matchers, SymbolRegexpMatchers)
22
+ end
23
+ end
24
+
@@ -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