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.
- checksums.yaml +7 -0
- data/roda-3.105.0/MIT-LICENSE +21 -0
- data/roda-3.105.0/lib/roda/cache.rb +42 -0
- data/roda-3.105.0/lib/roda/plugins/Integer_matcher_max.rb +55 -0
- data/roda-3.105.0/lib/roda/plugins/_after_hook.rb +11 -0
- data/roda-3.105.0/lib/roda/plugins/_base64.rb +34 -0
- data/roda-3.105.0/lib/roda/plugins/_before_hook.rb +41 -0
- data/roda-3.105.0/lib/roda/plugins/_optimized_matching.rb +227 -0
- data/roda-3.105.0/lib/roda/plugins/_symbol_class_matchers.rb +108 -0
- data/roda-3.105.0/lib/roda/plugins/_symbol_regexp_matchers.rb +24 -0
- data/roda-3.105.0/lib/roda/plugins/additional_render_engines.rb +61 -0
- data/roda-3.105.0/lib/roda/plugins/additional_view_directories.rb +66 -0
- data/roda-3.105.0/lib/roda/plugins/all_verbs.rb +50 -0
- data/roda-3.105.0/lib/roda/plugins/assets.rb +902 -0
- data/roda-3.105.0/lib/roda/plugins/assets_preloading.rb +89 -0
- data/roda-3.105.0/lib/roda/plugins/assume_ssl.rb +28 -0
- data/roda-3.105.0/lib/roda/plugins/autoload_hash_branches.rb +79 -0
- data/roda-3.105.0/lib/roda/plugins/autoload_named_routes.rb +65 -0
- data/roda-3.105.0/lib/roda/plugins/backtracking_array.rb +88 -0
- data/roda-3.105.0/lib/roda/plugins/bearer_token.rb +28 -0
- data/roda-3.105.0/lib/roda/plugins/branch_locals.rb +74 -0
- data/roda-3.105.0/lib/roda/plugins/break.rb +43 -0
- data/roda-3.105.0/lib/roda/plugins/caching.rb +206 -0
- data/roda-3.105.0/lib/roda/plugins/capture_erb.rb +94 -0
- data/roda-3.105.0/lib/roda/plugins/chunked.rb +331 -0
- data/roda-3.105.0/lib/roda/plugins/class_level_routing.rb +111 -0
- data/roda-3.105.0/lib/roda/plugins/class_matchers.rb +155 -0
- data/roda-3.105.0/lib/roda/plugins/common_logger.rb +80 -0
- data/roda-3.105.0/lib/roda/plugins/conditional_sessions.rb +67 -0
- data/roda-3.105.0/lib/roda/plugins/content_for.rb +103 -0
- data/roda-3.105.0/lib/roda/plugins/content_security_policy.rb +329 -0
- data/roda-3.105.0/lib/roda/plugins/cookie_flags.rb +157 -0
- data/roda-3.105.0/lib/roda/plugins/cookies.rb +51 -0
- data/roda-3.105.0/lib/roda/plugins/csrf.rb +81 -0
- data/roda-3.105.0/lib/roda/plugins/custom_block_results.rb +85 -0
- data/roda-3.105.0/lib/roda/plugins/custom_matchers.rb +89 -0
- data/roda-3.105.0/lib/roda/plugins/default_headers.rb +64 -0
- data/roda-3.105.0/lib/roda/plugins/default_status.rb +35 -0
- data/roda-3.105.0/lib/roda/plugins/delay_build.rb +18 -0
- data/roda-3.105.0/lib/roda/plugins/delegate.rb +77 -0
- data/roda-3.105.0/lib/roda/plugins/delete_empty_headers.rb +36 -0
- data/roda-3.105.0/lib/roda/plugins/direct_call.rb +38 -0
- data/roda-3.105.0/lib/roda/plugins/disallow_file_uploads.rb +38 -0
- data/roda-3.105.0/lib/roda/plugins/drop_body.rb +43 -0
- data/roda-3.105.0/lib/roda/plugins/each_part.rb +87 -0
- data/roda-3.105.0/lib/roda/plugins/early_hints.rb +25 -0
- data/roda-3.105.0/lib/roda/plugins/empty_root.rb +49 -0
- data/roda-3.105.0/lib/roda/plugins/environments.rb +79 -0
- data/roda-3.105.0/lib/roda/plugins/erb_h.rb +43 -0
- data/roda-3.105.0/lib/roda/plugins/error_email.rb +152 -0
- data/roda-3.105.0/lib/roda/plugins/error_handler.rb +133 -0
- data/roda-3.105.0/lib/roda/plugins/error_mail.rb +149 -0
- data/roda-3.105.0/lib/roda/plugins/exception_page.rb +445 -0
- data/roda-3.105.0/lib/roda/plugins/filter_common_logger.rb +46 -0
- data/roda-3.105.0/lib/roda/plugins/flash.rb +117 -0
- data/roda-3.105.0/lib/roda/plugins/h.rb +59 -0
- data/roda-3.105.0/lib/roda/plugins/halt.rb +108 -0
- data/roda-3.105.0/lib/roda/plugins/hash_branch_view_subdir.rb +76 -0
- data/roda-3.105.0/lib/roda/plugins/hash_branches.rb +145 -0
- data/roda-3.105.0/lib/roda/plugins/hash_matcher.rb +39 -0
- data/roda-3.105.0/lib/roda/plugins/hash_paths.rb +128 -0
- data/roda-3.105.0/lib/roda/plugins/hash_public.rb +125 -0
- data/roda-3.105.0/lib/roda/plugins/hash_public_cache.rb +91 -0
- data/roda-3.105.0/lib/roda/plugins/hash_routes.rb +304 -0
- data/roda-3.105.0/lib/roda/plugins/head.rb +99 -0
- data/roda-3.105.0/lib/roda/plugins/header_matchers.rb +88 -0
- data/roda-3.105.0/lib/roda/plugins/heartbeat.rb +41 -0
- data/roda-3.105.0/lib/roda/plugins/hmac_paths.rb +413 -0
- data/roda-3.105.0/lib/roda/plugins/hooks.rb +92 -0
- data/roda-3.105.0/lib/roda/plugins/host_authorization.rb +155 -0
- data/roda-3.105.0/lib/roda/plugins/host_routing.rb +190 -0
- data/roda-3.105.0/lib/roda/plugins/hsts.rb +35 -0
- data/roda-3.105.0/lib/roda/plugins/indifferent_params.rb +124 -0
- data/roda-3.105.0/lib/roda/plugins/inject_erb.rb +33 -0
- data/roda-3.105.0/lib/roda/plugins/invalid_request_body.rb +107 -0
- data/roda-3.105.0/lib/roda/plugins/ip_from_header.rb +34 -0
- data/roda-3.105.0/lib/roda/plugins/json.rb +119 -0
- data/roda-3.105.0/lib/roda/plugins/json_parser.rb +107 -0
- data/roda-3.105.0/lib/roda/plugins/link_to.rb +83 -0
- data/roda-3.105.0/lib/roda/plugins/mail_processor.rb +629 -0
- data/roda-3.105.0/lib/roda/plugins/mailer.rb +283 -0
- data/roda-3.105.0/lib/roda/plugins/map_matcher.rb +48 -0
- data/roda-3.105.0/lib/roda/plugins/match_affix.rb +64 -0
- data/roda-3.105.0/lib/roda/plugins/match_hook.rb +34 -0
- data/roda-3.105.0/lib/roda/plugins/match_hook_args.rb +93 -0
- data/roda-3.105.0/lib/roda/plugins/middleware.rb +225 -0
- data/roda-3.105.0/lib/roda/plugins/middleware_stack.rb +101 -0
- data/roda-3.105.0/lib/roda/plugins/module_include.rb +96 -0
- data/roda-3.105.0/lib/roda/plugins/multi_public.rb +95 -0
- data/roda-3.105.0/lib/roda/plugins/multi_route.rb +156 -0
- data/roda-3.105.0/lib/roda/plugins/multi_run.rb +144 -0
- data/roda-3.105.0/lib/roda/plugins/multi_view.rb +83 -0
- data/roda-3.105.0/lib/roda/plugins/multibyte_string_matcher.rb +57 -0
- data/roda-3.105.0/lib/roda/plugins/named_routes.rb +167 -0
- data/roda-3.105.0/lib/roda/plugins/named_templates.rb +102 -0
- data/roda-3.105.0/lib/roda/plugins/not_allowed.rb +149 -0
- data/roda-3.105.0/lib/roda/plugins/not_found.rb +55 -0
- data/roda-3.105.0/lib/roda/plugins/optimized_segment_matchers.rb +53 -0
- data/roda-3.105.0/lib/roda/plugins/optimized_string_matchers.rb +50 -0
- data/roda-3.105.0/lib/roda/plugins/padrino_render.rb +42 -0
- data/roda-3.105.0/lib/roda/plugins/param_matchers.rb +83 -0
- data/roda-3.105.0/lib/roda/plugins/params_capturing.rb +116 -0
- data/roda-3.105.0/lib/roda/plugins/part.rb +76 -0
- data/roda-3.105.0/lib/roda/plugins/partials.rb +74 -0
- data/roda-3.105.0/lib/roda/plugins/pass.rb +47 -0
- data/roda-3.105.0/lib/roda/plugins/path.rb +255 -0
- data/roda-3.105.0/lib/roda/plugins/path_matchers.rb +54 -0
- data/roda-3.105.0/lib/roda/plugins/path_rewriter.rb +111 -0
- data/roda-3.105.0/lib/roda/plugins/permissions_policy.rb +336 -0
- data/roda-3.105.0/lib/roda/plugins/placeholder_string_matchers.rb +48 -0
- data/roda-3.105.0/lib/roda/plugins/plain_hash_response_headers.rb +32 -0
- data/roda-3.105.0/lib/roda/plugins/precompile_templates.rb +156 -0
- data/roda-3.105.0/lib/roda/plugins/public.rb +182 -0
- data/roda-3.105.0/lib/roda/plugins/r.rb +35 -0
- data/roda-3.105.0/lib/roda/plugins/recheck_precompiled_assets.rb +107 -0
- data/roda-3.105.0/lib/roda/plugins/redirect_http_to_https.rb +99 -0
- data/roda-3.105.0/lib/roda/plugins/redirect_path.rb +59 -0
- data/roda-3.105.0/lib/roda/plugins/relative_path.rb +74 -0
- data/roda-3.105.0/lib/roda/plugins/render.rb +998 -0
- data/roda-3.105.0/lib/roda/plugins/render_coverage.rb +105 -0
- data/roda-3.105.0/lib/roda/plugins/render_each.rb +224 -0
- data/roda-3.105.0/lib/roda/plugins/render_locals.rb +102 -0
- data/roda-3.105.0/lib/roda/plugins/request_aref.rb +77 -0
- data/roda-3.105.0/lib/roda/plugins/request_headers.rb +81 -0
- data/roda-3.105.0/lib/roda/plugins/response_attachment.rb +94 -0
- data/roda-3.105.0/lib/roda/plugins/response_content_type.rb +79 -0
- data/roda-3.105.0/lib/roda/plugins/response_request.rb +29 -0
- data/roda-3.105.0/lib/roda/plugins/route_block_args.rb +50 -0
- data/roda-3.105.0/lib/roda/plugins/route_csrf.rb +388 -0
- data/roda-3.105.0/lib/roda/plugins/run_append_slash.rb +51 -0
- data/roda-3.105.0/lib/roda/plugins/run_handler.rb +51 -0
- data/roda-3.105.0/lib/roda/plugins/run_require_slash.rb +46 -0
- data/roda-3.105.0/lib/roda/plugins/sec_fetch_site_csrf.rb +131 -0
- data/roda-3.105.0/lib/roda/plugins/send_file.rb +127 -0
- data/roda-3.105.0/lib/roda/plugins/sessions.rb +537 -0
- data/roda-3.105.0/lib/roda/plugins/shared_vars.rb +86 -0
- data/roda-3.105.0/lib/roda/plugins/sinatra_helpers.rb +443 -0
- data/roda-3.105.0/lib/roda/plugins/slash_path_empty.rb +26 -0
- data/roda-3.105.0/lib/roda/plugins/static.rb +42 -0
- data/roda-3.105.0/lib/roda/plugins/static_routing.rb +89 -0
- data/roda-3.105.0/lib/roda/plugins/status_303.rb +34 -0
- data/roda-3.105.0/lib/roda/plugins/status_handler.rb +86 -0
- data/roda-3.105.0/lib/roda/plugins/streaming.rb +170 -0
- data/roda-3.105.0/lib/roda/plugins/strip_path_prefix.rb +33 -0
- data/roda-3.105.0/lib/roda/plugins/symbol_matchers.rb +188 -0
- data/roda-3.105.0/lib/roda/plugins/symbol_status.rb +32 -0
- data/roda-3.105.0/lib/roda/plugins/symbol_views.rb +37 -0
- data/roda-3.105.0/lib/roda/plugins/timestamp_public.rb +78 -0
- data/roda-3.105.0/lib/roda/plugins/type_routing.rb +215 -0
- data/roda-3.105.0/lib/roda/plugins/typecast_params.rb +1183 -0
- data/roda-3.105.0/lib/roda/plugins/typecast_params_sized_integers.rb +108 -0
- data/roda-3.105.0/lib/roda/plugins/unescape_path.rb +41 -0
- data/roda-3.105.0/lib/roda/plugins/view_options.rb +201 -0
- data/roda-3.105.0/lib/roda/plugins/view_subdir_leading_slash.rb +49 -0
- data/roda-3.105.0/lib/roda/plugins.rb +68 -0
- data/roda-3.105.0/lib/roda/request.rb +722 -0
- data/roda-3.105.0/lib/roda/response.rb +221 -0
- data/roda-3.105.0/lib/roda/session_middleware.rb +183 -0
- data/roda-3.105.0/lib/roda/version.rb +18 -0
- data/roda-3.105.0/lib/roda.rb +586 -0
- data/ultra-lite-hub.gemspec +12 -0
- 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
|