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
@@ -0,0 +1,586 @@
1
+ # frozen-string-literal: true
2
+
3
+ require "thread"
4
+ require_relative "roda/request"
5
+ require_relative "roda/response"
6
+ require_relative "roda/plugins"
7
+ require_relative "roda/cache"
8
+ require_relative "roda/version"
9
+
10
+ # The main class for Roda. Roda is built completely out of plugins, with the
11
+ # default plugin being Roda::RodaPlugins::Base, so this class is mostly empty
12
+ # except for some constants.
13
+ class Roda
14
+ # Error class raised by Roda
15
+ class RodaError < StandardError; end
16
+
17
+ @app = nil
18
+ @inherit_middleware = true
19
+ @middleware = []
20
+ @opts = {}
21
+ @raw_route_block = nil
22
+ @route_block = nil
23
+ @rack_app_route_block = nil
24
+
25
+ module RodaPlugins
26
+ # The base plugin for Roda, implementing all default functionality.
27
+ # Methods are put into a plugin so future plugins can easily override
28
+ # them and call super to get the default behavior.
29
+ module Base
30
+ # Class methods for the Roda class.
31
+ module ClassMethods
32
+ # The rack application that this class uses.
33
+ def app
34
+ @app || build_rack_app
35
+ end
36
+
37
+ # Whether middleware from the current class should be inherited by subclasses.
38
+ # True by default, should be set to false when using a design where the parent
39
+ # class accepts requests and uses run to dispatch the request to a subclass.
40
+ attr_accessor :inherit_middleware
41
+
42
+ # The settings/options hash for the current class.
43
+ attr_reader :opts
44
+
45
+ # The route block that this class uses.
46
+ attr_reader :route_block
47
+
48
+ # Call the internal rack application with the given environment.
49
+ # This allows the class itself to be used as a rack application.
50
+ # However, for performance, it's better to use #app to get direct
51
+ # access to the underlying rack app.
52
+ def call(env)
53
+ app.call(env)
54
+ end
55
+
56
+ # Clear the middleware stack
57
+ def clear_middleware!
58
+ @middleware.clear
59
+ @app = nil
60
+ end
61
+
62
+ # Define an instance method using the block with the provided name and
63
+ # expected arity. If the name is given as a Symbol, it is used directly.
64
+ # If the name is given as a String, a unique name will be generated using
65
+ # that string. The expected arity should be either 0 (no arguments),
66
+ # 1 (single argument), or :any (any number of arguments).
67
+ #
68
+ # If the :check_arity app option is not set to false, Roda will check that
69
+ # the arity of the block matches the expected arity, and compensate for
70
+ # cases where it does not. If it is set to :warn, Roda will warn in the
71
+ # cases where the arity does not match what is expected.
72
+ #
73
+ # If the expected arity is :any, Roda must perform a dynamic arity check
74
+ # when the method is called, which can hurt performance even in the case
75
+ # where the arity matches. The :check_dynamic_arity app option can be
76
+ # set to false to turn off the dynamic arity checks. The
77
+ # :check_dynamic_arity app option can be to :warn to warn if Roda needs
78
+ # to adjust arity dynamically.
79
+ #
80
+ # Roda only checks arity for regular blocks, not lambda blocks, as the
81
+ # fixes Roda uses for regular blocks would not work for lambda blocks.
82
+ #
83
+ # Roda does not support blocks with required keyword arguments if the
84
+ # expected arity is 0 or 1.
85
+ def define_roda_method(meth, expected_arity, &block)
86
+ if meth.is_a?(String)
87
+ meth = roda_method_name(meth)
88
+ end
89
+ call_meth = meth
90
+
91
+ # RODA4: Switch to false # :warn in last Roda 3 version
92
+ if (check_arity = opts.fetch(:check_arity, true)) && !block.lambda?
93
+ required_args, optional_args, rest, keyword = _define_roda_method_arg_numbers(block)
94
+
95
+ if keyword == :required && (expected_arity == 0 || expected_arity == 1)
96
+ raise RodaError, "cannot use block with required keyword arguments when calling define_roda_method with expected arity #{expected_arity}"
97
+ end
98
+
99
+ case expected_arity
100
+ when 0
101
+ unless required_args == 0
102
+ if check_arity == :warn
103
+ RodaPlugins.warn "Arity mismatch in block passed to define_roda_method. Expected Arity 0, but arguments required for #{block.inspect}"
104
+ end
105
+ b = block
106
+ block = lambda{instance_exec(&b)} # Fallback
107
+ end
108
+ when 1
109
+ if required_args == 0 && optional_args == 0 && !rest
110
+ if check_arity == :warn
111
+ RodaPlugins.warn "Arity mismatch in block passed to define_roda_method. Expected Arity 1, but no arguments accepted for #{block.inspect}"
112
+ end
113
+ temp_method = roda_method_name("temp")
114
+ class_eval("def #{temp_method}(_) #{meth =~ /\A\w+\z/ ? "#{meth}_arity" : "send(:\"#{meth}_arity\")"} end", __FILE__, __LINE__)
115
+ alias_method meth, temp_method
116
+ undef_method temp_method
117
+ private meth
118
+ alias_method meth, meth
119
+ meth = :"#{meth}_arity"
120
+ elsif required_args > 1
121
+ if check_arity == :warn
122
+ RodaPlugins.warn "Arity mismatch in block passed to define_roda_method. Expected Arity 1, but multiple arguments required for #{block.inspect}"
123
+ end
124
+ b = block
125
+ block = lambda{|r| instance_exec(r, &b)} # Fallback
126
+ end
127
+ when :any
128
+ if check_dynamic_arity = opts.fetch(:check_dynamic_arity, check_arity)
129
+ if keyword
130
+ # Complexity of handling keyword arguments using define_method is too high,
131
+ # Fallback to instance_exec in this case.
132
+ b = block
133
+ block = if RUBY_VERSION >= '2.7'
134
+ eval('lambda{|*a, **kw| instance_exec(*a, **kw, &b)}', nil, __FILE__, __LINE__) # Keyword arguments fallback
135
+ else
136
+ # :nocov:
137
+ lambda{|*a| instance_exec(*a, &b)} # Keyword arguments fallback
138
+ # :nocov:
139
+ end
140
+ else
141
+ arity_meth = meth
142
+ meth = :"#{meth}_arity"
143
+ end
144
+ end
145
+ else
146
+ raise RodaError, "unexpected arity passed to define_roda_method: #{expected_arity.inspect}"
147
+ end
148
+ end
149
+
150
+ define_method(meth, &block)
151
+ private meth
152
+ alias_method meth, meth
153
+
154
+ if arity_meth
155
+ required_args, optional_args, rest, keyword = _define_roda_method_arg_numbers(instance_method(meth))
156
+ max_args = required_args + optional_args
157
+ define_method(arity_meth) do |*a|
158
+ arity = a.length
159
+ if arity > required_args
160
+ if arity > max_args && !rest
161
+ if check_dynamic_arity == :warn
162
+ RodaPlugins.warn "Dynamic arity mismatch in block passed to define_roda_method. At most #{max_args} arguments accepted, but #{arity} arguments given for #{block.inspect}"
163
+ end
164
+ a = a.slice(0, max_args)
165
+ end
166
+ elsif arity < required_args
167
+ if check_dynamic_arity == :warn
168
+ RodaPlugins.warn "Dynamic arity mismatch in block passed to define_roda_method. #{required_args} args required, but #{arity} arguments given for #{block.inspect}"
169
+ end
170
+ a.concat([nil] * (required_args - arity))
171
+ end
172
+
173
+ send(meth, *a)
174
+ end
175
+ private arity_meth
176
+ alias_method arity_meth, arity_meth
177
+ end
178
+
179
+ call_meth
180
+ end
181
+
182
+ # Expand the given path, using the root argument as the base directory.
183
+ def expand_path(path, root=opts[:root])
184
+ ::File.expand_path(path, root)
185
+ end
186
+
187
+ # Freeze the internal state of the class, to avoid thread safety issues at runtime.
188
+ # It's optional to call this method, as nothing should be modifying the
189
+ # internal state at runtime anyway, but this makes sure an exception will
190
+ # be raised if you try to modify the internal state after calling this.
191
+ #
192
+ # Note that freezing the class prevents you from subclassing it, mostly because
193
+ # it would cause some plugins to break.
194
+ def freeze
195
+ return self if frozen?
196
+
197
+ unless opts[:subclassed]
198
+ # If the _roda_run_main_route instance method has not been overridden,
199
+ # make it an alias to _roda_main_route for performance
200
+ if instance_method(:_roda_run_main_route).owner == InstanceMethods
201
+ class_eval("alias _roda_run_main_route _roda_main_route")
202
+ end
203
+ self::RodaResponse.class_eval do
204
+ if instance_method(:set_default_headers).owner == ResponseMethods &&
205
+ instance_method(:default_headers).owner == ResponseMethods
206
+
207
+ private
208
+
209
+ alias set_default_headers set_default_headers
210
+ def set_default_headers
211
+ @headers[RodaResponseHeaders::CONTENT_TYPE] ||= 'text/html'
212
+ end
213
+ end
214
+ end
215
+
216
+ if @middleware.empty? && use_new_dispatch_api?
217
+ plugin :direct_call
218
+ end
219
+
220
+ if RUBY_VERSION > "2.4" && ([:on, :is, :_verb, :_match_class_String, :_match_class_Integer, :_match_string, :_match_regexp, :empty_path?, :if_match, :match, :_match_class]).all?{|m| self::RodaRequest.instance_method(m).owner == RequestMethods}
221
+ plugin :_optimized_matching
222
+ end
223
+ end
224
+
225
+ build_rack_app
226
+ @opts.freeze
227
+ @middleware.freeze
228
+
229
+ super
230
+ end
231
+
232
+ # Rebuild the _roda_before and _roda_after methods whenever a plugin might
233
+ # have added a _roda_before_* or _roda_after_* method.
234
+ def include(*a)
235
+ res = super
236
+ def_roda_before
237
+ def_roda_after
238
+ res
239
+ end
240
+
241
+ # When inheriting Roda, copy the shared data into the subclass,
242
+ # and setup the request and response subclasses.
243
+ def inherited(subclass)
244
+ raise RodaError, "Cannot subclass a frozen Roda class" if frozen?
245
+
246
+ # Mark current class as having been subclassed, as some optimizations
247
+ # depend on the class not being subclassed
248
+ opts[:subclassed] = true
249
+
250
+ super
251
+ subclass.instance_variable_set(:@inherit_middleware, @inherit_middleware)
252
+ subclass.instance_variable_set(:@middleware, @inherit_middleware ? @middleware.dup : [])
253
+ subclass.instance_variable_set(:@opts, opts.dup)
254
+ subclass.opts.delete(:subclassed)
255
+ subclass.opts.to_a.each do |k,v|
256
+ if (v.is_a?(Array) || v.is_a?(Hash)) && !v.frozen?
257
+ subclass.opts[k] = v.dup
258
+ end
259
+ end
260
+ if block = @raw_route_block
261
+ subclass.route(&block)
262
+ end
263
+
264
+ request_class = Class.new(self::RodaRequest)
265
+ request_class.roda_class = subclass
266
+ request_class.match_pattern_cache = RodaCache.new
267
+ subclass.const_set(:RodaRequest, request_class)
268
+
269
+ response_class = Class.new(self::RodaResponse)
270
+ response_class.roda_class = subclass
271
+ subclass.const_set(:RodaResponse, response_class)
272
+ end
273
+
274
+ # Load a new plugin into the current class. A plugin can be a module
275
+ # which is used directly, or a symbol representing a registered plugin
276
+ # which will be required and then used. Returns nil.
277
+ #
278
+ # Note that you should not load plugins into a Roda class after the
279
+ # class has been subclassed, as doing so can break the subclasses.
280
+ #
281
+ # Roda.plugin PluginModule
282
+ # Roda.plugin :csrf
283
+ def plugin(plugin, *args, &block)
284
+ raise RodaError, "Cannot add a plugin to a frozen Roda class" if frozen?
285
+ plugin = RodaPlugins.load_plugin(plugin) if plugin.is_a?(Symbol)
286
+ raise RodaError, "Invalid plugin type: #{plugin.class.inspect}" unless plugin.is_a?(Module)
287
+
288
+ if !plugin.respond_to?(:load_dependencies) && !plugin.respond_to?(:configure) && (!args.empty? || block)
289
+ # RODA4: switch from warning to error
290
+ RodaPlugins.warn("Plugin #{plugin} does not accept arguments or a block, but arguments or a block was passed when loading this. This will raise an error in Roda 4.")
291
+ end
292
+
293
+ plugin.load_dependencies(self, *args, &block) if plugin.respond_to?(:load_dependencies)
294
+ include(plugin::InstanceMethods) if defined?(plugin::InstanceMethods)
295
+ extend(plugin::ClassMethods) if defined?(plugin::ClassMethods)
296
+ self::RodaRequest.send(:include, plugin::RequestMethods) if defined?(plugin::RequestMethods)
297
+ self::RodaRequest.extend(plugin::RequestClassMethods) if defined?(plugin::RequestClassMethods)
298
+ self::RodaResponse.send(:include, plugin::ResponseMethods) if defined?(plugin::ResponseMethods)
299
+ self::RodaResponse.extend(plugin::ResponseClassMethods) if defined?(plugin::ResponseClassMethods)
300
+ plugin.configure(self, *args, &block) if plugin.respond_to?(:configure)
301
+ @app = nil
302
+ end
303
+ # :nocov:
304
+ ruby2_keywords(:plugin) if respond_to?(:ruby2_keywords, true)
305
+ # :nocov:
306
+
307
+ # Setup routing tree for the current Roda application, and build the
308
+ # underlying rack application using the stored middleware. Requires
309
+ # a block, which is yielded the request. By convention, the block
310
+ # argument should be named +r+. Example:
311
+ #
312
+ # Roda.route do |r|
313
+ # r.root do
314
+ # "Root"
315
+ # end
316
+ # end
317
+ #
318
+ # This should only be called once per class, and if called multiple
319
+ # times will overwrite the previous routing.
320
+ def route(&block)
321
+ unless block
322
+ RodaPlugins.warn "no block passed to Roda.route"
323
+ return
324
+ end
325
+
326
+ @raw_route_block = block
327
+ @route_block = block = convert_route_block(block)
328
+ @rack_app_route_block = block = rack_app_route_block(block)
329
+ public define_roda_method(:_roda_main_route, 1, &block)
330
+ @app = nil
331
+ end
332
+
333
+ # Add a middleware to use for the rack application. Must be
334
+ # called before calling #route to have an effect. Example:
335
+ #
336
+ # Roda.use Rack::ShowExceptions
337
+ def use(*args, &block)
338
+ @middleware << [args, block].freeze
339
+ @app = nil
340
+ end
341
+ # :nocov:
342
+ ruby2_keywords(:use) if respond_to?(:ruby2_keywords, true)
343
+ # :nocov:
344
+
345
+ private
346
+
347
+ # Return the number of required argument, optional arguments,
348
+ # whether the callable accepts any additional arguments,
349
+ # and whether the callable accepts keyword arguments (true, false
350
+ # or :required).
351
+ def _define_roda_method_arg_numbers(callable)
352
+ optional_args = 0
353
+ rest = false
354
+ keyword = false
355
+ callable.parameters.map(&:first).each do |arg_type, _|
356
+ case arg_type
357
+ when :opt
358
+ optional_args += 1
359
+ when :rest
360
+ rest = true
361
+ when :keyreq
362
+ keyword = :required
363
+ when :key, :keyrest
364
+ keyword ||= true
365
+ end
366
+ end
367
+ arity = callable.arity
368
+ if arity < 0
369
+ arity = arity.abs - 1
370
+ end
371
+ required_args = arity
372
+ arity -= 1 if keyword == :required
373
+
374
+ if callable.is_a?(Proc) && !callable.lambda?
375
+ optional_args -= arity
376
+ end
377
+
378
+ [required_args, optional_args, rest, keyword]
379
+ end
380
+
381
+ # The base rack app to use, before middleware is added.
382
+ def base_rack_app_callable(new_api=true)
383
+ if new_api
384
+ lambda{|env| new(env)._roda_handle_main_route}
385
+ else
386
+ block = @rack_app_route_block
387
+ lambda{|env| new(env).call(&block)}
388
+ end
389
+ end
390
+
391
+ # Build the rack app to use
392
+ def build_rack_app
393
+ app = base_rack_app_callable(use_new_dispatch_api?)
394
+
395
+ @middleware.reverse_each do |args, bl|
396
+ mid, *args = args
397
+ app = mid.new(app, *args, &bl)
398
+ app.freeze if opts[:freeze_middleware]
399
+ end
400
+
401
+ @app = app
402
+ end
403
+
404
+ # Modify the route block to use for any route block provided as input,
405
+ # which can include route blocks that are delegated to by the main route block.
406
+ # Can be modified by plugins.
407
+ def convert_route_block(block)
408
+ block
409
+ end
410
+
411
+ # Build a _roda_before method that calls each _roda_before_* method
412
+ # in order, if any _roda_before_* methods are defined. Also, rebuild
413
+ # the route block if a _roda_before method is defined.
414
+ def def_roda_before
415
+ meths = private_instance_methods.grep(/\A_roda_before_\d\d/).sort
416
+ unless meths.empty?
417
+ plugin :_before_hook unless private_method_defined?(:_roda_before)
418
+ if meths.length == 1
419
+ class_eval("alias _roda_before #{meths.first}", __FILE__, __LINE__)
420
+ else
421
+ class_eval("def _roda_before; #{meths.join(';')} end", __FILE__, __LINE__)
422
+ end
423
+ private :_roda_before
424
+ alias_method :_roda_before, :_roda_before
425
+ end
426
+ end
427
+
428
+ # Build a _roda_after method that calls each _roda_after_* method
429
+ # in order, if any _roda_after_* methods are defined. Also, use
430
+ # the internal after hook plugin if the _roda_after method is defined.
431
+ def def_roda_after
432
+ meths = private_instance_methods.grep(/\A_roda_after_\d\d/).sort
433
+ unless meths.empty?
434
+ plugin :error_handler unless private_method_defined?(:_roda_after)
435
+ if meths.length == 1
436
+ class_eval("alias _roda_after #{meths.first}", __FILE__, __LINE__)
437
+ else
438
+ class_eval("def _roda_after(res); #{meths.map{|s| "#{s}(res)"}.join(';')} end", __FILE__, __LINE__)
439
+ end
440
+ private :_roda_after
441
+ alias_method :_roda_after, :_roda_after
442
+ end
443
+ end
444
+
445
+ # The route block to use when building the rack app (or other initial
446
+ # entry point to the route block).
447
+ # By default, modifies the rack app route block to support before hooks
448
+ # if any before hooks are defined.
449
+ # Can be modified by plugins.
450
+ def rack_app_route_block(block)
451
+ block
452
+ end
453
+
454
+ # Whether the new dispatch API should be used.
455
+ def use_new_dispatch_api?
456
+ # RODA4: remove this method
457
+ ancestors.each do |mod|
458
+ break if mod == InstanceMethods
459
+ meths = mod.instance_methods(false)
460
+ if meths.include?(:call) && !(meths.include?(:_roda_handle_main_route) || meths.include?(:_roda_run_main_route))
461
+ RodaPlugins.warn <<WARNING
462
+ Falling back to using #call for dispatching for #{self}, due to #call override in #{mod}.
463
+ #{mod} should be fixed to adjust to Roda's new dispatch API, and override _roda_handle_main_route or _roda_run_main_route
464
+ WARNING
465
+ return false
466
+ end
467
+ end
468
+
469
+ true
470
+ end
471
+
472
+ method_num = 0
473
+ method_num_mutex = Mutex.new
474
+ # Return a unique method name symbol for the given suffix.
475
+ define_method(:roda_method_name) do |suffix|
476
+ :"_roda_#{suffix}_#{method_num_mutex.synchronize{method_num += 1}}"
477
+ end
478
+ end
479
+
480
+ # Instance methods for the Roda class.
481
+ #
482
+ # In addition to the listed methods, the following two methods are available:
483
+ #
484
+ # request :: The instance of the request class related to this request.
485
+ # This is the same object yielded by Roda.route.
486
+ # response :: The instance of the response class related to this request.
487
+ module InstanceMethods
488
+ # Create a request and response of the appropriate class
489
+ def initialize(env)
490
+ klass = self.class
491
+ @_request = klass::RodaRequest.new(self, env)
492
+ @_response = klass::RodaResponse.new
493
+ end
494
+
495
+ # Handle dispatching to the main route, catching :halt and handling
496
+ # the result of the block.
497
+ def _roda_handle_main_route
498
+ catch(:halt) do
499
+ r = @_request
500
+ r.block_result(_roda_run_main_route(r))
501
+ @_response.finish
502
+ end
503
+ end
504
+
505
+ # Treat the given block as a routing block, catching :halt if
506
+ # thrown by the block.
507
+ def _roda_handle_route
508
+ catch(:halt) do
509
+ @_request.block_result(yield)
510
+ @_response.finish
511
+ end
512
+ end
513
+
514
+ # Default implementation of the main route, usually overridden
515
+ # by Roda.route.
516
+ def _roda_main_route(_)
517
+ end
518
+
519
+ # Run the main route block with the request. Designed for
520
+ # extension by plugins
521
+ def _roda_run_main_route(r)
522
+ _roda_main_route(r)
523
+ end
524
+
525
+ # Deprecated method for the previous main route dispatch API.
526
+ def call(&block)
527
+ # RODA4: Remove
528
+ catch(:halt) do
529
+ r = @_request
530
+ r.block_result(instance_exec(r, &block)) # Fallback
531
+ @_response.finish
532
+ end
533
+ end
534
+
535
+ # Deprecated private alias for internal use
536
+ alias _call call
537
+ # RODA4: Remove
538
+ private :_call
539
+
540
+ # The environment hash for the current request. Example:
541
+ #
542
+ # env['REQUEST_METHOD'] # => 'GET'
543
+ def env
544
+ @_request.env
545
+ end
546
+
547
+ # The class-level options hash. This should probably not be
548
+ # modified at the instance level. Example:
549
+ #
550
+ # Roda.plugin :render
551
+ # Roda.route do |r|
552
+ # opts[:render_opts].inspect
553
+ # end
554
+ def opts
555
+ self.class.opts
556
+ end
557
+
558
+ attr_reader :_request # :nodoc:
559
+ alias request _request
560
+ remove_method :_request
561
+
562
+ attr_reader :_response # :nodoc:
563
+ alias response _response
564
+ remove_method :_response
565
+
566
+ # The session hash for the current request. Raises RodaError
567
+ # if no session exists. Example:
568
+ #
569
+ # session # => {}
570
+ def session
571
+ @_request.session
572
+ end
573
+
574
+ private
575
+
576
+ # Convert the segment matched by the Integer matcher to an integer.
577
+ def _convert_class_Integer(value)
578
+ value.to_i
579
+ end
580
+ end
581
+ end
582
+ end
583
+
584
+ extend RodaPlugins::Base::ClassMethods
585
+ plugin RodaPlugins::Base
586
+ end
@@ -0,0 +1,12 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "ultra-lite-hub"
3
+ s.version = "0.0.1"
4
+ s.summary = "Research test"
5
+ s.description = "University research based on roda"
6
+ s.authors = ["Andrey78"]
7
+ s.email = ["cakoc614@gmail.com"]
8
+ s.files = Dir.glob("**/*").reject { |f| f.end_with?('.gem') }
9
+ s.homepage = "https://rubygems.org/profiles/Andrey78"
10
+ s.license = "MIT"
11
+ s.metadata = { "source_code_uri" => "https://github.com/Andrey78/ultra-lite-hub" }
12
+ end