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,221 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
3
|
+
begin
|
|
4
|
+
require 'rack/headers'
|
|
5
|
+
rescue LoadError
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
class Roda
|
|
9
|
+
# Contains constants for response headers. This approach is used so that all
|
|
10
|
+
# headers used internally by Roda can be lower case on Rack 3, so that it is
|
|
11
|
+
# possible to use a plain hash of response headers instead of using Rack::Headers.
|
|
12
|
+
module RodaResponseHeaders
|
|
13
|
+
downcase = defined?(Rack::Headers) && Rack::Headers.is_a?(Class)
|
|
14
|
+
|
|
15
|
+
%w'Allow Cache-Control Content-Disposition Content-Encoding Content-Length
|
|
16
|
+
Content-Security-Policy Content-Security-Policy-Report-Only Content-Type
|
|
17
|
+
ETag Expires Last-Modified Link Location Set-Cookie Transfer-Encoding Vary
|
|
18
|
+
Permissions-Policy Permissions-Policy-Report-Only Strict-Transport-Security'.
|
|
19
|
+
each do |value|
|
|
20
|
+
value = value.downcase if downcase
|
|
21
|
+
const_set(value.tr('-', '_').upcase!.to_sym, value.freeze)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Base class used for Roda responses. The instance methods for this
|
|
26
|
+
# class are added by Roda::RodaPlugins::Base::ResponseMethods, the class
|
|
27
|
+
# methods are added by Roda::RodaPlugins::Base::ResponseClassMethods.
|
|
28
|
+
class RodaResponse
|
|
29
|
+
@roda_class = ::Roda
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
module RodaPlugins
|
|
33
|
+
module Base
|
|
34
|
+
# Class methods for RodaResponse
|
|
35
|
+
module ResponseClassMethods
|
|
36
|
+
# Reference to the Roda class related to this response class.
|
|
37
|
+
attr_accessor :roda_class
|
|
38
|
+
|
|
39
|
+
# Since RodaResponse is anonymously subclassed when Roda is subclassed,
|
|
40
|
+
# and then assigned to a constant of the Roda subclass, make inspect
|
|
41
|
+
# reflect the likely name for the class.
|
|
42
|
+
def inspect
|
|
43
|
+
"#{roda_class.inspect}::RodaResponse"
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Instance methods for RodaResponse
|
|
48
|
+
module ResponseMethods
|
|
49
|
+
# The body for the current response.
|
|
50
|
+
attr_reader :body
|
|
51
|
+
|
|
52
|
+
# The hash of response headers for the current response.
|
|
53
|
+
attr_reader :headers
|
|
54
|
+
|
|
55
|
+
# The status code to use for the response. If none is given, will use 200
|
|
56
|
+
# code for non-empty responses and a 404 code for empty responses.
|
|
57
|
+
attr_accessor :status
|
|
58
|
+
|
|
59
|
+
# Set the default headers when creating a response.
|
|
60
|
+
def initialize
|
|
61
|
+
@headers = _initialize_headers
|
|
62
|
+
@body = []
|
|
63
|
+
@length = 0
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Return the response header with the given key. Example:
|
|
67
|
+
#
|
|
68
|
+
# response['Content-Type'] # => 'text/html'
|
|
69
|
+
def [](key)
|
|
70
|
+
@headers[key]
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Set the response header with the given key to the given value.
|
|
74
|
+
#
|
|
75
|
+
# response['Content-Type'] = 'application/json'
|
|
76
|
+
def []=(key, value)
|
|
77
|
+
@headers[key] = value
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# The default headers to use for responses.
|
|
81
|
+
def default_headers
|
|
82
|
+
DEFAULT_HEADERS
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Whether the response body has been written to yet. Note
|
|
86
|
+
# that writing an empty string to the response body marks
|
|
87
|
+
# the response as not empty. Example:
|
|
88
|
+
#
|
|
89
|
+
# response.empty? # => true
|
|
90
|
+
# response.write('a')
|
|
91
|
+
# response.empty? # => false
|
|
92
|
+
def empty?
|
|
93
|
+
@body.empty?
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Return the rack response array of status, headers, and body
|
|
97
|
+
# for the current response. If the status has not been set,
|
|
98
|
+
# uses the return value of default_status if the body has
|
|
99
|
+
# been written to, otherwise uses a 404 status.
|
|
100
|
+
# Adds the Content-Length header to the size of the response body.
|
|
101
|
+
#
|
|
102
|
+
# Example:
|
|
103
|
+
#
|
|
104
|
+
# response.finish
|
|
105
|
+
# # => [200,
|
|
106
|
+
# # {'Content-Type'=>'text/html', 'Content-Length'=>'0'},
|
|
107
|
+
# # []]
|
|
108
|
+
def finish
|
|
109
|
+
b = @body
|
|
110
|
+
set_default_headers
|
|
111
|
+
h = @headers
|
|
112
|
+
|
|
113
|
+
if b.empty?
|
|
114
|
+
s = @status || 404
|
|
115
|
+
if (s == 304 || s == 204 || (s >= 100 && s <= 199))
|
|
116
|
+
h.delete(RodaResponseHeaders::CONTENT_TYPE)
|
|
117
|
+
elsif s == 205
|
|
118
|
+
empty_205_headers(h)
|
|
119
|
+
else
|
|
120
|
+
h[RodaResponseHeaders::CONTENT_LENGTH] ||= '0'
|
|
121
|
+
end
|
|
122
|
+
else
|
|
123
|
+
s = @status || default_status
|
|
124
|
+
h[RodaResponseHeaders::CONTENT_LENGTH] ||= @length.to_s
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
[s, h, b]
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# Return the rack response array using a given body. Assumes a
|
|
131
|
+
# 200 response status unless status has been explicitly set,
|
|
132
|
+
# and doesn't add the Content-Length header or use the existing
|
|
133
|
+
# body.
|
|
134
|
+
def finish_with_body(body)
|
|
135
|
+
set_default_headers
|
|
136
|
+
[@status || default_status, @headers, body]
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Return the default response status to be used when the body
|
|
140
|
+
# has been written to. This is split out to make overriding
|
|
141
|
+
# easier in plugins.
|
|
142
|
+
def default_status
|
|
143
|
+
200
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# Show response class, status code, response headers, and response body
|
|
147
|
+
def inspect
|
|
148
|
+
"#<#{self.class.inspect} #{@status.inspect} #{@headers.inspect} #{@body.inspect}>"
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# Set the Location header to the given path, and the status
|
|
152
|
+
# to the given status. Example:
|
|
153
|
+
#
|
|
154
|
+
# response.redirect('foo', 301)
|
|
155
|
+
# response.redirect('bar')
|
|
156
|
+
def redirect(path, status = 302)
|
|
157
|
+
@headers[RodaResponseHeaders::LOCATION] = path
|
|
158
|
+
@status = status
|
|
159
|
+
nil
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# Return the Roda class related to this response.
|
|
163
|
+
def roda_class
|
|
164
|
+
self.class.roda_class
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# Write to the response body. Returns nil.
|
|
168
|
+
#
|
|
169
|
+
# response.write('foo')
|
|
170
|
+
def write(str)
|
|
171
|
+
s = str.to_s
|
|
172
|
+
@length += s.bytesize
|
|
173
|
+
@body << s
|
|
174
|
+
nil
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
private
|
|
178
|
+
|
|
179
|
+
if defined?(Rack::Headers) && Rack::Headers.is_a?(Class)
|
|
180
|
+
DEFAULT_HEADERS = Rack::Headers[{RodaResponseHeaders::CONTENT_TYPE => "text/html".freeze}].freeze
|
|
181
|
+
|
|
182
|
+
# Use Rack::Headers for headers by default on Rack 3
|
|
183
|
+
def _initialize_headers
|
|
184
|
+
Rack::Headers.new
|
|
185
|
+
end
|
|
186
|
+
else
|
|
187
|
+
DEFAULT_HEADERS = {RodaResponseHeaders::CONTENT_TYPE => "text/html".freeze}.freeze
|
|
188
|
+
|
|
189
|
+
# Use plain hash for headers by default on Rack 1-2
|
|
190
|
+
def _initialize_headers
|
|
191
|
+
{}
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
if Rack.release < '2.0.2'
|
|
196
|
+
# Don't use a content length for empty 205 responses on
|
|
197
|
+
# rack 1, as it violates Rack::Lint in that version.
|
|
198
|
+
def empty_205_headers(headers)
|
|
199
|
+
headers.delete(RodaResponseHeaders::CONTENT_TYPE)
|
|
200
|
+
headers.delete(RodaResponseHeaders::CONTENT_LENGTH)
|
|
201
|
+
end
|
|
202
|
+
else
|
|
203
|
+
# Set the content length for empty 205 responses to 0
|
|
204
|
+
def empty_205_headers(headers)
|
|
205
|
+
headers.delete(RodaResponseHeaders::CONTENT_TYPE)
|
|
206
|
+
headers[RodaResponseHeaders::CONTENT_LENGTH] = '0'
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
# For each default header, if a header has not already been set for the
|
|
211
|
+
# response, set the header in the response.
|
|
212
|
+
def set_default_headers
|
|
213
|
+
h = @headers
|
|
214
|
+
default_headers.each do |k,v|
|
|
215
|
+
h[k] ||= v
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
end
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../roda'
|
|
4
|
+
require_relative 'plugins/sessions'
|
|
5
|
+
|
|
6
|
+
# Session middleware that can be used in any Rack application
|
|
7
|
+
# that uses Roda's sessions plugin for encrypted and signed cookies.
|
|
8
|
+
# See Roda::RodaPlugins::Sessions for details on options.
|
|
9
|
+
class RodaSessionMiddleware
|
|
10
|
+
# Class to hold session data. This is designed to mimic the API
|
|
11
|
+
# of Rack::Session::Abstract::SessionHash, but is simpler and faster.
|
|
12
|
+
# Undocumented methods operate the same as hash methods, but load the
|
|
13
|
+
# session from the cookie if it hasn't been loaded yet, and convert
|
|
14
|
+
# keys to strings.
|
|
15
|
+
#
|
|
16
|
+
# One difference between SessionHash and Rack::Session::Abstract::SessionHash
|
|
17
|
+
# is that SessionHash does not attempt to setup a session id, since
|
|
18
|
+
# one is not needed for cookie-based sessions, only for sessions
|
|
19
|
+
# that are loaded out of a database. If you need to have a session id
|
|
20
|
+
# for other reasons, manually create a session id using a randomly generated
|
|
21
|
+
# string.
|
|
22
|
+
class SessionHash
|
|
23
|
+
# The Roda::RodaRequest subclass instance related to the session.
|
|
24
|
+
attr_reader :req
|
|
25
|
+
|
|
26
|
+
# The underlying data hash, or nil if the session has not yet been
|
|
27
|
+
# loaded.
|
|
28
|
+
attr_reader :data
|
|
29
|
+
|
|
30
|
+
def initialize(req)
|
|
31
|
+
@req = req
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# The Roda sessions plugin options used by the middleware for this
|
|
35
|
+
# session hash.
|
|
36
|
+
def options
|
|
37
|
+
@req.roda_class.opts[:sessions]
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def each(&block)
|
|
41
|
+
load!
|
|
42
|
+
@data.each(&block)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def [](key)
|
|
46
|
+
load!
|
|
47
|
+
@data[key.to_s]
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def fetch(key, default = (no_default = true), &block)
|
|
51
|
+
load!
|
|
52
|
+
if no_default
|
|
53
|
+
@data.fetch(key.to_s, &block)
|
|
54
|
+
else
|
|
55
|
+
@data.fetch(key.to_s, default, &block)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def has_key?(key)
|
|
60
|
+
load!
|
|
61
|
+
@data.has_key?(key.to_s)
|
|
62
|
+
end
|
|
63
|
+
alias :key? :has_key?
|
|
64
|
+
alias :include? :has_key?
|
|
65
|
+
|
|
66
|
+
def []=(key, value)
|
|
67
|
+
load!
|
|
68
|
+
@data[key.to_s] = value
|
|
69
|
+
end
|
|
70
|
+
alias :store :[]=
|
|
71
|
+
|
|
72
|
+
# Clear the session, also removing a couple of roda session
|
|
73
|
+
# keys from the environment so that the related cookie will
|
|
74
|
+
# either be set or cleared in the rack response.
|
|
75
|
+
def clear
|
|
76
|
+
load!
|
|
77
|
+
env = @req.env
|
|
78
|
+
env.delete('roda.session.created_at')
|
|
79
|
+
env.delete('roda.session.updated_at')
|
|
80
|
+
@data.clear
|
|
81
|
+
end
|
|
82
|
+
alias :destroy :clear
|
|
83
|
+
|
|
84
|
+
def to_hash
|
|
85
|
+
load!
|
|
86
|
+
@data.dup
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def update(hash)
|
|
90
|
+
load!
|
|
91
|
+
hash.each do |key, value|
|
|
92
|
+
@data[key.to_s] = value
|
|
93
|
+
end
|
|
94
|
+
@data
|
|
95
|
+
end
|
|
96
|
+
alias :merge! :update
|
|
97
|
+
|
|
98
|
+
def replace(hash)
|
|
99
|
+
load!
|
|
100
|
+
@data.clear
|
|
101
|
+
update(hash)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def delete(key)
|
|
105
|
+
load!
|
|
106
|
+
@data.delete(key.to_s)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# If the session hasn't been loaded, display that.
|
|
110
|
+
def inspect
|
|
111
|
+
if loaded?
|
|
112
|
+
@data.inspect
|
|
113
|
+
else
|
|
114
|
+
"#<#{self.class}:0x#{self.object_id.to_s(16)} not yet loaded>"
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Return whether the session cookie already exists.
|
|
119
|
+
# If this is false, then the session was set to an empty hash.
|
|
120
|
+
def exists?
|
|
121
|
+
load!
|
|
122
|
+
req.env.has_key?('roda.session.serialized')
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Whether the session has already been loaded from the cookie yet.
|
|
126
|
+
def loaded?
|
|
127
|
+
!!defined?(@data)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def empty?
|
|
131
|
+
load!
|
|
132
|
+
@data.empty?
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def keys
|
|
136
|
+
load!
|
|
137
|
+
@data.keys
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def values
|
|
141
|
+
load!
|
|
142
|
+
@data.values
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
private
|
|
146
|
+
|
|
147
|
+
# Load the session from the cookie.
|
|
148
|
+
def load!
|
|
149
|
+
@data ||= @req.send(:_load_session)
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
module RequestMethods
|
|
154
|
+
# Work around for if type_routing plugin is loaded into Roda class itself.
|
|
155
|
+
def _remaining_path(_)
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# Setup the middleware, passing +opts+ as the Roda sessions plugin options.
|
|
160
|
+
def initialize(app, opts)
|
|
161
|
+
mid = Class.new(Roda)
|
|
162
|
+
Roda::RodaPlugins.set_temp_name(mid){"RodaSessionMiddleware::_RodaSubclass"}
|
|
163
|
+
mid.plugin :sessions, opts
|
|
164
|
+
@req_class = mid::RodaRequest
|
|
165
|
+
@req_class.send(:include, RequestMethods)
|
|
166
|
+
@app = app
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# Initialize the session hash in the environment before calling the next
|
|
170
|
+
# application, and if the session has been loaded after the result has been
|
|
171
|
+
# returned, then persist the session in the cookie.
|
|
172
|
+
def call(env)
|
|
173
|
+
session = env['rack.session'] = SessionHash.new(@req_class.new(nil, env))
|
|
174
|
+
|
|
175
|
+
res = @app.call(env)
|
|
176
|
+
|
|
177
|
+
if session.loaded?
|
|
178
|
+
session.req.persist_session(res[1], session.data)
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
res
|
|
182
|
+
end
|
|
183
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
class Roda
|
|
2
|
+
# The major version of Roda, updated only for major changes that are
|
|
3
|
+
# likely to require modification to Roda apps.
|
|
4
|
+
RodaMajorVersion = 3
|
|
5
|
+
|
|
6
|
+
# The minor version of Roda, updated for new feature releases of Roda.
|
|
7
|
+
RodaMinorVersion = 105
|
|
8
|
+
|
|
9
|
+
# The patch version of Roda, updated only for bug fixes from the last
|
|
10
|
+
# feature release.
|
|
11
|
+
RodaPatchVersion = 0
|
|
12
|
+
|
|
13
|
+
# The full version of Roda as a string.
|
|
14
|
+
RodaVersion = "#{RodaMajorVersion}.#{RodaMinorVersion}.#{RodaPatchVersion}".freeze
|
|
15
|
+
|
|
16
|
+
# The full version of Roda as a number (3.7.0 => 30070)
|
|
17
|
+
RodaVersionNumber = RodaMajorVersion*10000 + RodaMinorVersion*10 + RodaPatchVersion
|
|
18
|
+
end
|