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,443 @@
1
+ # frozen-string-literal: true
2
+
3
+ require 'rack/mime'
4
+
5
+ #
6
+ class Roda
7
+ module RodaPlugins
8
+ # The sinatra_helpers plugin ports most of the helper methods
9
+ # defined in Sinatra::Helpers to Roda, other than those
10
+ # helpers that were already covered by other plugins such
11
+ # as caching and streaming.
12
+ #
13
+ # Unlike Sinatra, the helper methods are added to either
14
+ # the request or response classes instead of directly to
15
+ # the scope of the route block. However, for consistency
16
+ # with Sinatra, delegate methods are added to the scope
17
+ # of the route block that call the methods on the request
18
+ # or response. If you do not want to pollute the namespace
19
+ # of the route block, you should load the plugin with the
20
+ # <tt>delegate: false</tt> option:
21
+ #
22
+ # plugin :sinatra_helpers, delegate: false
23
+ #
24
+ # == Class Methods Added
25
+ #
26
+ # The only class method added by this plugin is +mime_type+,
27
+ # which is a shortcut for retrieving or setting MIME types
28
+ # in Rack's MIME database:
29
+ #
30
+ # Roda.mime_type 'csv' # => 'text/csv'
31
+ # Roda.mime_type 'foobar', 'application/foobar' # set
32
+ #
33
+ # == Request Methods Added
34
+ #
35
+ # In addition to adding the following methods, this changes
36
+ # +redirect+ to use a 303 response status code by default for
37
+ # HTTP 1.1 non-GET requests, and to automatically use
38
+ # absolute URIs if the +:absolute_redirects+ Roda class option
39
+ # is true, and to automatically prefix redirect paths with the
40
+ # script name if the +:prefixed_redirects+ Roda class option is
41
+ # true.
42
+ #
43
+ # When adding delegate methods, a logger method is added to
44
+ # the route block scope that calls the logger method on the request.
45
+ #
46
+ # === back
47
+ #
48
+ # +back+ is an alias to referrer, so you can do:
49
+ #
50
+ # redirect back
51
+ #
52
+ # === error
53
+ #
54
+ # +error+ sets the response status code to 500 (or a status code you provide),
55
+ # and halts the request. It takes an optional body:
56
+ #
57
+ # error # 500 response, empty boby
58
+ # error 501 # 501 response, empty body
59
+ # error 'b' # 500 response, 'b' body
60
+ # error 501, 'b' # 501 response, 'b' body
61
+ #
62
+ # === not_found
63
+ #
64
+ # +not_found+ sets the response status code to 404 and halts the request.
65
+ # It takes an optional body:
66
+ #
67
+ # not_found # 404 response, empty body
68
+ # not_found 'b' # 404 response, 'b' body
69
+ #
70
+ # === uri
71
+ #
72
+ # +uri+ by default returns absolute URIs that are prefixed
73
+ # by the script name:
74
+ #
75
+ # request.script_name # => '/foo'
76
+ # uri '/bar' # => 'http://example.org/foo/bar'
77
+ #
78
+ # You can turn of the absolute or script name prefixing if you want:
79
+ #
80
+ # uri '/bar', false # => '/foo/bar'
81
+ # uri '/bar', true, false # => 'http://example.org/bar'
82
+ # uri '/bar', false, false # => '/bar'
83
+ #
84
+ # This method is aliased as +url+ and +to+.
85
+ #
86
+ # === send_file
87
+ #
88
+ # See send_file plugin documentation for details.
89
+ #
90
+ # == Response Methods Added
91
+ #
92
+ # === body
93
+ #
94
+ # When called with an argument or block, +body+ sets the body, otherwise
95
+ # it returns the body:
96
+ #
97
+ # body # => []
98
+ # body('b') # set body to 'b'
99
+ # body{'b'} # set body to 'b', but don't call until body is needed
100
+ #
101
+ # === body=
102
+ #
103
+ # +body+ sets the body to the given value:
104
+ #
105
+ # response.body = 'v'
106
+ #
107
+ # This method is not delegated to the scope of the route block,
108
+ # call +body+ with an argument to set the value.
109
+ #
110
+ # === status
111
+ #
112
+ # When called with an argument, +status+ sets the status, otherwise
113
+ # it returns the status:
114
+ #
115
+ # status # => 200
116
+ # status(301) # sets status to 301
117
+ #
118
+ # === headers
119
+ #
120
+ # When called with an argument, +headers+ merges the given headers
121
+ # into the current headers, otherwise it returns the headers:
122
+ #
123
+ # headers['Foo'] = 'Bar'
124
+ # headers 'Foo' => 'Bar'
125
+ #
126
+ # === mime_type
127
+ #
128
+ # +mime_type+ just calls the Roda class method to get the mime_type.
129
+ #
130
+ # === content_type
131
+ #
132
+ # When called with an argument, +content_type+ sets the Content-Type
133
+ # based on the argument, otherwise it returns the Content-Type.
134
+ #
135
+ # mime_type # => 'text/html'
136
+ # mime_type 'csv' # set Content-Type to 'text/csv'
137
+ # mime_type :csv # set Content-Type to 'text/csv'
138
+ # mime_type '.csv' # set Content-Type to 'text/csv'
139
+ # mime_type 'text/csv' # set Content-Type to 'text/csv'
140
+ #
141
+ # Options:
142
+ #
143
+ # :charset :: Set the charset for the mime type to the given charset, if the charset is
144
+ # not already set in the mime type.
145
+ # :default :: Uses the given type if the mime type is not known. If this option is not
146
+ # used and the mime type is not known, an exception will be raised.
147
+ #
148
+ # === attachment
149
+ #
150
+ # See response_attachment plugin for details.
151
+ #
152
+ # === status predicates
153
+ #
154
+ # This adds the following predicate methods for checking the status:
155
+ #
156
+ # informational? # 100-199
157
+ # success? # 200-299
158
+ # redirect? # 300-399
159
+ # client_error? # 400-499
160
+ # not_found? # 404
161
+ # server_error? # 500-599
162
+ #
163
+ # If the status has not yet been set for the response, these will
164
+ # return +nil+.
165
+ #
166
+ # == License
167
+ #
168
+ # The implementation was originally taken from Sinatra,
169
+ # which is also released under the MIT License:
170
+ #
171
+ # Copyright (c) 2007, 2008, 2009 Blake Mizerany
172
+ # Copyright (c) 2010, 2011, 2012, 2013, 2014 Konstantin Haase
173
+ #
174
+ # Permission is hereby granted, free of charge, to any person
175
+ # obtaining a copy of this software and associated documentation
176
+ # files (the "Software"), to deal in the Software without
177
+ # restriction, including without limitation the rights to use,
178
+ # copy, modify, merge, publish, distribute, sublicense, and/or sell
179
+ # copies of the Software, and to permit persons to whom the
180
+ # Software is furnished to do so, subject to the following
181
+ # conditions:
182
+ #
183
+ # The above copyright notice and this permission notice shall be
184
+ # included in all copies or substantial portions of the Software.
185
+ #
186
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
187
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
188
+ # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
189
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
190
+ # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
191
+ # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
192
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
193
+ # OTHER DEALINGS IN THE SOFTWARE.
194
+ module SinatraHelpers
195
+ # Depend on the status_303 plugin.
196
+ def self.load_dependencies(app, _opts = nil)
197
+ app.plugin :status_303
198
+ app.plugin :send_file
199
+ end
200
+
201
+ # Add delegate methods to the route block scope
202
+ # calling request or response methods, unless the
203
+ # :delegate option is false.
204
+ def self.configure(app, opts=OPTS)
205
+ app.send(:include, DelegateMethods) unless opts[:delegate] == false
206
+ end
207
+
208
+ # Class used when the response body is set explicitly, instead
209
+ # of using Roda's default body array and response.write to
210
+ # write to it.
211
+ class DelayedBody
212
+ # Save the block that will return the body, it won't be
213
+ # called until the body is needed.
214
+ def initialize(&block)
215
+ @block = block
216
+ end
217
+
218
+ # If the body is a String, yield it, otherwise yield each string
219
+ # returned by calling each on the body.
220
+ def each
221
+ v = value
222
+ if v.is_a?(String)
223
+ yield v
224
+ else
225
+ v.each{|s| yield s}
226
+ end
227
+ end
228
+
229
+ # Assume that if the body has been set directly that it is
230
+ # never empty.
231
+ def empty?
232
+ false
233
+ end
234
+
235
+ # Return the body as a single string, mostly useful during testing.
236
+ def join
237
+ a = []
238
+ each{|s| a << s}
239
+ a.join
240
+ end
241
+
242
+ # Calculate the length for the body.
243
+ def length
244
+ length = 0
245
+ each{|s| length += s.bytesize}
246
+ length
247
+ end
248
+
249
+ private
250
+
251
+ # Cache the body returned by the block. This way the block won't
252
+ # be called multiple times.
253
+ def value
254
+ @value ||= @block.call
255
+ end
256
+ end
257
+
258
+ module RequestMethods
259
+ # Alias for referrer
260
+ def back
261
+ referrer
262
+ end
263
+
264
+ # Halt processing and return the error status provided with the given code and
265
+ # optional body.
266
+ # If a single argument is given and it is not an integer, consider it the body
267
+ # and use a 500 status code.
268
+ def error(code=500, body = nil)
269
+ unless code.is_a?(Integer)
270
+ body = code
271
+ code = 500
272
+ end
273
+
274
+ response.status = code
275
+ response.body = body if body
276
+ halt
277
+ end
278
+
279
+ # Halt processing and return a 404 response with an optional body.
280
+ def not_found(body = nil)
281
+ error(404, body)
282
+ end
283
+
284
+ # If the absolute_redirects or :prefixed_redirects roda class options has been set, respect those
285
+ # and update the path.
286
+ def redirect(path=(no_add_script_name = true; default_redirect_path), status=default_redirect_status)
287
+ opts = roda_class.opts
288
+ absolute_redirects = opts[:absolute_redirects]
289
+ prefixed_redirects = no_add_script_name ? false : opts[:prefixed_redirects]
290
+ path = uri(path, absolute_redirects, prefixed_redirects) if absolute_redirects || prefixed_redirects
291
+ super(path, status)
292
+ end
293
+
294
+ # Backwards compatibility for callers of r.send_file.
295
+ def send_file(path, opts = OPTS)
296
+ scope.send_file(path, opts)
297
+ end
298
+
299
+ # Generates the absolute URI for a given path in the app.
300
+ # Takes Rack routers and reverse proxies into account.
301
+ def uri(addr = nil, absolute = true, add_script_name = true)
302
+ addr = addr.to_s if addr
303
+ return addr if addr =~ /\A[A-z][A-z0-9\+\.\-]*:/
304
+ uri = if absolute
305
+ h = if @env.has_key?("HTTP_X_FORWARDED_HOST") || port != (ssl? ? 443 : 80)
306
+ host_with_port
307
+ else
308
+ host
309
+ end
310
+ ["http#{'s' if ssl?}://#{h}"]
311
+ else
312
+ ['']
313
+ end
314
+ uri << script_name.to_s if add_script_name
315
+ uri << (addr || path_info)
316
+ File.join(uri)
317
+ end
318
+ alias url uri
319
+ alias to uri
320
+ end
321
+
322
+ module ResponseMethods
323
+ # Set or retrieve the response status code.
324
+ def status(value = nil || (return @status))
325
+ @status = value
326
+ end
327
+
328
+ # Set or retrieve the response body. When a block is given,
329
+ # evaluation is deferred until the body is needed.
330
+ def body(value = (return @body unless defined?(yield); nil), &block)
331
+ if block
332
+ @body = DelayedBody.new(&block)
333
+ else
334
+ self.body = value
335
+ end
336
+ end
337
+
338
+ # Set the body to the given value.
339
+ def body=(body)
340
+ @body = DelayedBody.new{body}
341
+ end
342
+
343
+ # If the body is a DelayedBody, set the appropriate length for it.
344
+ def finish
345
+ @length = @body.length if @body.is_a?(DelayedBody) && !@headers[RodaResponseHeaders::CONTENT_LENGTH]
346
+ super
347
+ end
348
+
349
+ # Set multiple response headers with Hash, or return the headers if no
350
+ # argument is given.
351
+ def headers(hash = nil || (return @headers))
352
+ @headers.merge!(hash)
353
+ end
354
+
355
+ # Look up a media type by file extension in Rack's mime registry.
356
+ def mime_type(type)
357
+ roda_class.mime_type(type)
358
+ end
359
+
360
+ # Set the Content-Type of the response body given a media type or file
361
+ # extension. See plugin documentation for options.
362
+ def content_type(type = nil || (return @headers[RodaResponseHeaders::CONTENT_TYPE]), opts = OPTS)
363
+ unless (mime_type = mime_type(type) || opts[:default])
364
+ raise RodaError, "Unknown media type: #{type}"
365
+ end
366
+
367
+ unless opts.empty?
368
+ opts.each do |key, val|
369
+ next if key == :default || (key == :charset && mime_type.include?('charset'))
370
+ val = val.inspect if val =~ /[";,]/
371
+ mime_type += "#{mime_type.include?(';') ? ', ' : ';'}#{key}=#{val}"
372
+ end
373
+ end
374
+
375
+ @headers[RodaResponseHeaders::CONTENT_TYPE] = mime_type
376
+ end
377
+
378
+ # Whether or not the status is set to 1xx. Returns nil if status not yet set.
379
+ def informational?
380
+ @status.between?(100, 199) if @status
381
+ end
382
+
383
+ # Whether or not the status is set to 2xx. Returns nil if status not yet set.
384
+ def success?
385
+ @status.between?(200, 299) if @status
386
+ end
387
+
388
+ # Whether or not the status is set to 3xx. Returns nil if status not yet set.
389
+ def redirect?
390
+ @status.between?(300, 399) if @status
391
+ end
392
+
393
+ # Whether or not the status is set to 4xx. Returns nil if status not yet set.
394
+ def client_error?
395
+ @status.between?(400, 499) if @status
396
+ end
397
+
398
+ # Whether or not the status is set to 5xx. Returns nil if status not yet set.
399
+ def server_error?
400
+ @status.between?(500, 599) if @status
401
+ end
402
+
403
+ # Whether or not the status is set to 404. Returns nil if status not yet set.
404
+ def not_found?
405
+ @status == 404 if @status
406
+ end
407
+ end
408
+
409
+ module ClassMethods
410
+ # If a type and value are given, set the value in Rack's MIME registry.
411
+ # If only a type is given, lookup the type in Rack's MIME registry and
412
+ # return it.
413
+ def mime_type(type=nil || (return), value = nil)
414
+ return type.to_s if type.to_s.include?('/')
415
+ type = ".#{type}" unless type.to_s[0] == ?.
416
+ if value
417
+ Rack::Mime::MIME_TYPES[type] = value
418
+ else
419
+ Rack::Mime.mime_type(type, nil)
420
+ end
421
+ end
422
+ end
423
+
424
+ module DelegateMethods
425
+ [:logger, :back].each do |meth|
426
+ define_method(meth){@_request.public_send(meth)}
427
+ end
428
+ [:redirect, :uri, :url, :to, :error, :not_found].each do |meth|
429
+ define_method(meth){|*v, &block| @_request.public_send(meth, *v, &block)}
430
+ end
431
+
432
+ [:informational?, :success?, :redirect?, :client_error?, :server_error?, :not_found?].each do |meth|
433
+ define_method(meth){@_response.public_send(meth)}
434
+ end
435
+ [:status, :body, :headers, :mime_type, :content_type, :attachment].each do |meth|
436
+ define_method(meth){|*v, &block| @_response.public_send(meth, *v, &block)}
437
+ end
438
+ end
439
+ end
440
+
441
+ register_plugin(:sinatra_helpers, SinatraHelpers)
442
+ end
443
+ end
@@ -0,0 +1,26 @@
1
+ # frozen-string-literal: true
2
+
3
+ #
4
+ class Roda
5
+ module RodaPlugins
6
+ # The slash_path_empty plugin considers "/" as an empty path,
7
+ # in addition to the default of "" being considered an empty
8
+ # path. This makes it so +r.is+ without an argument will match
9
+ # a path of "/", and +r.is+ and verb methods such as +r.get+ and
10
+ # +r.post+ will match if the path is "/" after the arguments
11
+ # are processed. This can make it easier to handle applications
12
+ # where a trailing "/" in the path should be ignored.
13
+ module SlashPathEmpty
14
+ module RequestMethods
15
+ private
16
+
17
+ # Consider the path empty if it is "/".
18
+ def empty_path?
19
+ super || remaining_path == '/'
20
+ end
21
+ end
22
+ end
23
+
24
+ register_plugin(:slash_path_empty, SlashPathEmpty)
25
+ end
26
+ end
@@ -0,0 +1,42 @@
1
+ # frozen-string-literal: true
2
+
3
+ require 'rack/static'
4
+
5
+ #
6
+ class Roda
7
+ module RodaPlugins
8
+ # The static plugin loads the Rack::Static middleware into the application.
9
+ # It mainly exists to make serving static files simpler, by supplying
10
+ # defaults to Rack::Static that are appropriate for Roda.
11
+ #
12
+ # The static plugin recognizes the application's :root option, and by default
13
+ # sets the Rack::Static +:root+ option to the +public+ subfolder of the application's
14
+ # +:root+ option. Additionally, if a relative path is provided as the :root
15
+ # option to the plugin, it will be considered relative to the application's
16
+ # +:root+ option.
17
+ #
18
+ # Since the :urls option for Rack::Static is always required, the static plugin
19
+ # uses a separate option for it.
20
+ #
21
+ # Users of this plugin may want to consider using the public plugin instead.
22
+ #
23
+ # Examples:
24
+ #
25
+ # opts[:root] = '/path/to/app'
26
+ # plugin :static, ['/js', '/css'] # path: /path/to/app/public
27
+ # plugin :static, ['/images'], root: 'pub' # path: /path/to/app/pub
28
+ # plugin :static, ['/media'], root: '/path/to/public' # path: /path/to/public
29
+ module Static
30
+ # Load the Rack::Static middleware. Use the paths given as the :urls option,
31
+ # and set the :root option to be relative to the application's :root option.
32
+ def self.configure(app, paths, opts={})
33
+ opts = opts.dup
34
+ opts[:urls] = paths
35
+ opts[:root] = app.expand_path(opts[:root]||"public")
36
+ app.use ::Rack::Static, opts
37
+ end
38
+ end
39
+
40
+ register_plugin(:static, Static)
41
+ end
42
+ end
@@ -0,0 +1,89 @@
1
+ # frozen-string-literal: true
2
+
3
+ #
4
+ class Roda
5
+ module RodaPlugins
6
+ # The static_routing plugin adds static_* routing class methods for handling
7
+ # static routes (i.e. routes with static paths, no nesting or placeholders). These
8
+ # routes are processed before the normal routing tree and designed for
9
+ # maximum performance. This can be substantially faster than Roda's normal
10
+ # tree based routing if you have large numbers of static routes, about 3-4x
11
+ # for 100-10000 static routes. Example:
12
+ #
13
+ # plugin :static_routing
14
+ #
15
+ # static_route '/foo' do |r|
16
+ # @var = :foo
17
+ #
18
+ # r.get do
19
+ # 'Not actually reached'
20
+ # end
21
+ #
22
+ # r.post{'static POST /#{@var}'}
23
+ # end
24
+ #
25
+ # static_get '/foo' do |r|
26
+ # 'static GET /foo'
27
+ # end
28
+ #
29
+ # route do |r|
30
+ # 'Not a static route'
31
+ # end
32
+ #
33
+ # A few things to note in the above example. First, unlike most other
34
+ # routing methods in Roda, these take the full path of the request, and only
35
+ # match if r.path_info matches exactly. This is why you need to include the
36
+ # leading slash in the path argument.
37
+ #
38
+ # Second, the static_* routing methods only take a single string argument for
39
+ # the path, they do not accept other options, and do not handle placeholders
40
+ # in strings. For any routes needing placeholders, you should use Roda's
41
+ # routing tree.
42
+ #
43
+ # There are separate static_* methods for each type of request method, and these
44
+ # request method specific routes are tried first. There is also a static_route
45
+ # method that will match regardless of the request method, if there is no
46
+ # matching request methods specific route. This is why the static_get
47
+ # method call takes precedence over the static_route method call for /foo.
48
+ # As shown above, you can use Roda's routing tree methods inside the
49
+ # static_route block to have shared behavior for different request methods,
50
+ # while still handling the request methods differently.
51
+ module StaticRouting
52
+ def self.load_dependencies(app)
53
+ app.plugin :hash_paths
54
+ end
55
+
56
+ module ClassMethods
57
+ # Add a static route for any request method. These are
58
+ # tried after the request method specific static routes (e.g.
59
+ # static_get), but allow you to use Roda's routing tree
60
+ # methods inside the route for handling shared behavior while
61
+ # still allowing request method specific handling.
62
+ def static_route(path, &block)
63
+ hash_path(:static_routing, path, &block)
64
+ end
65
+
66
+ [:get, :post, :delete, :head, :options, :link, :patch, :put, :trace, :unlink].each do |meth|
67
+ request_method = meth.to_s.upcase
68
+ define_method("static_#{meth}") do |path, &block|
69
+ hash_path(request_method, path, &block)
70
+ end
71
+ end
72
+ end
73
+
74
+ module InstanceMethods
75
+ private
76
+
77
+ # If there is a static routing method for the given path, call it
78
+ # instead having the routing tree handle the request.
79
+ def _roda_before_30__static_routing
80
+ r = @_request
81
+ r.hash_paths(r.request_method)
82
+ r.hash_paths(:static_routing)
83
+ end
84
+ end
85
+ end
86
+
87
+ register_plugin(:static_routing, StaticRouting)
88
+ end
89
+ end
@@ -0,0 +1,34 @@
1
+ # frozen-string-literal: true
2
+
3
+ #
4
+ class Roda
5
+ module RodaPlugins
6
+ # The status_303 plugin sets the default redirect status to be 303
7
+ # rather than 302 when the request is not a GET and the
8
+ # redirection occurs on an HTTP 1.1 connection as per RFC 7231.
9
+ # There are some frontend frameworks that require this behavior.
10
+ #
11
+ # Example:
12
+ #
13
+ # plugin :status_303
14
+ module Status303
15
+ module RequestMethods
16
+
17
+ private
18
+
19
+ def default_redirect_status
20
+ return super if is_get?
21
+
22
+ case http_version
23
+ when 'HTTP/1.0', 'HTTP/0.9', nil
24
+ super
25
+ else
26
+ 303
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ register_plugin(:status_303, Status303)
33
+ end
34
+ end