ultra-max-sys 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.

Potentially problematic release.


This version of ultra-max-sys might be problematic. Click here for more details.

Files changed (163) hide show
  1. checksums.yaml +7 -0
  2. data/roda-3.106.0/MIT-LICENSE +21 -0
  3. data/roda-3.106.0/lib/roda/cache.rb +42 -0
  4. data/roda-3.106.0/lib/roda/plugins/Integer_matcher_max.rb +55 -0
  5. data/roda-3.106.0/lib/roda/plugins/_after_hook.rb +11 -0
  6. data/roda-3.106.0/lib/roda/plugins/_base64.rb +34 -0
  7. data/roda-3.106.0/lib/roda/plugins/_before_hook.rb +41 -0
  8. data/roda-3.106.0/lib/roda/plugins/_optimized_matching.rb +227 -0
  9. data/roda-3.106.0/lib/roda/plugins/_symbol_class_matchers.rb +108 -0
  10. data/roda-3.106.0/lib/roda/plugins/_symbol_regexp_matchers.rb +24 -0
  11. data/roda-3.106.0/lib/roda/plugins/additional_render_engines.rb +61 -0
  12. data/roda-3.106.0/lib/roda/plugins/additional_view_directories.rb +66 -0
  13. data/roda-3.106.0/lib/roda/plugins/all_verbs.rb +50 -0
  14. data/roda-3.106.0/lib/roda/plugins/assets.rb +902 -0
  15. data/roda-3.106.0/lib/roda/plugins/assets_preloading.rb +89 -0
  16. data/roda-3.106.0/lib/roda/plugins/assume_ssl.rb +28 -0
  17. data/roda-3.106.0/lib/roda/plugins/autoload_hash_branches.rb +79 -0
  18. data/roda-3.106.0/lib/roda/plugins/autoload_named_routes.rb +65 -0
  19. data/roda-3.106.0/lib/roda/plugins/backtracking_array.rb +88 -0
  20. data/roda-3.106.0/lib/roda/plugins/bearer_token.rb +28 -0
  21. data/roda-3.106.0/lib/roda/plugins/branch_locals.rb +76 -0
  22. data/roda-3.106.0/lib/roda/plugins/break.rb +43 -0
  23. data/roda-3.106.0/lib/roda/plugins/caching.rb +206 -0
  24. data/roda-3.106.0/lib/roda/plugins/capture_erb.rb +94 -0
  25. data/roda-3.106.0/lib/roda/plugins/chunked.rb +333 -0
  26. data/roda-3.106.0/lib/roda/plugins/class_level_routing.rb +111 -0
  27. data/roda-3.106.0/lib/roda/plugins/class_matchers.rb +155 -0
  28. data/roda-3.106.0/lib/roda/plugins/common_logger.rb +82 -0
  29. data/roda-3.106.0/lib/roda/plugins/conditional_sessions.rb +67 -0
  30. data/roda-3.106.0/lib/roda/plugins/content_for.rb +105 -0
  31. data/roda-3.106.0/lib/roda/plugins/content_security_policy.rb +333 -0
  32. data/roda-3.106.0/lib/roda/plugins/cookie_flags.rb +157 -0
  33. data/roda-3.106.0/lib/roda/plugins/cookies.rb +51 -0
  34. data/roda-3.106.0/lib/roda/plugins/csrf.rb +81 -0
  35. data/roda-3.106.0/lib/roda/plugins/custom_block_results.rb +85 -0
  36. data/roda-3.106.0/lib/roda/plugins/custom_matchers.rb +89 -0
  37. data/roda-3.106.0/lib/roda/plugins/default_headers.rb +64 -0
  38. data/roda-3.106.0/lib/roda/plugins/default_status.rb +35 -0
  39. data/roda-3.106.0/lib/roda/plugins/delay_build.rb +18 -0
  40. data/roda-3.106.0/lib/roda/plugins/delegate.rb +77 -0
  41. data/roda-3.106.0/lib/roda/plugins/delete_empty_headers.rb +36 -0
  42. data/roda-3.106.0/lib/roda/plugins/direct_call.rb +38 -0
  43. data/roda-3.106.0/lib/roda/plugins/disallow_file_uploads.rb +38 -0
  44. data/roda-3.106.0/lib/roda/plugins/drop_body.rb +43 -0
  45. data/roda-3.106.0/lib/roda/plugins/each_part.rb +87 -0
  46. data/roda-3.106.0/lib/roda/plugins/early_hints.rb +25 -0
  47. data/roda-3.106.0/lib/roda/plugins/empty_root.rb +49 -0
  48. data/roda-3.106.0/lib/roda/plugins/environments.rb +79 -0
  49. data/roda-3.106.0/lib/roda/plugins/erb_h.rb +43 -0
  50. data/roda-3.106.0/lib/roda/plugins/error_email.rb +152 -0
  51. data/roda-3.106.0/lib/roda/plugins/error_handler.rb +133 -0
  52. data/roda-3.106.0/lib/roda/plugins/error_mail.rb +149 -0
  53. data/roda-3.106.0/lib/roda/plugins/exception_page.rb +445 -0
  54. data/roda-3.106.0/lib/roda/plugins/filter_common_logger.rb +46 -0
  55. data/roda-3.106.0/lib/roda/plugins/flash.rb +119 -0
  56. data/roda-3.106.0/lib/roda/plugins/h.rb +59 -0
  57. data/roda-3.106.0/lib/roda/plugins/halt.rb +108 -0
  58. data/roda-3.106.0/lib/roda/plugins/hash_branch_view_subdir.rb +76 -0
  59. data/roda-3.106.0/lib/roda/plugins/hash_branches.rb +145 -0
  60. data/roda-3.106.0/lib/roda/plugins/hash_matcher.rb +39 -0
  61. data/roda-3.106.0/lib/roda/plugins/hash_paths.rb +128 -0
  62. data/roda-3.106.0/lib/roda/plugins/hash_public.rb +125 -0
  63. data/roda-3.106.0/lib/roda/plugins/hash_public_cache.rb +91 -0
  64. data/roda-3.106.0/lib/roda/plugins/hash_routes.rb +304 -0
  65. data/roda-3.106.0/lib/roda/plugins/head.rb +99 -0
  66. data/roda-3.106.0/lib/roda/plugins/header_matchers.rb +88 -0
  67. data/roda-3.106.0/lib/roda/plugins/heartbeat.rb +41 -0
  68. data/roda-3.106.0/lib/roda/plugins/hmac_paths.rb +413 -0
  69. data/roda-3.106.0/lib/roda/plugins/hooks.rb +92 -0
  70. data/roda-3.106.0/lib/roda/plugins/host_authorization.rb +155 -0
  71. data/roda-3.106.0/lib/roda/plugins/host_routing.rb +194 -0
  72. data/roda-3.106.0/lib/roda/plugins/hsts.rb +35 -0
  73. data/roda-3.106.0/lib/roda/plugins/indifferent_params.rb +126 -0
  74. data/roda-3.106.0/lib/roda/plugins/inject_erb.rb +33 -0
  75. data/roda-3.106.0/lib/roda/plugins/invalid_request_body.rb +107 -0
  76. data/roda-3.106.0/lib/roda/plugins/ip_from_header.rb +34 -0
  77. data/roda-3.106.0/lib/roda/plugins/json.rb +119 -0
  78. data/roda-3.106.0/lib/roda/plugins/json_parser.rb +107 -0
  79. data/roda-3.106.0/lib/roda/plugins/link_to.rb +83 -0
  80. data/roda-3.106.0/lib/roda/plugins/mail_processor.rb +629 -0
  81. data/roda-3.106.0/lib/roda/plugins/mailer.rb +285 -0
  82. data/roda-3.106.0/lib/roda/plugins/map_matcher.rb +48 -0
  83. data/roda-3.106.0/lib/roda/plugins/match_affix.rb +64 -0
  84. data/roda-3.106.0/lib/roda/plugins/match_hook.rb +34 -0
  85. data/roda-3.106.0/lib/roda/plugins/match_hook_args.rb +93 -0
  86. data/roda-3.106.0/lib/roda/plugins/middleware.rb +225 -0
  87. data/roda-3.106.0/lib/roda/plugins/middleware_stack.rb +101 -0
  88. data/roda-3.106.0/lib/roda/plugins/module_include.rb +96 -0
  89. data/roda-3.106.0/lib/roda/plugins/multi_public.rb +95 -0
  90. data/roda-3.106.0/lib/roda/plugins/multi_route.rb +156 -0
  91. data/roda-3.106.0/lib/roda/plugins/multi_run.rb +144 -0
  92. data/roda-3.106.0/lib/roda/plugins/multi_view.rb +83 -0
  93. data/roda-3.106.0/lib/roda/plugins/multibyte_string_matcher.rb +57 -0
  94. data/roda-3.106.0/lib/roda/plugins/named_routes.rb +167 -0
  95. data/roda-3.106.0/lib/roda/plugins/named_templates.rb +102 -0
  96. data/roda-3.106.0/lib/roda/plugins/not_allowed.rb +151 -0
  97. data/roda-3.106.0/lib/roda/plugins/not_found.rb +55 -0
  98. data/roda-3.106.0/lib/roda/plugins/optimized_segment_matchers.rb +53 -0
  99. data/roda-3.106.0/lib/roda/plugins/optimized_string_matchers.rb +50 -0
  100. data/roda-3.106.0/lib/roda/plugins/padrino_render.rb +42 -0
  101. data/roda-3.106.0/lib/roda/plugins/param_matchers.rb +83 -0
  102. data/roda-3.106.0/lib/roda/plugins/params_capturing.rb +118 -0
  103. data/roda-3.106.0/lib/roda/plugins/part.rb +76 -0
  104. data/roda-3.106.0/lib/roda/plugins/partials.rb +74 -0
  105. data/roda-3.106.0/lib/roda/plugins/pass.rb +47 -0
  106. data/roda-3.106.0/lib/roda/plugins/path.rb +255 -0
  107. data/roda-3.106.0/lib/roda/plugins/path_matchers.rb +54 -0
  108. data/roda-3.106.0/lib/roda/plugins/path_rewriter.rb +111 -0
  109. data/roda-3.106.0/lib/roda/plugins/permissions_policy.rb +340 -0
  110. data/roda-3.106.0/lib/roda/plugins/placeholder_string_matchers.rb +48 -0
  111. data/roda-3.106.0/lib/roda/plugins/plain_hash_response_headers.rb +32 -0
  112. data/roda-3.106.0/lib/roda/plugins/precompile_templates.rb +156 -0
  113. data/roda-3.106.0/lib/roda/plugins/public.rb +182 -0
  114. data/roda-3.106.0/lib/roda/plugins/r.rb +35 -0
  115. data/roda-3.106.0/lib/roda/plugins/recheck_precompiled_assets.rb +107 -0
  116. data/roda-3.106.0/lib/roda/plugins/redirect_http_to_https.rb +99 -0
  117. data/roda-3.106.0/lib/roda/plugins/redirect_path.rb +59 -0
  118. data/roda-3.106.0/lib/roda/plugins/relative_path.rb +76 -0
  119. data/roda-3.106.0/lib/roda/plugins/render.rb +998 -0
  120. data/roda-3.106.0/lib/roda/plugins/render_coverage.rb +105 -0
  121. data/roda-3.106.0/lib/roda/plugins/render_each.rb +224 -0
  122. data/roda-3.106.0/lib/roda/plugins/render_locals.rb +102 -0
  123. data/roda-3.106.0/lib/roda/plugins/request_aref.rb +77 -0
  124. data/roda-3.106.0/lib/roda/plugins/request_headers.rb +83 -0
  125. data/roda-3.106.0/lib/roda/plugins/response_attachment.rb +94 -0
  126. data/roda-3.106.0/lib/roda/plugins/response_content_type.rb +79 -0
  127. data/roda-3.106.0/lib/roda/plugins/response_request.rb +36 -0
  128. data/roda-3.106.0/lib/roda/plugins/route_block_args.rb +50 -0
  129. data/roda-3.106.0/lib/roda/plugins/route_csrf.rb +388 -0
  130. data/roda-3.106.0/lib/roda/plugins/run_append_slash.rb +51 -0
  131. data/roda-3.106.0/lib/roda/plugins/run_handler.rb +51 -0
  132. data/roda-3.106.0/lib/roda/plugins/run_require_slash.rb +46 -0
  133. data/roda-3.106.0/lib/roda/plugins/sec_fetch_site_csrf.rb +131 -0
  134. data/roda-3.106.0/lib/roda/plugins/send_file.rb +127 -0
  135. data/roda-3.106.0/lib/roda/plugins/sessions.rb +537 -0
  136. data/roda-3.106.0/lib/roda/plugins/shape_friendly.rb +232 -0
  137. data/roda-3.106.0/lib/roda/plugins/shared_vars.rb +86 -0
  138. data/roda-3.106.0/lib/roda/plugins/sinatra_helpers.rb +444 -0
  139. data/roda-3.106.0/lib/roda/plugins/slash_path_empty.rb +26 -0
  140. data/roda-3.106.0/lib/roda/plugins/static.rb +42 -0
  141. data/roda-3.106.0/lib/roda/plugins/static_routing.rb +89 -0
  142. data/roda-3.106.0/lib/roda/plugins/status_303.rb +34 -0
  143. data/roda-3.106.0/lib/roda/plugins/status_handler.rb +86 -0
  144. data/roda-3.106.0/lib/roda/plugins/streaming.rb +170 -0
  145. data/roda-3.106.0/lib/roda/plugins/strip_path_prefix.rb +33 -0
  146. data/roda-3.106.0/lib/roda/plugins/symbol_matchers.rb +188 -0
  147. data/roda-3.106.0/lib/roda/plugins/symbol_status.rb +32 -0
  148. data/roda-3.106.0/lib/roda/plugins/symbol_views.rb +37 -0
  149. data/roda-3.106.0/lib/roda/plugins/timestamp_public.rb +78 -0
  150. data/roda-3.106.0/lib/roda/plugins/type_routing.rb +217 -0
  151. data/roda-3.106.0/lib/roda/plugins/typecast_params.rb +1185 -0
  152. data/roda-3.106.0/lib/roda/plugins/typecast_params_sized_integers.rb +108 -0
  153. data/roda-3.106.0/lib/roda/plugins/unescape_path.rb +41 -0
  154. data/roda-3.106.0/lib/roda/plugins/view_options.rb +203 -0
  155. data/roda-3.106.0/lib/roda/plugins/view_subdir_leading_slash.rb +49 -0
  156. data/roda-3.106.0/lib/roda/plugins.rb +68 -0
  157. data/roda-3.106.0/lib/roda/request.rb +722 -0
  158. data/roda-3.106.0/lib/roda/response.rb +221 -0
  159. data/roda-3.106.0/lib/roda/session_middleware.rb +184 -0
  160. data/roda-3.106.0/lib/roda/version.rb +18 -0
  161. data/roda-3.106.0/lib/roda.rb +741 -0
  162. data/ultra-max-sys.gemspec +12 -0
  163. metadata +202 -0
@@ -0,0 +1,91 @@
1
+ # frozen-string-literal: true
2
+
3
+ require 'json'
4
+ require 'find'
5
+
6
+ class Roda
7
+ module RodaPlugins
8
+ # The hash_public_cache plugin builds on top of the hash_public plugin and
9
+ # adds the ability to store the digests for the public files in a json file,
10
+ # and load that file at startup, which avoids the need for the process to
11
+ # read the public file in order to compute the digest.
12
+ #
13
+ # Examples:
14
+ #
15
+ # # Load the plugin. Options given will be passed to public and hash_public.
16
+ # plugin :hash_public_cache, "path/to/cache_file.json"
17
+ #
18
+ # # When rebuilding the cache:
19
+ # #
20
+ # # * Scan the public directory for files, calculate the digest on each.
21
+ # # * Write the hash public cache to a file.
22
+ # #
23
+ # # This is split into separate steps in case you want to modify the cache
24
+ # # manually after the scan.
25
+ # scan_hash_public_cache_dir
26
+ # dump_hash_public_cache_file
27
+ #
28
+ # # To load the cache at application startup (if the file exists):
29
+ # load_hash_public_cache_file
30
+ module HashPublicCache
31
+ def self.load_dependencies(app, _cache_file, opts = OPTS)
32
+ app.plugin :hash_public, opts
33
+ end
34
+
35
+ # Specify the location of the hash public cache file.
36
+ #
37
+ # The options given are passed to the hash_public plugin.
38
+ def self.configure(app, cache_file, opts = OPTS)
39
+ app.opts[:hash_public_cache_file] = cache_file
40
+ end
41
+
42
+ module ClassMethods
43
+ # Load the hash public cache file, if it exists. This replaces the hash
44
+ # public cache with the values from the file.
45
+ def load_hash_public_cache_file
46
+ file = opts[:hash_public_cache_file]
47
+ return unless File.file?(file)
48
+
49
+ cache = opts[:hash_public_cache] = (opts[:json_parser] || ::JSON.method(:parse)).call(::File.read(file))
50
+ cache.each_value(&:freeze)
51
+ nil
52
+ end
53
+
54
+ # Scan the public directory for files, computing the hash public digest
55
+ # for each. This will not rescan files that already have digest values.
56
+ # If a block is given, it will only calculate the digest for the file
57
+ # if the block returns truthy.
58
+ def scan_hash_public_cache_dir
59
+ cache = opts[:hash_public_cache]
60
+
61
+ # Public root doesn't have trailing slash even if given, as
62
+ # File.expand_path removes it.
63
+ root = opts[:public_root] + File::SEPARATOR
64
+
65
+ Find.find(opts[:public_root]) do |file|
66
+ if File.file?(file)
67
+ file = file.sub(root, '')
68
+ next if cache[file]
69
+
70
+ if defined?(yield)
71
+ next unless yield file
72
+ end
73
+
74
+ cache[file] = hash_path_digest(file)
75
+ end
76
+ end
77
+
78
+ nil
79
+ end
80
+
81
+ # Write the current hash public cache to the cache file.
82
+ def dump_hash_public_cache_file
83
+ File.write(opts[:hash_public_cache_file], (opts[:json_serializer] || :to_json.to_proc).call(opts[:hash_public_cache]))
84
+ nil
85
+ end
86
+ end
87
+ end
88
+
89
+ register_plugin(:hash_public_cache, HashPublicCache)
90
+ end
91
+ end
@@ -0,0 +1,304 @@
1
+ # frozen-string-literal: true
2
+
3
+ #
4
+ class Roda
5
+ module RodaPlugins
6
+ # The hash_routes plugin builds on top of the hash_branches and hash_paths plugins, and adds
7
+ # a DSL for configuring hash branches and paths. It also adds an +r.hash_routes+ method for
8
+ # first attempting dispatch to the configured hash_paths, then to the configured hash_branches:
9
+ #
10
+ # class App < Roda
11
+ # plugin :hash_routes
12
+ #
13
+ # hash_branch("a") do |r|
14
+ # # /a branch
15
+ # end
16
+ #
17
+ # hash_branch("b") do |r|
18
+ # # /b branch
19
+ # end
20
+ #
21
+ # hash_path("/a") do |r|
22
+ # # /a path
23
+ # end
24
+ #
25
+ # hash_path("/a/b") do |r|
26
+ # # /a/b path
27
+ # end
28
+ #
29
+ # route do |r|
30
+ # r.hash_routes
31
+ # end
32
+ # end
33
+ #
34
+ # With the above routing tree, requests for +/a+ and +/a/b+ will be routed to the appropriate
35
+ # +hash_path+ block. Other requests for the +/a+ branch, and all requests for the +/b+
36
+ # branch will be routed to the appropriate +hash_branch+ block.
37
+ #
38
+ # It is best for performance to explicitly specify the namespace when calling
39
+ # +r.hash_routes+.
40
+ #
41
+ # Because specifying routes explicitly using the +hash_branch+ and +hash_path+
42
+ # class methods can get repetitive, the hash_routes plugin offers a DSL for DRYing
43
+ # the code up. This DSL is used by calling the +hash_routes+ class method. The
44
+ # DSL used tries to mirror the standard Roda DSL, but it is not a normal routing
45
+ # tree (it's not possible to execute arbitrary code between branches during routing).
46
+ #
47
+ # class App < Roda
48
+ # plugin :hash_routes
49
+ #
50
+ # # No block argument is used, DSL evaluates block using instance_exec
51
+ # hash_routes "" do
52
+ # # on method is used for routing to next segment,
53
+ # # for similarity to standard Roda
54
+ # on "a" do |r|
55
+ # r.hash_routes '/a'
56
+ # end
57
+ #
58
+ # on "b" do |r|
59
+ # r.hash_routes(:b)
60
+ # end
61
+ # end
62
+ #
63
+ # # Block argument is used, block is yielded DSL instance
64
+ # hash_routes "/a" do |hr|
65
+ # # is method is used for routing to the remaining path,
66
+ # # for similarity to standard Roda
67
+ # hr.is "b" do |r|
68
+ # # /a/b path
69
+ # end
70
+ #
71
+ # hr.is "c" do |r|
72
+ # # /a/c path
73
+ # end
74
+ # end
75
+ #
76
+ # hash_routes :b do
77
+ # is "b" do |r|
78
+ # # /b/b path
79
+ # end
80
+ #
81
+ # is "c" do |r|
82
+ # # /b/c path
83
+ # end
84
+ # end
85
+ #
86
+ # route do |r|
87
+ # # No change here, DSL only makes setup DRYer
88
+ # r.hash_branches
89
+ # end
90
+ # end
91
+ #
92
+ # The +hash_routes+ DSL also offers some additional features to handle additional
93
+ # cases. It supports verb methods, such as +get+ and +post+, which operate like
94
+ # +is+, but are only called if the verb matches (and are not yielded the request).
95
+ # It supports a +view+ method for routes that only render views, as well as a
96
+ # +views+ method for setting up routes for multiple views in a single call, which
97
+ # is a good replacement for the +multi_view+ plugin.
98
+ # +is+, +view+, and the verb methods can use a value of +true+ for the empty
99
+ # remaining path (as the empty string specifies the <tt>"/"</tt> remaining path).
100
+ # It also supports a +dispatch_from+ method, allowing you to setup dispatching to
101
+ # current group of routes from a higher-level namespace.
102
+ # The +hash_routes+ class method will return the DSL instance, so you are not
103
+ # limited to using it with a block.
104
+ #
105
+ # Here's the above example modified to use some of these features:
106
+ #
107
+ # class App < Roda
108
+ # plugin :hash_routes
109
+ #
110
+ # hash_routes "/a" do
111
+ # # Dispatch requests for the /a branch from the empty (default) routing
112
+ # # namespace to this namespace
113
+ # dispatch_from "a"
114
+ #
115
+ # # Handle GET /a path, render "a" template, returning 404 for non-GET requests
116
+ # view true, "a"
117
+ #
118
+ # # Handle /a/b path, returning 404 for non-GET requests
119
+ # get "b" do
120
+ # # GET /a/b path
121
+ # end
122
+ #
123
+ # # Handle /a/c path, returning 404 for non-POST requests
124
+ # post "c" do
125
+ # # POST /a/c path
126
+ # end
127
+ # end
128
+ #
129
+ # bhr = hash_routes(:b)
130
+ #
131
+ # # Dispatch requests for the /b branch from the empty routing to this namespace,
132
+ # # but first check routes in the :b_preauth namespace. If there is no
133
+ # # matching route in the :b_preauth namespace, call the check_authenticated!
134
+ # # method before dispatching to any of the routes in this namespace
135
+ # bhr.dispatch_from "", "b" do |r|
136
+ # r.hash_routes :b_preauth
137
+ # check_authenticated!
138
+ # end
139
+ #
140
+ # bhr.is true do |r|
141
+ # # /b path
142
+ # end
143
+ #
144
+ # bhr.is "" do |r|
145
+ # # /b/ path
146
+ # end
147
+ #
148
+ # # GET /b/d path, render 'd2' template, returning 404 for non-GET requests
149
+ # bhr.views 'd', 'd2'
150
+ #
151
+ # # GET /b/e path, render 'e' template, returning 404 for non-GET requests
152
+ # # GET /b/f path, render 'f' template, returning 404 for non-GET requests
153
+ # bhr.views %w'e f'
154
+ #
155
+ # route do |r|
156
+ # r.hash_branches
157
+ # end
158
+ # end
159
+ #
160
+ # The +view+ and +views+ method depend on the render plugin being loaded, but this
161
+ # plugin does not load the render plugin. You must load the render plugin separately
162
+ # if you want to use the +view+ and +views+ methods.
163
+ #
164
+ # Certain parts of the +hash_routes+ DSL support do not work with the
165
+ # route_block_args plugin, as doing so would reduce performance. These are:
166
+ #
167
+ # * dispatch_from
168
+ # * view
169
+ # * views
170
+ # * all verb methods (get, post, etc.)
171
+ module HashRoutes
172
+ def self.load_dependencies(app)
173
+ app.plugin :hash_branches
174
+ app.plugin :hash_paths
175
+ end
176
+
177
+ def self.configure(app)
178
+ app.opts[:hash_routes_methods] ||= {}
179
+ end
180
+
181
+ # Internal class handling the internals of the +hash_routes+ class method blocks.
182
+ class DSL
183
+ def initialize(roda, namespace)
184
+ @roda = roda
185
+ @namespace = namespace
186
+ end
187
+
188
+ # Setup the given branch in the given namespace to dispatch to routes in this
189
+ # namespace. If a block is given, call the block with the request before
190
+ # dispatching to routes in this namespace.
191
+ def dispatch_from(namespace='', branch, &block)
192
+ ns = @namespace
193
+ if block
194
+ meth_hash = @roda.opts[:hash_routes_methods]
195
+ key = [:dispatch_from, namespace, branch].freeze
196
+ meth = meth_hash[key] = @roda.define_roda_method(meth_hash[key] || "hash_routes_dispatch_from_#{namespace}_#{branch}", 1, &block)
197
+ @roda.hash_branch(namespace, branch) do |r|
198
+ send(meth, r)
199
+ r.hash_routes(ns)
200
+ end
201
+ else
202
+ @roda.hash_branch(namespace, branch) do |r|
203
+ r.hash_routes(ns)
204
+ end
205
+ end
206
+ end
207
+
208
+ # Use the segment to setup a branch in the current namespace.
209
+ def on(segment, &block)
210
+ @roda.hash_branch(@namespace, segment, &block)
211
+ end
212
+
213
+ # Use the segment to setup a path in the current namespace.
214
+ # If path is given as a string, it is prefixed with a slash.
215
+ # If path is +true+, the empty string is used as the path.
216
+ def is(path, &block)
217
+ path = path == true ? "" : "/#{path}"
218
+ @roda.hash_path(@namespace, path, &block)
219
+ end
220
+
221
+ # Use the segment to setup a path in the current namespace that
222
+ # will render the view with the given name if the GET method is
223
+ # used, and will return a 404 if another request method is used.
224
+ # If path is given as a string, it is prefixed with a slash.
225
+ # If path is +true+, the empty string is used as the path.
226
+ def view(path, template)
227
+ path = path == true ? "" : "/#{path}"
228
+ @roda.hash_path(@namespace, path) do |r|
229
+ r.get do
230
+ view(template)
231
+ end
232
+ end
233
+ end
234
+
235
+ # For each template in the array of templates, setup a path in
236
+ # the current namespace for the template using the same name
237
+ # as the template.
238
+ def views(templates)
239
+ templates.each do |template|
240
+ view(template, template)
241
+ end
242
+ end
243
+
244
+ [:get, :post, :delete, :head, :options, :link, :patch, :put, :trace, :unlink].each do |meth|
245
+ define_method(meth) do |path, &block|
246
+ verb(meth, path, &block)
247
+ end
248
+ end
249
+
250
+ private
251
+
252
+ # Setup a path in the current namespace for the given request method verb.
253
+ # Returns 404 for requests for the path with a different request method.
254
+ def verb(verb, path, &block)
255
+ path = path == true ? "" : "/#{path}"
256
+ meth_hash = @roda.opts[:hash_routes_methods]
257
+ key = [@namespace, path].freeze
258
+ meth = meth_hash[key] = @roda.define_roda_method(meth_hash[key] || "hash_routes_#{@namespace}_#{path}", 0, &block)
259
+ @roda.hash_path(@namespace, path) do |r|
260
+ r.send(verb) do
261
+ send(meth)
262
+ end
263
+ end
264
+ end
265
+ end
266
+
267
+ module ClassMethods
268
+ # Freeze the hash_routes metadata when freezing the app.
269
+ def freeze
270
+ opts[:hash_routes_methods].freeze
271
+ super
272
+ end
273
+
274
+ # Invoke the DSL for configuring hash routes, see DSL for methods inside the
275
+ # block. If the block accepts an argument, yield the DSL instance. If the
276
+ # block does not accept an argument, instance_exec the block in the context
277
+ # of the DSL instance.
278
+ def hash_routes(namespace='', &block)
279
+ dsl = DSL.new(self, namespace)
280
+ if block
281
+ if block.arity == 1
282
+ yield dsl
283
+ else
284
+ dsl.instance_exec(&block)
285
+ end
286
+ end
287
+
288
+ dsl
289
+ end
290
+ end
291
+
292
+ module RequestMethods
293
+ # Check for matches in both the hash_path and hash_branch namespaces for
294
+ # a matching remaining path or next segment in the remaining path, respectively.
295
+ def hash_routes(namespace=matched_path)
296
+ hash_paths(namespace)
297
+ hash_branches(namespace)
298
+ end
299
+ end
300
+ end
301
+
302
+ register_plugin(:hash_routes, HashRoutes)
303
+ end
304
+ end
@@ -0,0 +1,99 @@
1
+ # frozen-string-literal: true
2
+
3
+ #
4
+ class Roda
5
+ module RodaPlugins
6
+ # The head plugin attempts to automatically handle HEAD requests,
7
+ # by treating them as GET requests and returning an empty body
8
+ # without modifying the response status or response headers.
9
+ #
10
+ # So for the following routes,
11
+ #
12
+ # route do |r|
13
+ # r.root do
14
+ # 'root'
15
+ # end
16
+ #
17
+ # r.get 'a' do
18
+ # 'a'
19
+ # end
20
+ #
21
+ # r.is 'b', method: [:get, :post] do
22
+ # 'b'
23
+ # end
24
+ # end
25
+ #
26
+ # HEAD requests for +/+, +/a+, and +/b+ will all return 200 status
27
+ # with an empty body.
28
+ #
29
+ # This plugin also works with the not_allowed plugin if it is loaded
30
+ # after the not_allowed plugin. In that case, if GET is one of Allow
31
+ # header options, then HEAD will be as well.
32
+ #
33
+ # NOTE: if you have a public facing website it is recommended that
34
+ # you enable this plugin, or manually handle HEAD anywhere you would
35
+ # handle GET. Search engines and other bots may send a
36
+ # HEAD request prior to crawling a page with a GET request. Without
37
+ # this plugin those HEAD requests will return a 404 status, which
38
+ # may prevent search engines from crawling your website.
39
+ module Head
40
+ # used to ensure proper resource release on HEAD requests
41
+ # we do not respond to a to_path method, here.
42
+ class CloseLater
43
+ def initialize(body)
44
+ @body = body
45
+ end
46
+
47
+ # yield nothing
48
+ def each(&_)
49
+ end
50
+
51
+ # this should be called by the Rack server
52
+ def close
53
+ @body.close
54
+ end
55
+ end
56
+
57
+ module InstanceMethods
58
+ private
59
+
60
+ # Always use an empty response body for head requests, with a
61
+ # content length of 0.
62
+ def _roda_after_30__head(res)
63
+ if res && @_request.head?
64
+ body = res[2]
65
+ if body.respond_to?(:close)
66
+ res[2] = CloseLater.new(body)
67
+ else
68
+ res[2] = EMPTY_ARRAY
69
+ end
70
+ end
71
+ end
72
+ end
73
+
74
+ module RequestMethods
75
+ # Consider HEAD requests as GET requests.
76
+ def is_get?
77
+ super || head?
78
+ end
79
+
80
+ private
81
+
82
+ # If the current request is a HEAD request, match if one of
83
+ # the given methods is a GET request.
84
+ def match_method(method)
85
+ super || (!method.is_a?(Array) && head? && method.to_s.upcase == 'GET')
86
+ end
87
+
88
+ # Work with the not_allowed plugin so that if GET is one
89
+ # of the Allow header options, then HEAD is as well.
90
+ def method_not_allowed(verbs)
91
+ verbs = verbs.sub('GET', 'HEAD, GET')
92
+ super
93
+ end
94
+ end
95
+ end
96
+
97
+ register_plugin(:head, Head)
98
+ end
99
+ end
@@ -0,0 +1,88 @@
1
+ # frozen-string-literal: true
2
+
3
+ #
4
+ class Roda
5
+ module RodaPlugins
6
+ # The header_matchers plugin adds hash matchers for matching on less-common
7
+ # HTTP headers.
8
+ #
9
+ # plugin :header_matchers
10
+ #
11
+ # It adds a +:header+ matcher for matching on arbitrary headers, which matches
12
+ # if the header is present, and yields the header value:
13
+ #
14
+ # r.on header: 'HTTP-X-App-Token' do |header_value|
15
+ # # Looks for env['HTTP_X_APP_TOKEN'] and yields it
16
+ # end
17
+ #
18
+ # It adds a +:host+ matcher for matching by the host of the request:
19
+ #
20
+ # r.on host: 'foo.example.com' do
21
+ # end
22
+ #
23
+ # For regexp values of the +:host+ matcher, any captures are yielded to the block:
24
+ #
25
+ # r.on host: /\A(\w+).example.com\z/ do |subdomain|
26
+ # end
27
+ #
28
+ # It adds a +:user_agent+ matcher for matching on a user agent patterns, which
29
+ # yields the regexp captures to the block:
30
+ #
31
+ # r.on user_agent: /Chrome\/([.\d]+)/ do |chrome_version|
32
+ # end
33
+ #
34
+ # It adds an +:accept+ matcher for matching based on the Accept header:
35
+ #
36
+ # r.on accept: 'text/csv' do
37
+ # end
38
+ #
39
+ # Note that the +:accept+ matcher is very simple and cannot handle wildcards,
40
+ # priorities, or anything but a simple comma separated list of mime types.
41
+ module HeaderMatchers
42
+ module RequestMethods
43
+ private
44
+
45
+ # Match if the given mimetype is one of the accepted mimetypes.
46
+ def match_accept(mimetype)
47
+ if @env["HTTP_ACCEPT"].to_s.split(',').any?{|s| s.strip == mimetype}
48
+ response[RodaResponseHeaders::CONTENT_TYPE] = mimetype
49
+ end
50
+ end
51
+
52
+ # Match if the given uppercase key is present inside the environment.
53
+ def match_header(key)
54
+ key = key.upcase
55
+ key.tr!("-","_")
56
+ unless key == "CONTENT_TYPE" || key == "CONTENT_LENGTH"
57
+ key = "HTTP_#{key}"
58
+ end
59
+ if v = @env[key]
60
+ @captures << v
61
+ end
62
+ end
63
+
64
+ # Match if the host of the request is the same as the hostname. +hostname+
65
+ # can be a regexp or a string.
66
+ def match_host(hostname)
67
+ if hostname.is_a?(Regexp)
68
+ if match = hostname.match(host)
69
+ @captures.concat(match.captures)
70
+ end
71
+ else
72
+ hostname === host
73
+ end
74
+ end
75
+
76
+ # Match the submitted user agent to the given pattern, capturing any
77
+ # regexp match groups.
78
+ def match_user_agent(pattern)
79
+ if (user_agent = @env["HTTP_USER_AGENT"]) && (match = pattern.match(user_agent))
80
+ @captures.concat(match.captures)
81
+ end
82
+ end
83
+ end
84
+ end
85
+
86
+ register_plugin(:header_matchers, HeaderMatchers)
87
+ end
88
+ end
@@ -0,0 +1,41 @@
1
+ # frozen-string-literal: true
2
+
3
+ #
4
+ class Roda
5
+ module RodaPlugins
6
+ # The heartbeat handles heartbeat/status requests. If a request for
7
+ # the heartbeat path comes in, a 200 response with a
8
+ # text/plain Content-Type and a body of "OK" will be returned.
9
+ # The default heartbeat path is "/heartbeat", so to use that:
10
+ #
11
+ # plugin :heartbeat
12
+ #
13
+ # You can also specify a custom heartbeat path:
14
+ #
15
+ # plugin :heartbeat, path: '/status'
16
+ module Heartbeat
17
+ # Set the heartbeat path to the given path.
18
+ def self.configure(app, opts=OPTS)
19
+ app.opts[:heartbeat_path] = (opts[:path] || app.opts[:heartbeat_path] || "/heartbeat").dup.freeze
20
+ end
21
+
22
+ module InstanceMethods
23
+ private
24
+
25
+ # If the request is for a heartbeat path, return the heartbeat response.
26
+ def _roda_before_20__heartbeat
27
+ if env['PATH_INFO'] == opts[:heartbeat_path]
28
+ response = @_response
29
+ response.status = 200
30
+ response[RodaResponseHeaders::CONTENT_TYPE] = 'text/plain'
31
+ response.write 'OK'
32
+ throw :halt, response.finish
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ register_plugin(:heartbeat, Heartbeat)
39
+ end
40
+ end
41
+