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,225 @@
1
+ # frozen-string-literal: true
2
+
3
+ #
4
+ class Roda
5
+ module RodaPlugins
6
+ # The middleware plugin allows the Roda app to be used as
7
+ # rack middleware.
8
+ #
9
+ # In the example below, requests to /mid will return Mid
10
+ # by the Mid middleware, and requests to /app will not be
11
+ # matched by the Mid middleware, so they will be forwarded
12
+ # to App.
13
+ #
14
+ # class Mid < Roda
15
+ # plugin :middleware
16
+ #
17
+ # route do |r|
18
+ # r.is "mid" do
19
+ # "Mid"
20
+ # end
21
+ # end
22
+ # end
23
+ #
24
+ # class App < Roda
25
+ # use Mid
26
+ #
27
+ # route do |r|
28
+ # r.is "app" do
29
+ # "App"
30
+ # end
31
+ # end
32
+ # end
33
+ #
34
+ # run App
35
+ #
36
+ # By default, when the app is used as middleware and handles the request at
37
+ # all, it does not forward the request to the next middleware. For the
38
+ # following setup:
39
+ #
40
+ # class Mid < Roda
41
+ # plugin :middleware
42
+ #
43
+ # route do |r|
44
+ # r.on "foo" do
45
+ # r.is "mid" do
46
+ # "Mid"
47
+ # end
48
+ # end
49
+ # end
50
+ # end
51
+ #
52
+ # class App < Roda
53
+ # use Mid
54
+ #
55
+ # route do |r|
56
+ # r.on "foo" do
57
+ # r.is "app" do
58
+ # "App"
59
+ # end
60
+ # end
61
+ # end
62
+ # end
63
+ #
64
+ # run App
65
+ #
66
+ # Requests for +/foo/mid will+ return +Mid+, but requests for +/foo/app+
67
+ # will return an empty 404 response, because the middleware handles the
68
+ # +/foo/app+ request in the <tt>r.on "foo" do</tt> block, but does not
69
+ # have the block return a result, which Roda treats as an empty 404 response.
70
+ # If you would like the middleware to forward +/foo/app+ request to the
71
+ # application, you should use the +:next_if_not_found+ plugin option.
72
+ #
73
+ # It is possible to use the Roda app as a regular app even when using
74
+ # the middleware plugin. Using an app as middleware automatically creates
75
+ # a subclass of the app for the middleware. Because a subclass is automatically
76
+ # created when the app is used as middleware, any configuration of the app
77
+ # should be done before using it as middleware instead of after.
78
+ #
79
+ # You can support configurable middleware by passing a block when loading
80
+ # the plugin:
81
+ #
82
+ # class Mid < Roda
83
+ # plugin :middleware do |middleware, *args, &block|
84
+ # middleware.opts[:middleware_args] = args
85
+ # block.call(middleware)
86
+ # end
87
+ #
88
+ # route do |r|
89
+ # r.is "mid" do
90
+ # opts[:middleware_args].join(' ')
91
+ # end
92
+ # end
93
+ # end
94
+ #
95
+ # class App < Roda
96
+ # use Mid, :foo, :bar do |middleware|
97
+ # middleware.opts[:middleware_args] << :baz
98
+ # end
99
+ # end
100
+ #
101
+ # # Request to App for /mid returns
102
+ # # "foo bar baz"
103
+ module Middleware
104
+ NEXT_PROC = lambda{throw :next, true}
105
+ private_constant :NEXT_PROC
106
+
107
+ # Configure the middleware plugin. Options:
108
+ # :env_var :: Set the environment variable to use to indicate to the roda
109
+ # application that the current request is a middleware request.
110
+ # You should only need to override this if you are using multiple
111
+ # roda middleware in the same application.
112
+ # :handle_result :: Callable object that will be called with request environment
113
+ # and rack response for all requests passing through the middleware,
114
+ # after either the middleware or next app handles the request
115
+ # and returns a response.
116
+ # :forward_response_headers :: Whether changes to the response headers made inside
117
+ # the middleware's route block should be applied to the
118
+ # final response when the request is forwarded to the app.
119
+ # Defaults to false.
120
+ # :next_if_not_found :: If the middleware handles the request but returns a not found
121
+ # result (404 with no body), forward the result to the next middleware.
122
+ def self.configure(app, opts={}, &block)
123
+ app.opts[:middleware_env_var] = opts[:env_var] if opts.has_key?(:env_var)
124
+ app.opts[:middleware_env_var] ||= 'roda.forward_next'
125
+ app.opts[:middleware_configure] = block if block
126
+ app.opts[:middleware_handle_result] = opts[:handle_result]
127
+ app.opts[:middleware_forward_response_headers] = opts[:forward_response_headers]
128
+ app.opts[:middleware_next_if_not_found] = opts[:next_if_not_found]
129
+ end
130
+
131
+ # Forwarder instances are what is actually used as middleware.
132
+ class Forwarder
133
+ # Make a subclass of +mid+ to use as the current middleware,
134
+ # and store +app+ as the next middleware to call.
135
+ def initialize(mid, app, *args, &block)
136
+ @mid = Class.new(mid)
137
+ RodaPlugins.set_temp_name(@mid){"#{mid}::middleware_subclass"}
138
+ if @mid.opts[:middleware_next_if_not_found]
139
+ @mid.plugin(:not_found, &NEXT_PROC)
140
+ end
141
+ if configure = @mid.opts[:middleware_configure]
142
+ configure.call(@mid, *args, &block)
143
+ elsif block || !args.empty?
144
+ raise RodaError, "cannot provide middleware args or block unless loading middleware plugin with a block"
145
+ end
146
+ @app = app
147
+ end
148
+
149
+ # When calling the middleware, first call the current middleware.
150
+ # If this returns a result, return that result directly. Otherwise,
151
+ # pass handling of the request to the next middleware.
152
+ def call(env)
153
+ res = nil
154
+
155
+ call_next = catch(:next) do
156
+ env[@mid.opts[:middleware_env_var]] = true
157
+ res = @mid.call(env)
158
+ false
159
+ end
160
+
161
+ if call_next
162
+ res = @app.call(env)
163
+
164
+ if modified_headers = env.delete('roda.response_headers')
165
+ res[1] = modified_headers.merge(res[1])
166
+ end
167
+ end
168
+
169
+ if handle_result = @mid.opts[:middleware_handle_result]
170
+ handle_result.call(env, res)
171
+ end
172
+
173
+ res
174
+ end
175
+ end
176
+
177
+ module ClassMethods
178
+ # Create a Forwarder instead of a new instance if a non-Hash is given.
179
+ def new(app, *args, &block)
180
+ if app.is_a?(Hash)
181
+ super
182
+ else
183
+ Forwarder.new(self, app, *args, &block)
184
+ end
185
+ end
186
+ end
187
+
188
+ module InstanceMethods
189
+ # Override the route block so that if no route matches, we throw so
190
+ # that the next middleware is called. Old Dispatch API.
191
+ def call(&block)
192
+ super do |r|
193
+ res = instance_exec(r, &block) # call Fallback
194
+ if r.forward_next
195
+ r.env['roda.response_headers'] = response.headers if opts[:middleware_forward_response_headers]
196
+ throw :next, true
197
+ end
198
+ res
199
+ end
200
+ end
201
+
202
+ # Override the route block so that if no route matches, we throw so
203
+ # that the next middleware is called.
204
+ def _roda_run_main_route(r)
205
+ res = super
206
+ if r.forward_next
207
+ r.env['roda.response_headers'] = response.headers if opts[:middleware_forward_response_headers]
208
+ throw :next, true
209
+ end
210
+ res
211
+ end
212
+ end
213
+
214
+ module RequestMethods
215
+ # Whether to forward the request to the next application. Set only if
216
+ # this request is being performed for middleware.
217
+ def forward_next
218
+ env[roda_class.opts[:middleware_env_var]]
219
+ end
220
+ end
221
+ end
222
+
223
+ register_plugin(:middleware, Middleware)
224
+ end
225
+ end
@@ -0,0 +1,101 @@
1
+ # frozen-string-literal: true
2
+
3
+ #
4
+ class Roda
5
+ module RodaPlugins
6
+ # The middleware_stack plugin adds methods to remove middleware
7
+ # from the middleware stack, and insert new middleware at specific
8
+ # positions in the middleware stack.
9
+ #
10
+ # plugin :middleware_stack
11
+ #
12
+ # # Remove csrf middleware
13
+ # middleware_stack.remove{|m, *args| m == Rack::Csrf}
14
+ #
15
+ # # Insert csrf middleware
16
+ # middleware_stack.before{|m, *args| m == Rack::CommonLogger}.use(Rack::Csrf, raise: true)
17
+ # middleware_stack.after{|m, *args| m == Rack::CommonLogger}.use(Rack::Csrf, raise: true)
18
+ module MiddlewareStack
19
+ # Represents a specific position in the application's middleware stack where new
20
+ # middleware can be inserted.
21
+ class StackPosition
22
+ def initialize(app, middleware, position)
23
+ @app = app
24
+ @middleware = middleware
25
+ @position = position
26
+ end
27
+
28
+ # Insert a new middleware into the current position in the middleware stack.
29
+ # Increments the position so that calling this multiple times adds later
30
+ # middleware after earlier middleware, similar to how +Roda.use+ works.
31
+ def use(*args, &block)
32
+ @middleware.insert(@position, [args, block])
33
+ @app.send(:build_rack_app)
34
+ @position += 1
35
+ nil
36
+ end
37
+ end
38
+
39
+ # Represents the applications middleware as a stack, allowing for easily
40
+ # removing middleware or finding places to insert new middleware.
41
+ class Stack
42
+ def initialize(app, middleware)
43
+ @app = app
44
+ @middleware = middleware
45
+ end
46
+
47
+ # Return a StackPosition representing the position after the middleware where
48
+ # the block returns true. Yields the middleware and any middleware arguments
49
+ # given, but not the middleware block.
50
+ # It the block never returns true, returns a StackPosition that will insert
51
+ # new middleware at the end of the stack.
52
+ def after(&block)
53
+ handle(1, &block)
54
+ end
55
+
56
+ # Return a StackPosition representing the position before the middleware where
57
+ # the block returns true. Yields the middleware and any middleware arguments
58
+ # given, but not the middleware block.
59
+ # It the block never returns true, returns a StackPosition that will insert
60
+ # new middleware at the end of the stack.
61
+ def before(&block)
62
+ handle(0, &block)
63
+ end
64
+
65
+ # Removes any middleware where the block returns true. Yields the middleware
66
+ # and any middleware arguments given, but not the middleware block
67
+ def remove
68
+ @middleware.delete_if do |m, _|
69
+ yield(*m)
70
+ end
71
+ @app.send(:build_rack_app)
72
+ nil
73
+ end
74
+
75
+ private
76
+
77
+ # Internals of before and after.
78
+ def handle(offset)
79
+ @middleware.each_with_index do |(m, _), i|
80
+ if yield(*m)
81
+ return StackPosition.new(@app, @middleware, i+offset)
82
+ end
83
+ end
84
+
85
+ StackPosition.new(@app, @middleware, @middleware.length)
86
+ end
87
+ end
88
+
89
+ module ClassMethods
90
+ # Return a new Stack that allows removing middleware and inserting
91
+ # middleware at specific places in the stack.
92
+ def middleware_stack
93
+ Stack.new(self, @middleware)
94
+ end
95
+ end
96
+ end
97
+
98
+ register_plugin(:middleware_stack, MiddlewareStack)
99
+ end
100
+ end
101
+
@@ -0,0 +1,96 @@
1
+ # frozen-string-literal: true
2
+
3
+ #
4
+ class Roda
5
+ module RodaPlugins
6
+ # The module_include plugin adds request_module and response_module class methods
7
+ # for adding modules/methods to request/response classes. It's designed to make
8
+ # it easier to add request/response methods for a given roda class. To add a module
9
+ # to the request or response class:
10
+ #
11
+ # Roda.request_module SomeRequestModule
12
+ # Roda.response_module SomeResponseModule
13
+ #
14
+ # Alternatively, you can pass a block to the methods and it will create a module
15
+ # automatically:
16
+ #
17
+ # Roda.request_module do
18
+ # def description
19
+ # "#{request_method} #{path_info}"
20
+ # end
21
+ # end
22
+ module ModuleInclude
23
+ module ClassMethods
24
+ # Include the given module in the request class. If a block
25
+ # is provided instead of a module, create a module using the
26
+ # the block. Example:
27
+ #
28
+ # Roda.request_module SomeModule
29
+ #
30
+ # Roda.request_module do
31
+ # def description
32
+ # "#{request_method} #{path_info}"
33
+ # end
34
+ # end
35
+ #
36
+ # Roda.route do |r|
37
+ # r.description
38
+ # end
39
+ def request_module(mod = nil, &block)
40
+ module_include(:request, mod, &block)
41
+ end
42
+
43
+ # Include the given module in the response class. If a block
44
+ # is provided instead of a module, create a module using the
45
+ # the block. Example:
46
+ #
47
+ # Roda.response_module SomeModule
48
+ #
49
+ # Roda.response_module do
50
+ # def error!
51
+ # self.status = 500
52
+ # end
53
+ # end
54
+ #
55
+ # Roda.route do |r|
56
+ # response.error!
57
+ # end
58
+ def response_module(mod = nil, &block)
59
+ module_include(:response, mod, &block)
60
+ end
61
+
62
+ private
63
+
64
+ # Backbone of the request_module and response_module methods.
65
+ def module_include(type, mod, &block)
66
+ if type == :response
67
+ klass = self::RodaResponse
68
+ iv = :@response_module
69
+ else
70
+ klass = self::RodaRequest
71
+ iv = :@request_module
72
+ end
73
+
74
+ if mod
75
+ raise RodaError, "can't provide both argument and block to response_module" if defined?(yield)
76
+ klass.send(:include, mod)
77
+ else
78
+ if instance_variable_defined?(iv)
79
+ mod = instance_variable_get(iv)
80
+ else
81
+ mod = instance_variable_set(iv, Module.new)
82
+ RodaPlugins.set_temp_name(mod){"#{klass}::module_include"}
83
+ klass.send(:include, mod)
84
+ end
85
+
86
+ mod.module_eval(&block) if block
87
+ end
88
+
89
+ mod
90
+ end
91
+ end
92
+ end
93
+
94
+ register_plugin(:module_include, ModuleInclude)
95
+ end
96
+ end
@@ -0,0 +1,95 @@
1
+ # frozen-string-literal: true
2
+
3
+ begin
4
+ require 'rack/files'
5
+ rescue LoadError
6
+ require 'rack/file'
7
+ end
8
+
9
+ #
10
+ class Roda
11
+ module RodaPlugins
12
+ # The multi_public plugin adds an +r.multi_public+ method that accepts an argument specifying
13
+ # a directory from which to serve static files. It is similar to the public plugin, but
14
+ # allows for multiple separate directories.
15
+ #
16
+ # Here's an example of using the multi_public plugin to serve 3 different types of files
17
+ # from 3 different directories:
18
+ #
19
+ # plugin :multi_public,
20
+ # img: 'static/images',
21
+ # font: 'assets/fonts',
22
+ # form: 'static/forms/pdfs'
23
+ #
24
+ # route do
25
+ # r.on "images" do
26
+ # r.multi_public(:img)
27
+ # end
28
+ #
29
+ # r.on "fonts" do
30
+ # r.multi_public(:font)
31
+ # end
32
+ #
33
+ # r.on "forms" do
34
+ # r.multi_public(:form)
35
+ # end
36
+ # end
37
+ #
38
+ # It is possible to simplify the routing tree for this using string keys and an array
39
+ # matcher:
40
+ #
41
+ # plugin :multi_public,
42
+ # 'images' => 'static/images',
43
+ # 'fonts' => 'assets/fonts',
44
+ # 'forms' => 'static/forms/pdfs'
45
+ #
46
+ # route do
47
+ # r.on %w"images fonts forms" do |dir|
48
+ # r.multi_public(dir)
49
+ # end
50
+ # end
51
+ #
52
+ # You can provide custom headers and default mime type for each directory using an array
53
+ # of three elements as the value, with the first element being the path, the second
54
+ # being the custom headers, and the third being the default mime type:
55
+ #
56
+ # plugin :multi_public,
57
+ # 'images' => ['static/images', {'Cache-Control'=>'max-age=86400'}, nil],
58
+ # 'fonts' => ['assets/fonts', {'Cache-Control'=>'max-age=31536000'}, 'font/ttf'],
59
+ # 'forms' => ['static/forms/pdfs', nil, 'application/pdf']
60
+ #
61
+ # route do
62
+ # r.on %w"images fonts forms" do |dir|
63
+ # r.multi_public(dir)
64
+ # end
65
+ # end
66
+ module MultiPublic
67
+ RACK_FILES = defined?(Rack::Files) ? Rack::Files : Rack::File
68
+
69
+ def self.load_dependencies(app, _, opts=OPTS)
70
+ app.plugin(:public, opts)
71
+ end
72
+
73
+ # Use the given directories to setup servers. Any opts are passed to the public plugin.
74
+ def self.configure(app, directories, _=OPTS)
75
+ roots = app.opts[:multi_public_servers] = (app.opts[:multi_public_servers] || {}).dup
76
+ directories.each do |key, path|
77
+ path, headers, mime = path
78
+ roots[key] = RACK_FILES.new(app.expand_path(path), headers||{}, mime||'text/plain')
79
+ end
80
+ roots.freeze
81
+ end
82
+
83
+ module RequestMethods
84
+ # Serve files from the directory corresponding to the given key if the file exists and
85
+ # this is a GET request.
86
+ def multi_public(key)
87
+ public_serve_with(roda_class.opts[:multi_public_servers].fetch(key))
88
+ end
89
+ end
90
+ end
91
+
92
+ register_plugin(:multi_public, MultiPublic)
93
+ end
94
+ end
95
+
@@ -0,0 +1,156 @@
1
+ # frozen-string-literal: true
2
+
3
+ #
4
+ class Roda
5
+ module RodaPlugins
6
+ # The multi_route plugin builds on the named_routes plugin and allows for
7
+ # dispatching to multiple named routes # by calling the +r.multi_route+ method,
8
+ # which will check # if the first segment in the path matches a named route,
9
+ # and dispatch to that named route.
10
+ #
11
+ # The hash_branches plugin offers a +r.hash_branches+ method that is similar to
12
+ # and performs better than the +r.multi_route+ method, and it is recommended
13
+ # to consider using that instead of this plugin.
14
+ #
15
+ # Example:
16
+ #
17
+ # plugin :multi_route
18
+ #
19
+ # route('foo') do |r|
20
+ # r.is 'bar' do
21
+ # '/foo/bar'
22
+ # end
23
+ # end
24
+ #
25
+ # route('bar') do |r|
26
+ # r.is 'foo' do
27
+ # '/bar/foo'
28
+ # end
29
+ # end
30
+ #
31
+ # route do |r|
32
+ # r.multi_route
33
+ # end
34
+ #
35
+ # Note that only named routes with string names will be dispatched to by the
36
+ # +r.multi_route+ method. Named routes with other names can be dispatched to
37
+ # using the named_routes plugin API, but will not be automatically dispatched
38
+ # to by +r.multi_route+.
39
+ #
40
+ # You can provide a block to +r.multi_route+ that is
41
+ # called if the route matches but the named route did not handle the
42
+ # request:
43
+ #
44
+ # r.multi_route do
45
+ # "default body"
46
+ # end
47
+ #
48
+ # If a block is not provided to multi_route, the return value of the named
49
+ # route block will be used.
50
+ #
51
+ # == Namespace Support
52
+ #
53
+ # The multi_route plugin also has support for namespaces, allowing you to
54
+ # use +r.multi_route+ at multiple levels in your routing tree. Example:
55
+ #
56
+ # route('foo') do |r|
57
+ # r.multi_route('foo')
58
+ # end
59
+ #
60
+ # route('bar') do |r|
61
+ # r.multi_route('bar')
62
+ # end
63
+ #
64
+ # route('baz', 'foo') do |r|
65
+ # # handles /foo/baz prefix
66
+ # end
67
+ #
68
+ # route('quux', 'foo') do |r|
69
+ # # handles /foo/quux prefix
70
+ # end
71
+ #
72
+ # route('baz', 'bar') do |r|
73
+ # # handles /bar/baz prefix
74
+ # end
75
+ #
76
+ # route('quux', 'bar') do |r|
77
+ # # handles /bar/quux prefix
78
+ # end
79
+ #
80
+ # route do |r|
81
+ # r.multi_route
82
+ # end
83
+ module MultiRoute
84
+ def self.load_dependencies(app)
85
+ app.plugin :named_routes
86
+ end
87
+
88
+ # Initialize storage for the named routes.
89
+ def self.configure(app)
90
+ app::RodaRequest.instance_variable_set(:@namespaced_route_regexps, {})
91
+ end
92
+
93
+ module ClassMethods
94
+ # Freeze the multi_route regexp matchers so that there can be no thread safety issues at runtime.
95
+ def freeze
96
+ super
97
+ opts[:namespaced_routes].each_key do |k|
98
+ self::RodaRequest.named_route_regexp(k)
99
+ end
100
+ self::RodaRequest.instance_variable_get(:@namespaced_route_regexps).freeze
101
+ self
102
+ end
103
+
104
+ # Copy the named routes into the subclass when inheriting.
105
+ def inherited(subclass)
106
+ super
107
+ subclass::RodaRequest.instance_variable_set(:@namespaced_route_regexps, {})
108
+ end
109
+
110
+ # Clear the multi_route regexp matcher for the namespace.
111
+ def route(name=nil, namespace=nil, &block)
112
+ super
113
+ if name
114
+ self::RodaRequest.clear_named_route_regexp!(namespace)
115
+ end
116
+ end
117
+ end
118
+
119
+ module RequestClassMethods
120
+ # Clear cached regexp for named routes, it will be regenerated
121
+ # the next time it is needed.
122
+ #
123
+ # This shouldn't be an issue in production applications, but
124
+ # during development it's useful to support new named routes
125
+ # being added while the application is running.
126
+ def clear_named_route_regexp!(namespace=nil)
127
+ @namespaced_route_regexps.delete(namespace)
128
+ end
129
+
130
+ # A regexp matching any of the current named routes.
131
+ def named_route_regexp(namespace=nil)
132
+ @namespaced_route_regexps[namespace] ||= /(#{Regexp.union(roda_class.named_routes(namespace).select{|s| s.is_a?(String)}.sort.reverse)})/
133
+ end
134
+ end
135
+
136
+ module RequestMethods
137
+ # Check if the first segment in the path matches any of the current
138
+ # named routes. If so, call that named route. If not, do nothing.
139
+ # If the named route does not handle the request, and a block
140
+ # is given, yield to the block.
141
+ def multi_route(namespace=nil)
142
+ on self.class.named_route_regexp(namespace) do |section|
143
+ res = route(section, namespace)
144
+ if defined?(yield)
145
+ yield
146
+ else
147
+ res
148
+ end
149
+ end
150
+ end
151
+ end
152
+ end
153
+
154
+ register_plugin(:multi_route, MultiRoute)
155
+ end
156
+ end