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,111 @@
1
+ # frozen-string-literal: true
2
+
3
+ #
4
+ class Roda
5
+ module RodaPlugins
6
+ # The class_level_routing plugin adds routing methods at the class level, which can
7
+ # be used instead of or in addition to using the normal +route+ method to start the
8
+ # routing tree. If a request is not matched by the normal routing tree, the class
9
+ # level routes will be tried. This offers a more Sinatra-like API, while
10
+ # still allowing you to use a routing tree inside individual actions.
11
+ #
12
+ # Here's the first example from the README, modified to use the class_level_routing
13
+ # plugin:
14
+ #
15
+ # class App < Roda
16
+ # plugin :class_level_routing
17
+ #
18
+ # # GET / request
19
+ # root do
20
+ # request.redirect "/hello"
21
+ # end
22
+ #
23
+ # # GET /hello/world request
24
+ # get "hello/world" do
25
+ # "Hello world!"
26
+ # end
27
+ #
28
+ # # /hello request
29
+ # is "hello" do
30
+ # # Set variable for both GET and POST requests
31
+ # @greeting = 'Hello'
32
+ #
33
+ # # GET /hello request
34
+ # request.get do
35
+ # "#{@greeting}!"
36
+ # end
37
+ #
38
+ # # POST /hello request
39
+ # request.post do
40
+ # puts "Someone said #{@greeting}!"
41
+ # request.redirect
42
+ # end
43
+ # end
44
+ # end
45
+ #
46
+ # When using the class_level_routing plugin with nested routes, you may also want to use the
47
+ # delegate plugin to delegate certain instance methods to the request object, so you don't have
48
+ # to continually use +request.+ in your routing blocks.
49
+ #
50
+ # Note that class level routing is implemented via a simple array of routes, so routing performance
51
+ # will degrade linearly as the number of routes increases. For best performance, you should use
52
+ # the normal +route+ class method to define your routing tree. This plugin does make it simpler to
53
+ # add additional routes after the routing tree has already been defined, though.
54
+ module ClassLevelRouting
55
+ # Initialize the class_routes array when the plugin is loaded. Also, if the application doesn't
56
+ # currently have a routing block, setup an empty routing block so that things will still work if
57
+ # a routing block isn't added.
58
+ def self.configure(app)
59
+ app.opts[:class_level_routes] ||= []
60
+ end
61
+
62
+ module ClassMethods
63
+ # Define routing methods that will store class level routes.
64
+ [:root, :on, :is, :get, :post, :delete, :head, :options, :link, :patch, :put, :trace, :unlink].each do |request_meth|
65
+ define_method(request_meth) do |*args, &block|
66
+ meth = define_roda_method("class_level_routing_#{request_meth}", :any, &block)
67
+ opts[:class_level_routes] << [request_meth, args, meth].freeze
68
+ end
69
+ end
70
+
71
+ # Freeze the class level routes so that there can be no thread safety issues at runtime.
72
+ def freeze
73
+ opts[:class_level_routes].freeze
74
+ super
75
+ end
76
+ end
77
+
78
+ module InstanceMethods
79
+ def initialize(_)
80
+ super
81
+ @_original_remaining_path = @_request.remaining_path
82
+ end
83
+
84
+ private
85
+
86
+ # If the normal routing tree doesn't handle an action, try each class level route
87
+ # to see if it matches.
88
+ def _roda_after_10__class_level_routing(result)
89
+ if result && result[0] == 404 && (v = result[2]).is_a?(Array) && v.empty?
90
+ # Reset the response so it doesn't inherit the status or any headers from
91
+ # the original response.
92
+ @_response.send(:initialize)
93
+ @_response.status = nil
94
+ result.replace(_roda_handle_route do
95
+ r = @_request
96
+ opts[:class_level_routes].each do |request_meth, args, meth|
97
+ r.instance_variable_set(:@remaining_path, @_original_remaining_path)
98
+ r.public_send(request_meth, *args) do |*a|
99
+ send(meth, *a)
100
+ end
101
+ end
102
+ nil
103
+ end)
104
+ end
105
+ end
106
+ end
107
+ end
108
+
109
+ register_plugin(:class_level_routing, ClassLevelRouting)
110
+ end
111
+ end
@@ -0,0 +1,155 @@
1
+ # frozen-string-literal: true
2
+
3
+ #
4
+ class Roda
5
+ module RodaPlugins
6
+ # The class_matchers plugin allows you do define custom regexps and
7
+ # conversion procs to use for specific classes. For example, if you
8
+ # have multiple routes similar to:
9
+ #
10
+ # r.on /(\d\d\d\d)-(\d\d)-(\d\d)/ do |y, m, d|
11
+ # date = Date.new(y.to_i, m.to_i, d.to_i)
12
+ # # ...
13
+ # end
14
+ #
15
+ # You can register a Date class matcher for that regexp:
16
+ #
17
+ # class_matcher(Date, /(\d\d\d\d)-(\d\d)-(\d\d)/) do |y, m, d|
18
+ # Date.new(y.to_i, m.to_i, d.to_i)
19
+ # end
20
+ #
21
+ # And then use the Date class as a matcher, and it will yield a Date object:
22
+ #
23
+ # r.on Date do |date|
24
+ # # ...
25
+ # end
26
+ #
27
+ # This is useful to DRY up code if you are using the same type of pattern and
28
+ # type conversion in multiple places in your application. You can have the
29
+ # block return an array to yield multiple captures.
30
+ #
31
+ # If you have a segment match the passed regexp, but decide during block
32
+ # processing that you do not want to treat it as a match, you can have the
33
+ # block return nil or false. This is useful if you want to make sure you
34
+ # are using valid data:
35
+ #
36
+ # class_matcher(Date, /(\d\d\d\d)-(\d\d)-(\d\d)/) do |y, m, d|
37
+ # y = y.to_i
38
+ # m = m.to_i
39
+ # d = d.to_i
40
+ # Date.new(y, m, d) if Date.valid_date?(y, m, d)
41
+ # end
42
+ #
43
+ # The second argument to class_matcher can be a class already registered
44
+ # as a class matcher. This can DRY up code that wants a conversion
45
+ # performed by an existing class matcher:
46
+ #
47
+ # class_matcher Employee, Integer do |id|
48
+ # Employee[id]
49
+ # end
50
+ #
51
+ # With the above example, the Integer matcher performs the conversion to
52
+ # integer, so +id+ is yielded as an integer. The block then looks up the
53
+ # employee with that id. If there is no employee with that id, then
54
+ # the Employee matcher will not match.
55
+ #
56
+ # If using the symbol_matchers plugin, you can provide a recognized symbol
57
+ # matcher as the second argument to class_matcher, and it will work in
58
+ # a similar manner:
59
+ #
60
+ # symbol_matcher(:employee_id, /E-(\d{6})/) do |employee_id|
61
+ # employee_id.to_i
62
+ # end
63
+ # class_matcher Employee, :employee_id do |id|
64
+ # Employee[id]
65
+ # end
66
+ #
67
+ # Blocks passed to the class_matchers plugin are evaluated in route
68
+ # block context.
69
+ #
70
+ # When passing a regexp as a matcher, to class_matcher, you can provide a
71
+ # <tt>segment: true</tt> option to speed up the matching on Ruby 2.4+:
72
+ #
73
+ # symbol_matcher(:employee_id, /E-(\d{6})/, segment: true) do |employee_id|
74
+ # employee_id.to_i
75
+ # end
76
+ #
77
+ # Use of <tt>segment: true</tt> requires that the regexp not match more than
78
+ # one segment (i.e. it cannot match +/+). Additionally, the entire segment will
79
+ # be captured, so any capture groups in the regexp will be ignored.
80
+ #
81
+ # This plugin does not work with the params_capturing plugin, as it does not
82
+ # offer the ability to associate block arguments with named keys.
83
+ module ClassMatchers
84
+ def self.load_dependencies(app)
85
+ app.plugin :_symbol_class_matchers
86
+ end
87
+
88
+ def self.configure(app)
89
+ app.opts[:class_matchers] ||= {
90
+ Integer=>[/(\d{1,100})/, /\A\/(\d{1,100})(?=\/|\z)/, :_convert_class_Integer].freeze,
91
+ String=>[/([^\/]+)/, nil, nil].freeze
92
+ }
93
+ end
94
+
95
+ module ClassMethods
96
+ # Set the matcher and block to use for the given class.
97
+ # The matcher can be a regexp, registered class matcher, or registered symbol
98
+ # matcher (if using the symbol_matchers plugin).
99
+ #
100
+ # If providing a regexp, the block given will be called with all regexp captures.
101
+ # If providing a registered class or symbol, the block will be called with the
102
+ # captures returned by the block for the registered class or symbol, or the regexp
103
+ # captures if no block was registered with the class or symbol. In either case,
104
+ # if a block is given, it should return an array with the captures to yield to
105
+ # the match block.
106
+ def class_matcher(klass, matcher, opts=OPTS, &block)
107
+ _symbol_class_matcher(Class, klass, matcher, block, opts) do |meth, (_, regexp, convert_meth, consume_meth)|
108
+ if regexp
109
+ if consume_meth == :_consume_single_segment
110
+ define_method(meth){_consume_single_segment(regexp, convert_meth)}
111
+ else
112
+ define_method(meth){consume(regexp, convert_meth)}
113
+ end
114
+ else
115
+ define_method(meth){_consume_segment(convert_meth)}
116
+ end
117
+ end
118
+ end
119
+
120
+ # Freeze the class_matchers hash when freezing the app.
121
+ def freeze
122
+ opts[:class_matchers].freeze
123
+ super
124
+ end
125
+ end
126
+
127
+ module RequestMethods
128
+ # Use faster approach for segment matching. This is used for
129
+ # matchers based on the String class matcher, and avoids the
130
+ # use of regular expressions for scanning.
131
+ def _consume_segment(convert_meth)
132
+ rp = @remaining_path
133
+ if _match_class_String
134
+ if convert_meth
135
+ if captures = scope.send(convert_meth, @captures.pop)
136
+ if captures.is_a?(Array)
137
+ @captures.concat(captures)
138
+ else
139
+ @captures << captures
140
+ end
141
+ else
142
+ @remaining_path = rp
143
+ nil
144
+ end
145
+ else
146
+ true
147
+ end
148
+ end
149
+ end
150
+ end
151
+ end
152
+
153
+ register_plugin(:class_matchers, ClassMatchers)
154
+ end
155
+ end
@@ -0,0 +1,80 @@
1
+ # frozen-string-literal: true
2
+
3
+ #
4
+ class Roda
5
+ module RodaPlugins
6
+ # The common_logger plugin adds common logger support to Roda
7
+ # applications, similar to Rack::CommonLogger, with the following
8
+ # differences:
9
+ #
10
+ # * Better performance
11
+ # * Doesn't include middleware timing
12
+ # * Doesn't proxy the body
13
+ # * Doesn't support different capitalization of the Content-Length response header
14
+ # * Logs to +$stderr+ instead of <tt>env['rack.errors']</tt> if explicit logger not passed
15
+ #
16
+ # Example:
17
+ #
18
+ # plugin :common_logger
19
+ # plugin :common_logger, $stdout
20
+ # plugin :common_logger, Logger.new('filename')
21
+ # plugin :common_logger, Logger.new('filename'), method: :debug
22
+ module CommonLogger
23
+ MUTATE_LINE = RUBY_VERSION < '2.3' || RUBY_VERSION >= '3'
24
+ private_constant :MUTATE_LINE
25
+
26
+ def self.configure(app, logger=nil, opts=OPTS)
27
+ app.opts[:common_logger] = logger || app.opts[:common_logger] || $stderr
28
+ app.opts[:common_logger_meth] = app.opts[:common_logger].method(opts.fetch(:method){logger.respond_to?(:write) ? :write : :<<})
29
+ end
30
+
31
+ if RUBY_VERSION >= '2.1'
32
+ # A timer object for calculating elapsed time.
33
+ def self.start_timer
34
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
35
+ end
36
+ else
37
+ # :nocov:
38
+ def self.start_timer # :nodoc:
39
+ Time.now
40
+ end
41
+ # :nocov:
42
+ end
43
+
44
+ module InstanceMethods
45
+ private
46
+
47
+ # Log request/response information in common log format to logger.
48
+ def _roda_after_90__common_logger(result)
49
+ return unless result && (status = result[0]) && (headers = result[1])
50
+
51
+ elapsed_time = if timer = @_request_timer
52
+ '%0.4f' % (CommonLogger.start_timer - timer)
53
+ else
54
+ '-'
55
+ end
56
+
57
+ env = @_request.env
58
+
59
+ line = "#{env['HTTP_X_FORWARDED_FOR'] || env["REMOTE_ADDR"] || "-"} - #{env["REMOTE_USER"] || "-"} [#{Time.now.strftime("%d/%b/%Y:%H:%M:%S %z")}] \"#{env["REQUEST_METHOD"]} #{env["SCRIPT_NAME"]}#{env["PATH_INFO"]}#{"?#{env["QUERY_STRING"]}" if ((qs = env["QUERY_STRING"]) && !qs.empty?)} #{@_request.http_version}\" #{status} #{((length = headers[RodaResponseHeaders::CONTENT_LENGTH]) && (length unless length == '0')) || '-'} #{elapsed_time} "
60
+ if MUTATE_LINE
61
+ line.gsub!(/[^[:print:]]/){|c| sprintf("\\x%x", c.ord)}
62
+ # :nocov:
63
+ else
64
+ line = line.gsub(/[^[:print:]]/){|c| sprintf("\\x%x", c.ord)}
65
+ # :nocov:
66
+ end
67
+ line[-1] = "\n"
68
+ opts[:common_logger_meth].call(line)
69
+ end
70
+
71
+ # Create timer instance used for timing
72
+ def _roda_before_05__common_logger
73
+ @_request_timer = CommonLogger.start_timer
74
+ end
75
+ end
76
+ end
77
+
78
+ register_plugin(:common_logger, CommonLogger)
79
+ end
80
+ end
@@ -0,0 +1,67 @@
1
+ # frozen-string-literal: true
2
+
3
+ class Roda
4
+ module RodaPlugins
5
+ # The conditional_sessions plugin loads the sessions plugin. However,
6
+ # it only allows sessions if the block passed to the plugin returns
7
+ # truthy. The block is evaluated in request context. This is designed for
8
+ # use in applications that want to use sessions for some requests,
9
+ # and want to be sure that sessions are not used for other requests.
10
+ # For example, if you want to make sure that sessions are not used for
11
+ # requests with paths starting with /static, you could do:
12
+ #
13
+ # plugin :conditional_sessions, secret: ENV["SECRET"] do
14
+ # !path_info.start_with?('/static')
15
+ # end
16
+ #
17
+ # The the request session, session_created_at, and session_updated_at methods
18
+ # raise a RodaError exception when sessions are not allowed. The request
19
+ # persist_session and route scope clear_session methods do nothing when
20
+ # sessions are not allowed.
21
+ module ConditionalSessions
22
+ # Pass all options to the sessions block, and use the block to define
23
+ # a request method for whether sessions are allowed.
24
+ def self.load_dependencies(app, opts=OPTS, &block)
25
+ app.plugin :sessions, opts
26
+ app::RodaRequest.class_eval do
27
+ define_method(:use_sessions?, &block)
28
+ alias use_sessions? use_sessions?
29
+ end
30
+ end
31
+
32
+ module InstanceMethods
33
+ # Do nothing if not using sessions.
34
+ def clear_session
35
+ super if @_request.use_sessions?
36
+ end
37
+ end
38
+
39
+ module RequestMethods
40
+ # Raise RodaError if not using sessions.
41
+ def session
42
+ raise RodaError, "session called on request not using sessions" unless use_sessions?
43
+ super
44
+ end
45
+
46
+ # Raise RodaError if not using sessions.
47
+ def session_created_at
48
+ raise RodaError, "session_created_at called on request not using sessions" unless use_sessions?
49
+ super
50
+ end
51
+
52
+ # Raise RodaError if not using sessions.
53
+ def session_updated_at
54
+ raise RodaError, "session_updated_at called on request not using sessions" unless use_sessions?
55
+ super
56
+ end
57
+
58
+ # Do nothing if not using sessions.
59
+ def persist_session(headers, session)
60
+ super if use_sessions?
61
+ end
62
+ end
63
+ end
64
+
65
+ register_plugin(:conditional_sessions, ConditionalSessions)
66
+ end
67
+ end
@@ -0,0 +1,103 @@
1
+ # frozen-string-literal: true
2
+
3
+ #
4
+ class Roda
5
+ module RodaPlugins
6
+ # The content_for plugin is designed to be used with the
7
+ # render plugin, allowing you to store content inside one
8
+ # template, and retrieve that content inside a separate
9
+ # template. Most commonly, this is so view templates
10
+ # can set content for the layout template to display outside
11
+ # of the normal content pane.
12
+ #
13
+ # In the template in which you want to store content, call
14
+ # content_for with a block:
15
+ #
16
+ # <% content_for :foo do %>
17
+ # Some content here.
18
+ # <% end %>
19
+ #
20
+ # or:
21
+ #
22
+ # <% content_for :foo do "Some content here." end %>
23
+ #
24
+ # You can also set the raw content as the second argument,
25
+ # instead of passing a block:
26
+ #
27
+ # <% content_for :foo, "Some content" %>
28
+ #
29
+ # In the template in which you want to retrieve content,
30
+ # call content_for without the block or argument:
31
+ #
32
+ # <%= content_for :foo %>
33
+ #
34
+ # Note that when storing content by calling content_for
35
+ # with a block and embedding template code, the return
36
+ # value of the block is used as the content (after being
37
+ # converted to a string). This can cause issues in some
38
+ # cases, such as:
39
+ #
40
+ # <% content_for :foo do %>
41
+ # <% [1,2,3].each do |i| %>
42
+ # Content <%= i %>
43
+ # <% end %>
44
+ # <% end %>
45
+ #
46
+ # In the above example, the return value of the block is
47
+ # <tt>[1,2,3]</tt>, as Array#each returns the receiver.
48
+ # If whitespace is not important, you can work around this by
49
+ # adding an empty line before the end of the content_for block.
50
+ #
51
+ # If content_for is used multiple times with the same key,
52
+ # by default, the last call will append previous calls.
53
+ # If you want to overwrite the previous content, pass the
54
+ # <tt>append: false</tt> option when loading the plugin:
55
+ #
56
+ # plugin :content_for, append: false
57
+ module ContentFor
58
+ # Depend on the capture_erb plugin, since it uses capture_erb
59
+ # to capture the content.
60
+ def self.load_dependencies(app, _opts = OPTS)
61
+ app.plugin :capture_erb
62
+ end
63
+
64
+ # Configure whether to append or overwrite if content_for
65
+ # is called multiple times with the same key.
66
+ def self.configure(app, opts = OPTS)
67
+ app.opts[:append_content_for] = opts.fetch(:append, true)
68
+ end
69
+
70
+ module InstanceMethods
71
+ # If called with a block, store content enclosed by block
72
+ # under the given key. If called without a block, retrieve
73
+ # stored content with the given key, or return nil if there
74
+ # is no content stored with that key.
75
+ def content_for(key, value=nil, &block)
76
+ append = opts[:append_content_for]
77
+
78
+ if block || value
79
+ if block
80
+ value = capture_erb(&block)
81
+ end
82
+
83
+ @_content_for ||= {}
84
+
85
+ if append
86
+ (@_content_for[key] ||= []) << value
87
+ else
88
+ @_content_for[key] = value
89
+ end
90
+ elsif @_content_for && (value = @_content_for[key])
91
+ if append
92
+ value = value.join
93
+ end
94
+
95
+ value
96
+ end
97
+ end
98
+ end
99
+ end
100
+
101
+ register_plugin(:content_for, ContentFor)
102
+ end
103
+ end