ultra-max-sys 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ultra-max-sys might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/roda-3.106.0/MIT-LICENSE +21 -0
- data/roda-3.106.0/lib/roda/cache.rb +42 -0
- data/roda-3.106.0/lib/roda/plugins/Integer_matcher_max.rb +55 -0
- data/roda-3.106.0/lib/roda/plugins/_after_hook.rb +11 -0
- data/roda-3.106.0/lib/roda/plugins/_base64.rb +34 -0
- data/roda-3.106.0/lib/roda/plugins/_before_hook.rb +41 -0
- data/roda-3.106.0/lib/roda/plugins/_optimized_matching.rb +227 -0
- data/roda-3.106.0/lib/roda/plugins/_symbol_class_matchers.rb +108 -0
- data/roda-3.106.0/lib/roda/plugins/_symbol_regexp_matchers.rb +24 -0
- data/roda-3.106.0/lib/roda/plugins/additional_render_engines.rb +61 -0
- data/roda-3.106.0/lib/roda/plugins/additional_view_directories.rb +66 -0
- data/roda-3.106.0/lib/roda/plugins/all_verbs.rb +50 -0
- data/roda-3.106.0/lib/roda/plugins/assets.rb +902 -0
- data/roda-3.106.0/lib/roda/plugins/assets_preloading.rb +89 -0
- data/roda-3.106.0/lib/roda/plugins/assume_ssl.rb +28 -0
- data/roda-3.106.0/lib/roda/plugins/autoload_hash_branches.rb +79 -0
- data/roda-3.106.0/lib/roda/plugins/autoload_named_routes.rb +65 -0
- data/roda-3.106.0/lib/roda/plugins/backtracking_array.rb +88 -0
- data/roda-3.106.0/lib/roda/plugins/bearer_token.rb +28 -0
- data/roda-3.106.0/lib/roda/plugins/branch_locals.rb +76 -0
- data/roda-3.106.0/lib/roda/plugins/break.rb +43 -0
- data/roda-3.106.0/lib/roda/plugins/caching.rb +206 -0
- data/roda-3.106.0/lib/roda/plugins/capture_erb.rb +94 -0
- data/roda-3.106.0/lib/roda/plugins/chunked.rb +333 -0
- data/roda-3.106.0/lib/roda/plugins/class_level_routing.rb +111 -0
- data/roda-3.106.0/lib/roda/plugins/class_matchers.rb +155 -0
- data/roda-3.106.0/lib/roda/plugins/common_logger.rb +82 -0
- data/roda-3.106.0/lib/roda/plugins/conditional_sessions.rb +67 -0
- data/roda-3.106.0/lib/roda/plugins/content_for.rb +105 -0
- data/roda-3.106.0/lib/roda/plugins/content_security_policy.rb +333 -0
- data/roda-3.106.0/lib/roda/plugins/cookie_flags.rb +157 -0
- data/roda-3.106.0/lib/roda/plugins/cookies.rb +51 -0
- data/roda-3.106.0/lib/roda/plugins/csrf.rb +81 -0
- data/roda-3.106.0/lib/roda/plugins/custom_block_results.rb +85 -0
- data/roda-3.106.0/lib/roda/plugins/custom_matchers.rb +89 -0
- data/roda-3.106.0/lib/roda/plugins/default_headers.rb +64 -0
- data/roda-3.106.0/lib/roda/plugins/default_status.rb +35 -0
- data/roda-3.106.0/lib/roda/plugins/delay_build.rb +18 -0
- data/roda-3.106.0/lib/roda/plugins/delegate.rb +77 -0
- data/roda-3.106.0/lib/roda/plugins/delete_empty_headers.rb +36 -0
- data/roda-3.106.0/lib/roda/plugins/direct_call.rb +38 -0
- data/roda-3.106.0/lib/roda/plugins/disallow_file_uploads.rb +38 -0
- data/roda-3.106.0/lib/roda/plugins/drop_body.rb +43 -0
- data/roda-3.106.0/lib/roda/plugins/each_part.rb +87 -0
- data/roda-3.106.0/lib/roda/plugins/early_hints.rb +25 -0
- data/roda-3.106.0/lib/roda/plugins/empty_root.rb +49 -0
- data/roda-3.106.0/lib/roda/plugins/environments.rb +79 -0
- data/roda-3.106.0/lib/roda/plugins/erb_h.rb +43 -0
- data/roda-3.106.0/lib/roda/plugins/error_email.rb +152 -0
- data/roda-3.106.0/lib/roda/plugins/error_handler.rb +133 -0
- data/roda-3.106.0/lib/roda/plugins/error_mail.rb +149 -0
- data/roda-3.106.0/lib/roda/plugins/exception_page.rb +445 -0
- data/roda-3.106.0/lib/roda/plugins/filter_common_logger.rb +46 -0
- data/roda-3.106.0/lib/roda/plugins/flash.rb +119 -0
- data/roda-3.106.0/lib/roda/plugins/h.rb +59 -0
- data/roda-3.106.0/lib/roda/plugins/halt.rb +108 -0
- data/roda-3.106.0/lib/roda/plugins/hash_branch_view_subdir.rb +76 -0
- data/roda-3.106.0/lib/roda/plugins/hash_branches.rb +145 -0
- data/roda-3.106.0/lib/roda/plugins/hash_matcher.rb +39 -0
- data/roda-3.106.0/lib/roda/plugins/hash_paths.rb +128 -0
- data/roda-3.106.0/lib/roda/plugins/hash_public.rb +125 -0
- data/roda-3.106.0/lib/roda/plugins/hash_public_cache.rb +91 -0
- data/roda-3.106.0/lib/roda/plugins/hash_routes.rb +304 -0
- data/roda-3.106.0/lib/roda/plugins/head.rb +99 -0
- data/roda-3.106.0/lib/roda/plugins/header_matchers.rb +88 -0
- data/roda-3.106.0/lib/roda/plugins/heartbeat.rb +41 -0
- data/roda-3.106.0/lib/roda/plugins/hmac_paths.rb +413 -0
- data/roda-3.106.0/lib/roda/plugins/hooks.rb +92 -0
- data/roda-3.106.0/lib/roda/plugins/host_authorization.rb +155 -0
- data/roda-3.106.0/lib/roda/plugins/host_routing.rb +194 -0
- data/roda-3.106.0/lib/roda/plugins/hsts.rb +35 -0
- data/roda-3.106.0/lib/roda/plugins/indifferent_params.rb +126 -0
- data/roda-3.106.0/lib/roda/plugins/inject_erb.rb +33 -0
- data/roda-3.106.0/lib/roda/plugins/invalid_request_body.rb +107 -0
- data/roda-3.106.0/lib/roda/plugins/ip_from_header.rb +34 -0
- data/roda-3.106.0/lib/roda/plugins/json.rb +119 -0
- data/roda-3.106.0/lib/roda/plugins/json_parser.rb +107 -0
- data/roda-3.106.0/lib/roda/plugins/link_to.rb +83 -0
- data/roda-3.106.0/lib/roda/plugins/mail_processor.rb +629 -0
- data/roda-3.106.0/lib/roda/plugins/mailer.rb +285 -0
- data/roda-3.106.0/lib/roda/plugins/map_matcher.rb +48 -0
- data/roda-3.106.0/lib/roda/plugins/match_affix.rb +64 -0
- data/roda-3.106.0/lib/roda/plugins/match_hook.rb +34 -0
- data/roda-3.106.0/lib/roda/plugins/match_hook_args.rb +93 -0
- data/roda-3.106.0/lib/roda/plugins/middleware.rb +225 -0
- data/roda-3.106.0/lib/roda/plugins/middleware_stack.rb +101 -0
- data/roda-3.106.0/lib/roda/plugins/module_include.rb +96 -0
- data/roda-3.106.0/lib/roda/plugins/multi_public.rb +95 -0
- data/roda-3.106.0/lib/roda/plugins/multi_route.rb +156 -0
- data/roda-3.106.0/lib/roda/plugins/multi_run.rb +144 -0
- data/roda-3.106.0/lib/roda/plugins/multi_view.rb +83 -0
- data/roda-3.106.0/lib/roda/plugins/multibyte_string_matcher.rb +57 -0
- data/roda-3.106.0/lib/roda/plugins/named_routes.rb +167 -0
- data/roda-3.106.0/lib/roda/plugins/named_templates.rb +102 -0
- data/roda-3.106.0/lib/roda/plugins/not_allowed.rb +151 -0
- data/roda-3.106.0/lib/roda/plugins/not_found.rb +55 -0
- data/roda-3.106.0/lib/roda/plugins/optimized_segment_matchers.rb +53 -0
- data/roda-3.106.0/lib/roda/plugins/optimized_string_matchers.rb +50 -0
- data/roda-3.106.0/lib/roda/plugins/padrino_render.rb +42 -0
- data/roda-3.106.0/lib/roda/plugins/param_matchers.rb +83 -0
- data/roda-3.106.0/lib/roda/plugins/params_capturing.rb +118 -0
- data/roda-3.106.0/lib/roda/plugins/part.rb +76 -0
- data/roda-3.106.0/lib/roda/plugins/partials.rb +74 -0
- data/roda-3.106.0/lib/roda/plugins/pass.rb +47 -0
- data/roda-3.106.0/lib/roda/plugins/path.rb +255 -0
- data/roda-3.106.0/lib/roda/plugins/path_matchers.rb +54 -0
- data/roda-3.106.0/lib/roda/plugins/path_rewriter.rb +111 -0
- data/roda-3.106.0/lib/roda/plugins/permissions_policy.rb +340 -0
- data/roda-3.106.0/lib/roda/plugins/placeholder_string_matchers.rb +48 -0
- data/roda-3.106.0/lib/roda/plugins/plain_hash_response_headers.rb +32 -0
- data/roda-3.106.0/lib/roda/plugins/precompile_templates.rb +156 -0
- data/roda-3.106.0/lib/roda/plugins/public.rb +182 -0
- data/roda-3.106.0/lib/roda/plugins/r.rb +35 -0
- data/roda-3.106.0/lib/roda/plugins/recheck_precompiled_assets.rb +107 -0
- data/roda-3.106.0/lib/roda/plugins/redirect_http_to_https.rb +99 -0
- data/roda-3.106.0/lib/roda/plugins/redirect_path.rb +59 -0
- data/roda-3.106.0/lib/roda/plugins/relative_path.rb +76 -0
- data/roda-3.106.0/lib/roda/plugins/render.rb +998 -0
- data/roda-3.106.0/lib/roda/plugins/render_coverage.rb +105 -0
- data/roda-3.106.0/lib/roda/plugins/render_each.rb +224 -0
- data/roda-3.106.0/lib/roda/plugins/render_locals.rb +102 -0
- data/roda-3.106.0/lib/roda/plugins/request_aref.rb +77 -0
- data/roda-3.106.0/lib/roda/plugins/request_headers.rb +83 -0
- data/roda-3.106.0/lib/roda/plugins/response_attachment.rb +94 -0
- data/roda-3.106.0/lib/roda/plugins/response_content_type.rb +79 -0
- data/roda-3.106.0/lib/roda/plugins/response_request.rb +36 -0
- data/roda-3.106.0/lib/roda/plugins/route_block_args.rb +50 -0
- data/roda-3.106.0/lib/roda/plugins/route_csrf.rb +388 -0
- data/roda-3.106.0/lib/roda/plugins/run_append_slash.rb +51 -0
- data/roda-3.106.0/lib/roda/plugins/run_handler.rb +51 -0
- data/roda-3.106.0/lib/roda/plugins/run_require_slash.rb +46 -0
- data/roda-3.106.0/lib/roda/plugins/sec_fetch_site_csrf.rb +131 -0
- data/roda-3.106.0/lib/roda/plugins/send_file.rb +127 -0
- data/roda-3.106.0/lib/roda/plugins/sessions.rb +537 -0
- data/roda-3.106.0/lib/roda/plugins/shape_friendly.rb +232 -0
- data/roda-3.106.0/lib/roda/plugins/shared_vars.rb +86 -0
- data/roda-3.106.0/lib/roda/plugins/sinatra_helpers.rb +444 -0
- data/roda-3.106.0/lib/roda/plugins/slash_path_empty.rb +26 -0
- data/roda-3.106.0/lib/roda/plugins/static.rb +42 -0
- data/roda-3.106.0/lib/roda/plugins/static_routing.rb +89 -0
- data/roda-3.106.0/lib/roda/plugins/status_303.rb +34 -0
- data/roda-3.106.0/lib/roda/plugins/status_handler.rb +86 -0
- data/roda-3.106.0/lib/roda/plugins/streaming.rb +170 -0
- data/roda-3.106.0/lib/roda/plugins/strip_path_prefix.rb +33 -0
- data/roda-3.106.0/lib/roda/plugins/symbol_matchers.rb +188 -0
- data/roda-3.106.0/lib/roda/plugins/symbol_status.rb +32 -0
- data/roda-3.106.0/lib/roda/plugins/symbol_views.rb +37 -0
- data/roda-3.106.0/lib/roda/plugins/timestamp_public.rb +78 -0
- data/roda-3.106.0/lib/roda/plugins/type_routing.rb +217 -0
- data/roda-3.106.0/lib/roda/plugins/typecast_params.rb +1185 -0
- data/roda-3.106.0/lib/roda/plugins/typecast_params_sized_integers.rb +108 -0
- data/roda-3.106.0/lib/roda/plugins/unescape_path.rb +41 -0
- data/roda-3.106.0/lib/roda/plugins/view_options.rb +203 -0
- data/roda-3.106.0/lib/roda/plugins/view_subdir_leading_slash.rb +49 -0
- data/roda-3.106.0/lib/roda/plugins.rb +68 -0
- data/roda-3.106.0/lib/roda/request.rb +722 -0
- data/roda-3.106.0/lib/roda/response.rb +221 -0
- data/roda-3.106.0/lib/roda/session_middleware.rb +184 -0
- data/roda-3.106.0/lib/roda/version.rb +18 -0
- data/roda-3.106.0/lib/roda.rb +741 -0
- data/ultra-max-sys.gemspec +12 -0
- metadata +202 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
3
|
+
require 'tilt'
|
|
4
|
+
# :nocov:
|
|
5
|
+
raise 'Tilt version does not support coverable templates' unless Tilt::Template.method_defined?(:compiled_path=)
|
|
6
|
+
# :nocov:
|
|
7
|
+
|
|
8
|
+
#
|
|
9
|
+
class Roda
|
|
10
|
+
module RodaPlugins
|
|
11
|
+
# The render_coverage plugin builds on top of the render plugin
|
|
12
|
+
# and sets compiled_path on created templates. This allows
|
|
13
|
+
# Ruby's coverage library before Ruby 3.2 to consider code created
|
|
14
|
+
# by templates. You may not need this plugin on Ruby 3.2+, since
|
|
15
|
+
# on Ruby 3.2+, coverage can consider code loaded with +eval+.
|
|
16
|
+
# This plugin is only supported when using tilt 2.1+, since it
|
|
17
|
+
# requires the compiled_path supported added in tilt 2.1.
|
|
18
|
+
#
|
|
19
|
+
# By default, the render_coverage plugin will use +coverage/views+
|
|
20
|
+
# as the directory containing the compiled template files. You can
|
|
21
|
+
# change this by passing the :dir option when loading the plugin.
|
|
22
|
+
# By default, the plugin will set the compiled_path by taking the
|
|
23
|
+
# template file path, stripping off any of the allowed_paths used
|
|
24
|
+
# by the render plugin, and converting slashes to dashes. You can
|
|
25
|
+
# override the allowed_paths to strip by passing the :strip_paths
|
|
26
|
+
# option when loading the plugin. Paths outside :strip_paths (or
|
|
27
|
+
# the render plugin allowed_paths if :strip_paths is not set) will
|
|
28
|
+
# not have a compiled_path set.
|
|
29
|
+
#
|
|
30
|
+
# Due to how Ruby's coverage library works in regards to loading
|
|
31
|
+
# a compiled template file with identical code more than once,
|
|
32
|
+
# it may be beneficial to run coverage testing with the
|
|
33
|
+
# +RODA_RENDER_COMPILED_METHOD_SUPPORT+ environment variable set
|
|
34
|
+
# to +no+ if using this plugin.
|
|
35
|
+
module RenderCoverage
|
|
36
|
+
def self.load_dependencies(app, opts=OPTS)
|
|
37
|
+
app.plugin :render
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Use the :dir option to set the directory to store the compiled
|
|
41
|
+
# template files, and the :strip_paths directory for paths to
|
|
42
|
+
# strip.
|
|
43
|
+
def self.configure(app, opts=OPTS)
|
|
44
|
+
app.opts[:render_coverage_strip_paths] = opts[:strip_paths].map{|f| File.expand_path(f)} if opts.has_key?(:strip_paths)
|
|
45
|
+
coverage_dir = app.opts[:render_coverage_dir] = opts[:dir] || app.opts[:render_coverage_dir] || 'coverage/views'
|
|
46
|
+
Dir.mkdir(coverage_dir) unless File.directory?(coverage_dir)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
module ClassMethods
|
|
50
|
+
# Set a compiled path on the created template, if the path for
|
|
51
|
+
# the template is in one of the allowed_views.
|
|
52
|
+
def create_template(opts, template_opts)
|
|
53
|
+
return super if opts[:template_block]
|
|
54
|
+
|
|
55
|
+
path = File.expand_path(opts[:path])
|
|
56
|
+
compiled_path = nil
|
|
57
|
+
(self.opts[:render_coverage_strip_paths] || render_opts[:allowed_paths]).each do |dir|
|
|
58
|
+
if path.start_with?(dir + '/')
|
|
59
|
+
compiled_path = File.join(self.opts[:render_coverage_dir], path[dir.length+1, 10000000].tr('/', '-'))
|
|
60
|
+
break
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# For Tilt 2.6+, when using :scope_class and fixed locals, must provide
|
|
65
|
+
# compiled path as option, since compilation happens during initalization
|
|
66
|
+
# in that case. This option should be ignored if the template does not
|
|
67
|
+
# support it, but some template class may break if the option is not
|
|
68
|
+
# handled, so for compatibility, only set the method if Tilt::Template
|
|
69
|
+
# will handle it.
|
|
70
|
+
if compiled_path && Tilt::Template.method_defined?(:fixed_locals?)
|
|
71
|
+
template_opts = template_opts.dup
|
|
72
|
+
template_opts[:compiled_path] = compiled_path
|
|
73
|
+
compiled_path = nil
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
template = super
|
|
77
|
+
|
|
78
|
+
# Set compiled path for template when using older tilt versions.
|
|
79
|
+
# :nocov:
|
|
80
|
+
template.compiled_path = compiled_path if compiled_path
|
|
81
|
+
# :nocov:
|
|
82
|
+
|
|
83
|
+
template
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
module InstanceMethods
|
|
88
|
+
private
|
|
89
|
+
|
|
90
|
+
# Convert template paths to real paths to try to ensure the same template is cached.
|
|
91
|
+
def template_path(opts)
|
|
92
|
+
path = super
|
|
93
|
+
|
|
94
|
+
if File.file?(path)
|
|
95
|
+
File.realpath(path)
|
|
96
|
+
else
|
|
97
|
+
path
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
register_plugin(:render_coverage, RenderCoverage)
|
|
104
|
+
end
|
|
105
|
+
end
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'render'
|
|
4
|
+
|
|
5
|
+
#
|
|
6
|
+
class Roda
|
|
7
|
+
module RodaPlugins
|
|
8
|
+
# The render_each plugin allows you to render a template for each
|
|
9
|
+
# value in an enumerable, returning the concatention of all of the
|
|
10
|
+
# template renderings. For example:
|
|
11
|
+
#
|
|
12
|
+
# render_each([1,2,3], :foo)
|
|
13
|
+
#
|
|
14
|
+
# will render the +foo+ template 3 times. Each time the template
|
|
15
|
+
# is rendered, the local variable +foo+ will contain the given
|
|
16
|
+
# value (e.g. on the first rendering +foo+ is 1).
|
|
17
|
+
#
|
|
18
|
+
# If you provide a block when calling the method, it will yield
|
|
19
|
+
# each rendering instead of returning a concatentation of the
|
|
20
|
+
# renderings. This is useful if you want to wrap each rendering in
|
|
21
|
+
# something else. For example, instead of calling +render+ multiple
|
|
22
|
+
# times in a loop:
|
|
23
|
+
#
|
|
24
|
+
# <% [1,2,3].each do |v| %>
|
|
25
|
+
# <p><%= render(:foo, locals: {foo: v}) %></p>
|
|
26
|
+
# <% end %>
|
|
27
|
+
#
|
|
28
|
+
# You can use +render_each+, allowing for simpler and more optimized
|
|
29
|
+
# code:
|
|
30
|
+
#
|
|
31
|
+
# <% render_each([1,2,3], :foo) do |text| %>
|
|
32
|
+
# <p><%= text %></p>
|
|
33
|
+
# <% end %>
|
|
34
|
+
#
|
|
35
|
+
# You can also provide a block to avoid excess memory usage. For
|
|
36
|
+
# example, if you are calling the method inside an erb template,
|
|
37
|
+
# instead of doing:
|
|
38
|
+
#
|
|
39
|
+
# <%= render_each([1,2,3], :foo) %>
|
|
40
|
+
#
|
|
41
|
+
# You can do:
|
|
42
|
+
#
|
|
43
|
+
# <% render_each([1,2,3], :foo) %><%= body %><% end %>
|
|
44
|
+
#
|
|
45
|
+
# This results in the same behavior, but avoids building a large
|
|
46
|
+
# intermediate string just to concatenate to the template result.
|
|
47
|
+
#
|
|
48
|
+
# When passing a block, +render_each+ returns +nil+.
|
|
49
|
+
#
|
|
50
|
+
# You can pass additional render options via an options hash:
|
|
51
|
+
#
|
|
52
|
+
# render_each([1,2,3], :foo, views: 'partials')
|
|
53
|
+
#
|
|
54
|
+
# One additional option supported by is +:local+, which sets the
|
|
55
|
+
# local variable containing the current value to use. So:
|
|
56
|
+
#
|
|
57
|
+
# render_each([1,2,3], :foo, local: :bar)
|
|
58
|
+
#
|
|
59
|
+
# Will render the +foo+ template, but the local variable used inside
|
|
60
|
+
# the template will be +bar+. You can use <tt>local: nil</tt> to
|
|
61
|
+
# not set a local variable inside the template. By default, the
|
|
62
|
+
# local variable name is based on the template name, with any
|
|
63
|
+
# directories and file extensions removed.
|
|
64
|
+
module RenderEach
|
|
65
|
+
# Load the render plugin before this plugin, since this plugin
|
|
66
|
+
# calls the render method.
|
|
67
|
+
def self.load_dependencies(app)
|
|
68
|
+
app.plugin :render
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
ALLOWED_KEYS = [:locals, :local].freeze
|
|
72
|
+
|
|
73
|
+
if Render::COMPILED_METHOD_SUPPORT
|
|
74
|
+
module ClassMethods
|
|
75
|
+
# If using compiled methods and assuming fixed locals, optimize
|
|
76
|
+
# _cached_render_each_template_method.
|
|
77
|
+
def freeze
|
|
78
|
+
if render_opts[:assume_fixed_locals] && !render_opts[:check_template_mtime]
|
|
79
|
+
include AssumeFixedLocalsInstanceMethods
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
super
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
module AssumeFixedLocalsInstanceMethods
|
|
87
|
+
private
|
|
88
|
+
|
|
89
|
+
# Optimize method since this module is only loaded when using fixed locals
|
|
90
|
+
# and when caching templates.
|
|
91
|
+
def _cached_render_each_template_method(template)
|
|
92
|
+
case template
|
|
93
|
+
when String, Symbol
|
|
94
|
+
_cached_template_method_lookup(render_opts[:template_method_cache], template)
|
|
95
|
+
else
|
|
96
|
+
false
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
module InstanceMethods
|
|
103
|
+
# For each value in enum, render the given template using the
|
|
104
|
+
# given opts. The template and options hash are passed to +render+.
|
|
105
|
+
# Additional options supported:
|
|
106
|
+
# :local :: The local variable to use for the current enum value
|
|
107
|
+
# inside the template. An explicit +nil+ value does not
|
|
108
|
+
# set a local variable. If not set, uses the template name.
|
|
109
|
+
def render_each(enum, template, opts=(no_opts = true; optimized_template = _cached_render_each_template_method(template); OPTS), &block)
|
|
110
|
+
if optimized_template
|
|
111
|
+
return _optimized_render_each(enum, optimized_template, render_each_default_local(template), {}, &block)
|
|
112
|
+
elsif opts.has_key?(:local)
|
|
113
|
+
as = opts[:local]
|
|
114
|
+
else
|
|
115
|
+
as = render_each_default_local(template)
|
|
116
|
+
if no_opts && optimized_template.nil? && (optimized_template = _optimized_render_method_for_locals(template, (locals = {as=>nil})))
|
|
117
|
+
return _optimized_render_each(enum, optimized_template, as, locals, &block)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
if as
|
|
122
|
+
opts = opts.dup
|
|
123
|
+
if locals
|
|
124
|
+
opts[:locals] = locals
|
|
125
|
+
else
|
|
126
|
+
locals = opts[:locals] = if locals = opts[:locals]
|
|
127
|
+
Hash[locals]
|
|
128
|
+
else
|
|
129
|
+
{}
|
|
130
|
+
end
|
|
131
|
+
locals[as] = nil
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
if (opts.keys - ALLOWED_KEYS).empty? && (optimized_template = _optimized_render_method_for_locals(template, locals))
|
|
135
|
+
return _optimized_render_each(enum, optimized_template, as, locals, &block)
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
if defined?(yield)
|
|
140
|
+
enum.each do |v|
|
|
141
|
+
locals[as] = v if as
|
|
142
|
+
yield render_template(template, opts)
|
|
143
|
+
end
|
|
144
|
+
nil
|
|
145
|
+
else
|
|
146
|
+
enum.map do |v|
|
|
147
|
+
locals[as] = v if as
|
|
148
|
+
render_template(template, opts)
|
|
149
|
+
end.join
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
private
|
|
154
|
+
|
|
155
|
+
if File.basename("a/b") == "b" && File.basename("a\\b") == "a\\b" && RUBY_VERSION >= '3'
|
|
156
|
+
# The default local variable name to use for the template, if the :local option
|
|
157
|
+
# is not used when calling render_each.
|
|
158
|
+
def render_each_default_local(template)
|
|
159
|
+
# Optimize to avoid allocations when possible
|
|
160
|
+
template = case template
|
|
161
|
+
when Symbol
|
|
162
|
+
s = template.name
|
|
163
|
+
return template unless s.include?("/") || s.include?(".")
|
|
164
|
+
s
|
|
165
|
+
when String
|
|
166
|
+
return template.to_sym unless template.include?("/") || template.include?(".")
|
|
167
|
+
template
|
|
168
|
+
else
|
|
169
|
+
template.to_s
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
File.basename(template).sub(/\..+\z/, '').to_sym
|
|
173
|
+
end
|
|
174
|
+
# :nocov:
|
|
175
|
+
else
|
|
176
|
+
def render_each_default_local(template)
|
|
177
|
+
File.basename(template.to_s).sub(/\..+\z/, '').to_sym
|
|
178
|
+
end
|
|
179
|
+
# :nocov:
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
if Render::COMPILED_METHOD_SUPPORT
|
|
183
|
+
# If compiled method support is enabled in the render plugin, return the
|
|
184
|
+
# method name to call to render the template. Return false if not given
|
|
185
|
+
# a string or symbol, or if compiled method support for this template has
|
|
186
|
+
# been explicitly disabled. Otherwise return nil.
|
|
187
|
+
def _cached_render_each_template_method(template)
|
|
188
|
+
case template
|
|
189
|
+
when String, Symbol
|
|
190
|
+
if (method_cache = render_opts[:template_method_cache])
|
|
191
|
+
key = render_opts[:assume_fixed_locals] ? template : [:_render_locals, template, [template.to_sym]]
|
|
192
|
+
_cached_template_method_lookup(method_cache, key)
|
|
193
|
+
end
|
|
194
|
+
else
|
|
195
|
+
false
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
# Use an optimized render for each value in the enum.
|
|
200
|
+
def _optimized_render_each(enum, optimized_template, as, locals)
|
|
201
|
+
if defined?(yield)
|
|
202
|
+
enum.each do |v|
|
|
203
|
+
locals[as] = v
|
|
204
|
+
yield _call_optimized_template_method(optimized_template, locals)
|
|
205
|
+
end
|
|
206
|
+
nil
|
|
207
|
+
else
|
|
208
|
+
enum.map do |v|
|
|
209
|
+
locals[as] = v
|
|
210
|
+
_call_optimized_template_method(optimized_template, locals)
|
|
211
|
+
end.join
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
else
|
|
215
|
+
def _cached_render_each_template_method(template)
|
|
216
|
+
nil
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
register_plugin(:render_each, RenderEach)
|
|
223
|
+
end
|
|
224
|
+
end
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'render'
|
|
4
|
+
|
|
5
|
+
#
|
|
6
|
+
class Roda
|
|
7
|
+
module RodaPlugins
|
|
8
|
+
# The render_locals plugin allows setting default locals for rendering templates.
|
|
9
|
+
#
|
|
10
|
+
# plugin :render_locals, render: {heading: 'Hello'}
|
|
11
|
+
#
|
|
12
|
+
# route do |r|
|
|
13
|
+
# r.get "foo" do
|
|
14
|
+
# view 'foo', locals: {name: 'Foo'} # locals: {:heading=>'Hello', :name=>'Foo'}
|
|
15
|
+
# end
|
|
16
|
+
#
|
|
17
|
+
# r.get "bar" do
|
|
18
|
+
# view 'foo', locals: {heading: 'Bar'} # locals: {:heading=>'Bar'}
|
|
19
|
+
# end
|
|
20
|
+
#
|
|
21
|
+
# view "default" # locals: {:heading=>'Hello'}
|
|
22
|
+
# end
|
|
23
|
+
#
|
|
24
|
+
# The render_locals plugin accepts the following options:
|
|
25
|
+
#
|
|
26
|
+
# render :: The default locals to use for template rendering
|
|
27
|
+
# layout :: The default locals to use for layout rendering
|
|
28
|
+
# merge :: Whether to merge template locals into layout locals
|
|
29
|
+
module RenderLocals
|
|
30
|
+
def self.load_dependencies(app, opts=OPTS)
|
|
31
|
+
app.plugin :render
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def self.configure(app, opts=OPTS)
|
|
35
|
+
app.opts[:render_locals] = (app.opts[:render_locals] || {}).merge(opts[:render]||{}).freeze
|
|
36
|
+
app.opts[:layout_locals] = (app.opts[:layout_locals] || {}).merge(opts[:layout]||{}).freeze
|
|
37
|
+
if opts.has_key?(:merge)
|
|
38
|
+
app.opts[:merge_locals] = opts[:merge]
|
|
39
|
+
app.opts[:layout_locals] = app.opts[:render_locals].merge(app.opts[:layout_locals]).freeze
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
module InstanceMethods
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
if Render::COMPILED_METHOD_SUPPORT
|
|
47
|
+
# Disable use of cached templates, since it assumes a render/view call with no
|
|
48
|
+
# options will have no locals.
|
|
49
|
+
def _cached_template_method(template)
|
|
50
|
+
nil
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def _optimized_view_content(template)
|
|
54
|
+
nil
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def render_locals
|
|
59
|
+
opts[:render_locals]
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def layout_locals
|
|
63
|
+
opts[:layout_locals]
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# If this isn't the layout template, then use the plugin's render locals as the default locals.
|
|
67
|
+
def render_template_opts(template, opts)
|
|
68
|
+
opts = super
|
|
69
|
+
return opts if opts[:_is_layout]
|
|
70
|
+
|
|
71
|
+
plugin_locals = render_locals
|
|
72
|
+
if locals = opts[:locals]
|
|
73
|
+
plugin_locals = Hash[plugin_locals].merge!(locals)
|
|
74
|
+
end
|
|
75
|
+
opts[:locals] = plugin_locals
|
|
76
|
+
opts
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# If using a layout, then use the plugin's layout locals as the default locals.
|
|
80
|
+
def view_layout_opts(opts)
|
|
81
|
+
if layout_opts = super
|
|
82
|
+
merge_locals = layout_opts.has_key?(:merge_locals) ? layout_opts[:merge_locals] : self.opts[:merge_locals]
|
|
83
|
+
|
|
84
|
+
locals = {}
|
|
85
|
+
locals.merge!(layout_locals)
|
|
86
|
+
if merge_locals && (method_locals = opts[:locals])
|
|
87
|
+
locals.merge!(method_locals)
|
|
88
|
+
end
|
|
89
|
+
if method_layout_locals = layout_opts[:locals]
|
|
90
|
+
locals.merge!(method_layout_locals)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
layout_opts[:locals] = locals
|
|
94
|
+
layout_opts
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
register_plugin(:render_locals, RenderLocals)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
class Roda
|
|
5
|
+
module RodaPlugins
|
|
6
|
+
# The request_aref plugin allows for custom handling of the r[] and r[]=
|
|
7
|
+
# methods (where r is the Request instance). In the current version of
|
|
8
|
+
# rack, these methods are deprecated, but the deprecation message is only
|
|
9
|
+
# printed in verbose mode. This plugin can allow for handling calls to
|
|
10
|
+
# these methods in one of three ways:
|
|
11
|
+
#
|
|
12
|
+
# :allow :: Allow the method calls without a deprecation, which is the
|
|
13
|
+
# historical behavior
|
|
14
|
+
# :warn :: Always issue a deprecation message by calling +warn+, not just
|
|
15
|
+
# in verbose mode.
|
|
16
|
+
# :raise :: Raise an error if either method is called
|
|
17
|
+
module RequestAref
|
|
18
|
+
# Make #[] and #[]= methods work as configured by aliasing the appropriate
|
|
19
|
+
# request_a(ref|set)_* methods to them.
|
|
20
|
+
def self.configure(app, setting)
|
|
21
|
+
case setting
|
|
22
|
+
when :allow, :raise, :warn
|
|
23
|
+
app::RodaRequest.class_eval do
|
|
24
|
+
alias_method(:[], :"request_aref_#{setting}")
|
|
25
|
+
alias_method(:[]=, :"request_aset_#{setting}")
|
|
26
|
+
public :[], :[]=
|
|
27
|
+
end
|
|
28
|
+
else
|
|
29
|
+
raise RodaError, "Unsupport request_aref plugin setting: #{setting.inspect}"
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Exception class raised when #[] or #[]= are called when the
|
|
34
|
+
# :raise setting is used.
|
|
35
|
+
class Error < RodaError
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
module RequestMethods
|
|
39
|
+
private
|
|
40
|
+
|
|
41
|
+
# Allow #[] calls
|
|
42
|
+
def request_aref_allow(k)
|
|
43
|
+
params[k.to_s]
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Always warn on #[] calls
|
|
47
|
+
def request_aref_warn(k)
|
|
48
|
+
warn("#{self.class}#[] is deprecated, use #params.[] instead")
|
|
49
|
+
params[k.to_s]
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Raise error on #[] calls
|
|
53
|
+
def request_aref_raise(k)
|
|
54
|
+
raise Error, "#{self.class}#[] has been removed, use #params.[] instead"
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Allow #[]= calls
|
|
58
|
+
def request_aset_allow(k, v)
|
|
59
|
+
params[k.to_s] = v
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Always warn on #[]= calls
|
|
63
|
+
def request_aset_warn(k, v)
|
|
64
|
+
warn("#{self.class}#[]= is deprecated, use #params.[]= instead")
|
|
65
|
+
params[k.to_s] = v
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Raise error on #[]= calls
|
|
69
|
+
def request_aset_raise(k, v)
|
|
70
|
+
raise Error, "#{self.class}#[]= has been removed, use #params.[]= instead"
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
register_plugin(:request_aref, RequestAref)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
3
|
+
require 'set'
|
|
4
|
+
|
|
5
|
+
class Roda
|
|
6
|
+
module RodaPlugins
|
|
7
|
+
# The request_headers plugin provides access to headers sent in the
|
|
8
|
+
# request in a more natural way than directly accessing the env hash.
|
|
9
|
+
#
|
|
10
|
+
# In practise this means you don't need to uppercase, convert dashes
|
|
11
|
+
# to underscores, or add a HTTP_ prefix.
|
|
12
|
+
#
|
|
13
|
+
# For example, to access a header called X-My-Header you
|
|
14
|
+
# would previously need to do:
|
|
15
|
+
#
|
|
16
|
+
# r.env['HTTP_X_MY_HEADER']
|
|
17
|
+
#
|
|
18
|
+
# But with this plugin you can now say:
|
|
19
|
+
#
|
|
20
|
+
# r.headers['X-My-Header']
|
|
21
|
+
#
|
|
22
|
+
# The name is actually case-insensitive so <tt>x-my-header</tt> will work as well.
|
|
23
|
+
#
|
|
24
|
+
# Example:
|
|
25
|
+
#
|
|
26
|
+
# plugin :request_headers
|
|
27
|
+
module RequestHeaders
|
|
28
|
+
REQUEST_INSTANCE_VARIABLES = [:@request_headers].freeze
|
|
29
|
+
|
|
30
|
+
module RequestMethods
|
|
31
|
+
# Provide access to the request headers while normalizing indexes.
|
|
32
|
+
def headers
|
|
33
|
+
@request_headers ||= Headers.new(@env)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
class Headers
|
|
38
|
+
# Set of environment variable names that don't need HTTP_ prepended to them.
|
|
39
|
+
CGI_VARIABLES = Set.new(%w'
|
|
40
|
+
AUTH_TYPE
|
|
41
|
+
CONTENT_LENGTH
|
|
42
|
+
CONTENT_TYPE
|
|
43
|
+
GATEWAY_INTERFACE
|
|
44
|
+
HTTPS
|
|
45
|
+
PATH_INFO
|
|
46
|
+
PATH_TRANSLATED
|
|
47
|
+
QUERY_STRING
|
|
48
|
+
REMOTE_ADDR
|
|
49
|
+
REMOTE_HOST
|
|
50
|
+
REMOTE_IDENT
|
|
51
|
+
REMOTE_USER
|
|
52
|
+
REQUEST_METHOD
|
|
53
|
+
SCRIPT_NAME
|
|
54
|
+
SERVER_NAME
|
|
55
|
+
SERVER_PORT
|
|
56
|
+
SERVER_PROTOCOL
|
|
57
|
+
SERVER_SOFTWARE
|
|
58
|
+
').freeze
|
|
59
|
+
|
|
60
|
+
def initialize(env)
|
|
61
|
+
@env = env
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Returns the value for the given key mapped to @env
|
|
65
|
+
def [](key)
|
|
66
|
+
@env[env_name(key)]
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
private
|
|
70
|
+
|
|
71
|
+
# Convert a HTTP header name into an environment variable name
|
|
72
|
+
def env_name(key)
|
|
73
|
+
key = key.to_s.upcase
|
|
74
|
+
key.tr!('-', '_')
|
|
75
|
+
key = 'HTTP_' + key unless CGI_VARIABLES.include?(key)
|
|
76
|
+
key
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
register_plugin(:request_headers, RequestHeaders)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
3
|
+
require 'rack/mime'
|
|
4
|
+
|
|
5
|
+
#
|
|
6
|
+
class Roda
|
|
7
|
+
module RodaPlugins
|
|
8
|
+
# The attachment plugin adds a response.attachment method.
|
|
9
|
+
# When called with no filename, +attachment+ sets the Content-Disposition
|
|
10
|
+
# to attachment. When called with a filename,+attachment+ sets the Content-Disposition
|
|
11
|
+
# to attachment with the appropriate filename parameter, and if the filename
|
|
12
|
+
# extension is recognized, this also sets the Content-Type to the appropriate
|
|
13
|
+
# MIME type if not already set.
|
|
14
|
+
#
|
|
15
|
+
# # set Content-Disposition to 'attachment'
|
|
16
|
+
# response.attachment
|
|
17
|
+
#
|
|
18
|
+
# # set Content-Disposition to 'attachment; filename="a.csv"',
|
|
19
|
+
# # also set Content-Type to 'text/csv'
|
|
20
|
+
# response.attachment 'a.csv'
|
|
21
|
+
#
|
|
22
|
+
# == License
|
|
23
|
+
#
|
|
24
|
+
# The implementation was originally taken from Sinatra,
|
|
25
|
+
# which is also released under the MIT License:
|
|
26
|
+
#
|
|
27
|
+
# Copyright (c) 2007, 2008, 2009 Blake Mizerany
|
|
28
|
+
# Copyright (c) 2010, 2011, 2012, 2013, 2014 Konstantin Haase
|
|
29
|
+
#
|
|
30
|
+
# Permission is hereby granted, free of charge, to any person
|
|
31
|
+
# obtaining a copy of this software and associated documentation
|
|
32
|
+
# files (the "Software"), to deal in the Software without
|
|
33
|
+
# restriction, including without limitation the rights to use,
|
|
34
|
+
# copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
35
|
+
# copies of the Software, and to permit persons to whom the
|
|
36
|
+
# Software is furnished to do so, subject to the following
|
|
37
|
+
# conditions:
|
|
38
|
+
#
|
|
39
|
+
# The above copyright notice and this permission notice shall be
|
|
40
|
+
# included in all copies or substantial portions of the Software.
|
|
41
|
+
#
|
|
42
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
43
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
44
|
+
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
45
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
46
|
+
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
47
|
+
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
48
|
+
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
49
|
+
# OTHER DEALINGS IN THE SOFTWARE.
|
|
50
|
+
module ResponseAttachment
|
|
51
|
+
UTF8_ENCODING = Encoding.find('UTF-8')
|
|
52
|
+
ISO88591_ENCODING = Encoding.find('ISO-8859-1')
|
|
53
|
+
BINARY_ENCODING = Encoding.find('BINARY')
|
|
54
|
+
|
|
55
|
+
module ResponseMethods
|
|
56
|
+
# Set the Content-Disposition to "attachment" with the specified filename,
|
|
57
|
+
# instructing the user agents to prompt to save.
|
|
58
|
+
def attachment(filename = nil, disposition='attachment')
|
|
59
|
+
if filename
|
|
60
|
+
param_filename = File.basename(filename)
|
|
61
|
+
encoding = param_filename.encoding
|
|
62
|
+
|
|
63
|
+
needs_encoding = param_filename.gsub!(/[^ 0-9a-zA-Z!\#$&\+\.\^_`\|~]+/, '-')
|
|
64
|
+
params = "; filename=#{param_filename.inspect}"
|
|
65
|
+
|
|
66
|
+
if needs_encoding && (encoding == UTF8_ENCODING || encoding == ISO88591_ENCODING)
|
|
67
|
+
# File name contains non attr-char characters from RFC 5987 Section 3.2.1
|
|
68
|
+
|
|
69
|
+
encoded_filename = File.basename(filename).force_encoding(BINARY_ENCODING)
|
|
70
|
+
# Similar regexp as above, but treat each byte separately, and encode
|
|
71
|
+
# space characters, since those aren't allowed in attr-char
|
|
72
|
+
encoded_filename.gsub!(/[^0-9a-zA-Z!\#$&\+\.\^_`\|~]/) do |c|
|
|
73
|
+
"%%%X" % c.ord
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
encoded_params = "; filename*=#{encoding.to_s}''#{encoded_filename}"
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
unless @headers[RodaResponseHeaders::CONTENT_TYPE]
|
|
80
|
+
ext = File.extname(filename)
|
|
81
|
+
if !ext.empty? && (content_type = Rack::Mime.mime_type(ext, nil))
|
|
82
|
+
@headers[RodaResponseHeaders::CONTENT_TYPE] = content_type
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
@headers[RodaResponseHeaders::CONTENT_DISPOSITION] = "#{disposition}#{params}#{encoded_params}"
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
register_plugin(:response_attachment, ResponseAttachment)
|
|
93
|
+
end
|
|
94
|
+
end
|