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,285 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
3
|
+
require 'stringio'
|
|
4
|
+
require 'mail'
|
|
5
|
+
|
|
6
|
+
class Roda
|
|
7
|
+
module RodaPlugins
|
|
8
|
+
# The mailer plugin allows your Roda application to send emails easily.
|
|
9
|
+
#
|
|
10
|
+
# class Mailer < Roda
|
|
11
|
+
# plugin :render
|
|
12
|
+
# plugin :mailer
|
|
13
|
+
#
|
|
14
|
+
# route do |r|
|
|
15
|
+
# r.on "albums", Integer do |album_id|
|
|
16
|
+
# @album = Album[album_id]
|
|
17
|
+
#
|
|
18
|
+
# r.mail "added" do
|
|
19
|
+
# from 'from@example.com'
|
|
20
|
+
# to 'to@example.com'
|
|
21
|
+
# cc 'cc@example.com'
|
|
22
|
+
# bcc 'bcc@example.com'
|
|
23
|
+
# subject 'Album Added'
|
|
24
|
+
# add_file "path/to/album_added_img.jpg"
|
|
25
|
+
# render(:albums_added_email) # body
|
|
26
|
+
# end
|
|
27
|
+
# end
|
|
28
|
+
# end
|
|
29
|
+
# end
|
|
30
|
+
#
|
|
31
|
+
# The default method for sending a mail is +sendmail+:
|
|
32
|
+
#
|
|
33
|
+
# Mailer.sendmail("/albums/1/added")
|
|
34
|
+
#
|
|
35
|
+
# If you want to return the <tt>Mail::Message</tt> instance for further modification,
|
|
36
|
+
# you can just use the +mail+ method:
|
|
37
|
+
#
|
|
38
|
+
# mail = Mailer.mail("/albums/1/added")
|
|
39
|
+
# mail.from 'from2@example.com'
|
|
40
|
+
# mail.deliver
|
|
41
|
+
#
|
|
42
|
+
# The mailer plugin uses the mail gem, so if you want to configure how
|
|
43
|
+
# email is sent, you can use <tt>Mail.defaults</tt> (see the mail gem documentation for
|
|
44
|
+
# more details):
|
|
45
|
+
#
|
|
46
|
+
# Mail.defaults do
|
|
47
|
+
# delivery_method :smtp, address: 'smtp.example.com', port: 587
|
|
48
|
+
# end
|
|
49
|
+
#
|
|
50
|
+
# You can support multipart emails using +text_part+ and +html_part+:
|
|
51
|
+
#
|
|
52
|
+
# r.mail "added" do
|
|
53
|
+
# from 'from@example.com'
|
|
54
|
+
# to 'to@example.com'
|
|
55
|
+
# subject 'Album Added'
|
|
56
|
+
# text_part render('album_added.txt') # views/album_added.txt.erb
|
|
57
|
+
# html_part render('album_added.html') # views/album_added.html.erb
|
|
58
|
+
# end
|
|
59
|
+
#
|
|
60
|
+
# In addition to allowing you to use Roda's render plugin for rendering
|
|
61
|
+
# email bodies, you can use all of Roda's usual routing tree features
|
|
62
|
+
# to DRY up your code:
|
|
63
|
+
#
|
|
64
|
+
# r.on "albums", Integer do |album_id|
|
|
65
|
+
# @album = Album[album_id]
|
|
66
|
+
# from 'from@example.com'
|
|
67
|
+
# to 'to@example.com'
|
|
68
|
+
#
|
|
69
|
+
# r.mail "added" do
|
|
70
|
+
# subject 'Album Added'
|
|
71
|
+
# render(:albums_added_email)
|
|
72
|
+
# end
|
|
73
|
+
#
|
|
74
|
+
# r.mail "deleted" do
|
|
75
|
+
# subject 'Album Deleted'
|
|
76
|
+
# render(:albums_deleted_email)
|
|
77
|
+
# end
|
|
78
|
+
# end
|
|
79
|
+
#
|
|
80
|
+
# When sending a mail via +mail+ or +sendmail+, a RodaError will be raised
|
|
81
|
+
# if the mail object does not have a body. This is similar to the 404
|
|
82
|
+
# status that Roda uses by default for web requests that don't have
|
|
83
|
+
# a body. If you want to specifically send an email with an empty body, you
|
|
84
|
+
# can use the explicit empty string:
|
|
85
|
+
#
|
|
86
|
+
# r.mail do
|
|
87
|
+
# from 'from@example.com'
|
|
88
|
+
# to 'to@example.com'
|
|
89
|
+
# subject 'No Body Here'
|
|
90
|
+
# ""
|
|
91
|
+
# end
|
|
92
|
+
#
|
|
93
|
+
# If while preparing the email you figure out you don't want to send an
|
|
94
|
+
# email, call +no_mail!+:
|
|
95
|
+
#
|
|
96
|
+
# r.mail 'welcome', Integer do |id|
|
|
97
|
+
# no_mail! unless user = User[id]
|
|
98
|
+
# # ...
|
|
99
|
+
# end
|
|
100
|
+
#
|
|
101
|
+
# You can pass arguments when calling +mail+ or +sendmail+, and they
|
|
102
|
+
# will be yielded as additional arguments to the appropriate +r.mail+ block:
|
|
103
|
+
#
|
|
104
|
+
# Mailer.sendmail('/welcome/1', 'foo@example.com')
|
|
105
|
+
#
|
|
106
|
+
# r.mail 'welcome', Integer do |user_id, mail_from|
|
|
107
|
+
# from mail_from
|
|
108
|
+
# to User[user_id].email
|
|
109
|
+
# # ...
|
|
110
|
+
# end
|
|
111
|
+
#
|
|
112
|
+
# By default, the mailer uses text/plain as the Content-Type for emails.
|
|
113
|
+
# You can override the default by specifying a :content_type option when
|
|
114
|
+
# loading the plugin:
|
|
115
|
+
#
|
|
116
|
+
# plugin :mailer, content_type: 'text/html'
|
|
117
|
+
#
|
|
118
|
+
# For backwards compatibility reasons, the +r.mail+ method does not do
|
|
119
|
+
# a terminal match by default if provided arguments (unlike +r.get+ and
|
|
120
|
+
# +r.post+). You can pass the :terminal option to make +r.mail+ enforce
|
|
121
|
+
# a terminal match if provided arguments.
|
|
122
|
+
#
|
|
123
|
+
# The mailer plugin does support being used inside a Roda application
|
|
124
|
+
# that is handling web requests, where the routing block for mails and
|
|
125
|
+
# web requests is shared. However, it's recommended that you create a
|
|
126
|
+
# separate Roda application for emails. This can be a subclass of your main
|
|
127
|
+
# Roda application if you want your helper methods to automatically be
|
|
128
|
+
# available in your email views.
|
|
129
|
+
module Mailer
|
|
130
|
+
RESPONSE_INSTANCE_VARIABLES = [:@mail, :@mail_attachments].freeze
|
|
131
|
+
|
|
132
|
+
# Error raised when the using the mail class method, but the routing
|
|
133
|
+
# tree doesn't return the mail object.
|
|
134
|
+
class Error < ::Roda::RodaError; end
|
|
135
|
+
|
|
136
|
+
# Set the options for the mailer. Options:
|
|
137
|
+
# :content_type :: The default content type for emails (default: text/plain)
|
|
138
|
+
def self.configure(app, opts=OPTS)
|
|
139
|
+
app.opts[:mailer] = (app.opts[:mailer]||OPTS).merge(opts).freeze
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
module ClassMethods
|
|
143
|
+
# Return a Mail::Message instance for the email for the given request path
|
|
144
|
+
# and arguments. Any arguments given are yielded to the appropriate +r.mail+
|
|
145
|
+
# block after any usual match block arguments. You can further manipulate the
|
|
146
|
+
#returned mail object before calling +deliver+ to send the mail.
|
|
147
|
+
def mail(path, *args)
|
|
148
|
+
mail = ::Mail.new
|
|
149
|
+
catch(:no_mail) do
|
|
150
|
+
unless mail.equal?(new("PATH_INFO"=>path, 'SCRIPT_NAME'=>'', "REQUEST_METHOD"=>"MAIL", 'rack.input'=>StringIO.new, 'roda.mail'=>mail, 'roda.mail_args'=>args)._roda_handle_main_route)
|
|
151
|
+
raise Error, "route did not return mail instance for #{path.inspect}, #{args.inspect}"
|
|
152
|
+
end
|
|
153
|
+
mail
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
# :nocov:
|
|
157
|
+
ruby2_keywords(:mail) if respond_to?(:ruby2_keywords, true)
|
|
158
|
+
# :nocov:
|
|
159
|
+
|
|
160
|
+
# Calls +mail+ with given arguments and immediately sends the resulting mail.
|
|
161
|
+
def sendmail(*args)
|
|
162
|
+
if m = mail(*args)
|
|
163
|
+
m.deliver
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
# :nocov:
|
|
167
|
+
ruby2_keywords(:sendmail) if respond_to?(:ruby2_keywords, true)
|
|
168
|
+
# :nocov:
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
module RequestMethods
|
|
172
|
+
# Similar to routing tree methods such as +get+ and +post+, this matches
|
|
173
|
+
# only if the request method is MAIL (only set when using the Roda class
|
|
174
|
+
# +mail+ or +sendmail+ methods) and the rest of the arguments match
|
|
175
|
+
# the request. This yields any of the captures to the block, as well as
|
|
176
|
+
# any arguments passed to the +mail+ or +sendmail+ Roda class methods.
|
|
177
|
+
def mail(*args)
|
|
178
|
+
if @env["REQUEST_METHOD"] == "MAIL"
|
|
179
|
+
# RODA4: Make terminal match the default
|
|
180
|
+
send(roda_class.opts[:mailer][:terminal] ? :_verb : :if_match, args) do |*vs|
|
|
181
|
+
yield(*(vs + @env['roda.mail_args']))
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
module ResponseMethods
|
|
188
|
+
# The mail object related to the current request.
|
|
189
|
+
attr_accessor :mail
|
|
190
|
+
|
|
191
|
+
# If the related request was an email request, add any response headers
|
|
192
|
+
# to the email, as well as adding the response body to the email.
|
|
193
|
+
# Return the email unless no body was set for it, which would indicate
|
|
194
|
+
# that the routing tree did not handle the request.
|
|
195
|
+
def finish
|
|
196
|
+
if m = mail
|
|
197
|
+
header_content_type = @headers.delete(RodaResponseHeaders::CONTENT_TYPE)
|
|
198
|
+
m.headers(@headers)
|
|
199
|
+
m.body(@body.join) unless @body.empty?
|
|
200
|
+
mail_attachments.each do |a, block|
|
|
201
|
+
m.add_file(*a)
|
|
202
|
+
block.call if block
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
if content_type = header_content_type || roda_class.opts[:mailer][:content_type]
|
|
206
|
+
if mail.multipart?
|
|
207
|
+
if /multipart\/mixed/ =~ mail.content_type &&
|
|
208
|
+
mail.parts.length >= 2 &&
|
|
209
|
+
(part = mail.parts.find{|p| !p.attachment && (p.encoded; /text\/plain/ =~ p.content_type)})
|
|
210
|
+
part.content_type = content_type
|
|
211
|
+
end
|
|
212
|
+
else
|
|
213
|
+
mail.content_type = content_type
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
unless m.body.to_s.empty? && m.parts.empty? && @body.empty?
|
|
218
|
+
m
|
|
219
|
+
end
|
|
220
|
+
else
|
|
221
|
+
super
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
# The attachments related to the current mail.
|
|
226
|
+
def mail_attachments
|
|
227
|
+
@mail_attachments ||= []
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
module InstanceMethods
|
|
232
|
+
# Add delegates for common email methods.
|
|
233
|
+
[:from, :to, :cc, :bcc, :subject].each do |meth|
|
|
234
|
+
define_method(meth) do |*args|
|
|
235
|
+
env['roda.mail'].public_send(meth, *args)
|
|
236
|
+
nil
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
[:text_part, :html_part].each do |meth|
|
|
240
|
+
define_method(meth) do |*args|
|
|
241
|
+
_mail_part(meth, *args)
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
# If this is an email request, set the mail object in the response, as well
|
|
246
|
+
# as the default content_type for the email.
|
|
247
|
+
def initialize(env)
|
|
248
|
+
super
|
|
249
|
+
if mail = env['roda.mail']
|
|
250
|
+
res = @_response
|
|
251
|
+
res.mail = mail
|
|
252
|
+
res.headers.delete(RodaResponseHeaders::CONTENT_TYPE)
|
|
253
|
+
end
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
# Delay adding a file to the message until after the message body has been set.
|
|
257
|
+
# If a block is given, the block is called after the file has been added, and you
|
|
258
|
+
# can access the attachment via <tt>response.mail_attachments.last</tt>.
|
|
259
|
+
def add_file(*a, &block)
|
|
260
|
+
response.mail_attachments << [a, block]
|
|
261
|
+
nil
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
# Signal that no mail should be sent for this request.
|
|
265
|
+
def no_mail!
|
|
266
|
+
throw :no_mail
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
private
|
|
270
|
+
|
|
271
|
+
# Set the text_part or html_part (depending on the method) in the related email,
|
|
272
|
+
# using the given body and optional headers.
|
|
273
|
+
def _mail_part(meth, body, headers=nil)
|
|
274
|
+
env['roda.mail'].public_send(meth) do
|
|
275
|
+
body(body)
|
|
276
|
+
headers(headers) if headers
|
|
277
|
+
end
|
|
278
|
+
nil
|
|
279
|
+
end
|
|
280
|
+
end
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
register_plugin(:mailer, Mailer)
|
|
284
|
+
end
|
|
285
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
class Roda
|
|
5
|
+
module RodaPlugins
|
|
6
|
+
# The map_matcher plugin allows you to provide a string-keyed
|
|
7
|
+
# hash during route matching, and match any of the keys in the hash
|
|
8
|
+
# as the next segment in the request path, yielding the corresponding
|
|
9
|
+
# value in the hash:
|
|
10
|
+
#
|
|
11
|
+
# class App < Roda
|
|
12
|
+
# plugin :map_matcher
|
|
13
|
+
#
|
|
14
|
+
# map = { "foo" => "bar", "baz" => "quux" }.freeze
|
|
15
|
+
#
|
|
16
|
+
# route do
|
|
17
|
+
# r.get map: map do |v|
|
|
18
|
+
# v
|
|
19
|
+
# # GET /foo => bar
|
|
20
|
+
# # GET /baz => quux
|
|
21
|
+
# end
|
|
22
|
+
# end
|
|
23
|
+
# end
|
|
24
|
+
module MapMatcher
|
|
25
|
+
module RequestMethods
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
# Match only if the next segment in the path is one of the keys
|
|
29
|
+
# in the hash, and yield the value of the hash.
|
|
30
|
+
def match_map(hash)
|
|
31
|
+
rp = @remaining_path
|
|
32
|
+
if key = _match_class_String
|
|
33
|
+
if value = hash[@captures[-1]]
|
|
34
|
+
@captures[-1] = value
|
|
35
|
+
true
|
|
36
|
+
else
|
|
37
|
+
@remaining_path = rp
|
|
38
|
+
@captures.pop
|
|
39
|
+
false
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
register_plugin(:map_matcher, MapMatcher)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
class Roda
|
|
5
|
+
module RodaPlugins
|
|
6
|
+
# The match_affix plugin allows changing the default prefix and suffix used for
|
|
7
|
+
# match patterns. Roda's default behavior for a match pattern like <tt>"albums"</tt>
|
|
8
|
+
# is to use the pattern <tt>/\A\/(?:albums)(?=\/|\z)/</tt>. This prefixes the pattern
|
|
9
|
+
# with +/+ and suffixes it with <tt>(?=\/|\z)</tt>. With the match_affix plugin, you
|
|
10
|
+
# can change the prefix and suffix to use. So if you want to be explicit and require
|
|
11
|
+
# a leading +/+ in patterns, you can set the prefix to <tt>""</tt>. If you want to
|
|
12
|
+
# consume a trailing slash instead of leaving it, you can set the suffix to <tt>(\/|\z)</tt>.
|
|
13
|
+
#
|
|
14
|
+
# You set the prefix and suffix to use by passing arguments when loading the plugin:
|
|
15
|
+
#
|
|
16
|
+
# plugin :match_affix, ""
|
|
17
|
+
#
|
|
18
|
+
# will load the plugin and use an empty prefix (instead of a slash).
|
|
19
|
+
#
|
|
20
|
+
# plugin :match_affix, "", /(\/|\z)/
|
|
21
|
+
#
|
|
22
|
+
# will use an empty prefix and change the suffix to consume a trailing slash.
|
|
23
|
+
#
|
|
24
|
+
# plugin :match_affix, nil, /(?:\/\z|(?=\/|\z))/
|
|
25
|
+
#
|
|
26
|
+
# will not modify the prefix and will change the suffix so that it consumes a trailing slash
|
|
27
|
+
# at the end of the path only.
|
|
28
|
+
#
|
|
29
|
+
# This plugin automatically loads the placeholder_string_matchers plugin.
|
|
30
|
+
module MatchAffix
|
|
31
|
+
def self.load_dependencies(app, _prefix, _suffix=nil)
|
|
32
|
+
app.plugin :placeholder_string_matchers
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Set the default prefix and suffix to use in match patterns, if a non-nil value
|
|
36
|
+
# is given.
|
|
37
|
+
def self.configure(app, prefix, suffix=nil)
|
|
38
|
+
app.opts[:match_prefix] = prefix if prefix
|
|
39
|
+
app.opts[:match_suffix] = suffix if suffix
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
module RequestClassMethods
|
|
43
|
+
private
|
|
44
|
+
|
|
45
|
+
# Use the match prefix and suffix provided when loading the plugin, or fallback
|
|
46
|
+
# to Roda's default prefix/suffix if one was not provided.
|
|
47
|
+
def consume_pattern(pattern)
|
|
48
|
+
/\A#{roda_class.opts[:match_prefix] || "/"}(?:#{pattern})#{roda_class.opts[:match_suffix] || "(?=\/|\z)"}/
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
module RequestMethods
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
# Use regexps for all string matches, so that the prefix and suffix matches work.
|
|
56
|
+
def _match_string(str)
|
|
57
|
+
consume(self.class.cached_matcher(str){Regexp.escape(str).gsub(/:(\w+)/){|m| _match_symbol_regexp($1)}})
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
register_plugin(:match_affix, MatchAffix)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
class Roda
|
|
5
|
+
module RodaPlugins
|
|
6
|
+
# The match_hook plugin adds hooks that are called upon a successful match
|
|
7
|
+
# by any of the matchers. The hooks do not take any arguments. If you would
|
|
8
|
+
# like hooks that pass the arguments/matchers and values yielded to the route block,
|
|
9
|
+
# use the match_hook_args plugin. This uses the match_hook_args plugin internally,
|
|
10
|
+
# but doesn't pass the matchers and values yielded.
|
|
11
|
+
#
|
|
12
|
+
# plugin :match_hook
|
|
13
|
+
#
|
|
14
|
+
# match_hook do
|
|
15
|
+
# logger.debug("#{request.matched_path} matched. #{request.remaining_path} remaining.")
|
|
16
|
+
# end
|
|
17
|
+
module MatchHook
|
|
18
|
+
def self.load_dependencies(app)
|
|
19
|
+
app.plugin :match_hook_args
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
module ClassMethods
|
|
23
|
+
# Add a match hook.
|
|
24
|
+
def match_hook(&block)
|
|
25
|
+
meth = define_roda_method("match_hook", 0, &block)
|
|
26
|
+
add_match_hook{|_,_| send(meth)}
|
|
27
|
+
nil
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
register_plugin :match_hook, MatchHook
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
class Roda
|
|
5
|
+
module RodaPlugins
|
|
6
|
+
# The match_hook_args plugin adds hooks that are called upon a successful match
|
|
7
|
+
# by any of the matchers. It is similar to the match_hook plugin, but it allows
|
|
8
|
+
# for passing the matchers and block arguments for each match method.
|
|
9
|
+
#
|
|
10
|
+
# plugin :match_hook_args
|
|
11
|
+
#
|
|
12
|
+
# add_match_hook do |matchers, block_args|
|
|
13
|
+
# logger.debug("matchers: #{matchers.inspect}. #{block_args.inspect} yielded.")
|
|
14
|
+
# end
|
|
15
|
+
#
|
|
16
|
+
# # Term is an implicit matcher used for terminating matches, and
|
|
17
|
+
# # will be included in the array of matchers yielded to the match hook
|
|
18
|
+
# # if a terminating match is used.
|
|
19
|
+
# term = self.class::RodaRequest::TERM
|
|
20
|
+
#
|
|
21
|
+
# route do |r|
|
|
22
|
+
# r.root do
|
|
23
|
+
# # for a request for /
|
|
24
|
+
# # matchers: nil, block_args: nil
|
|
25
|
+
# end
|
|
26
|
+
#
|
|
27
|
+
# r.on 'a', ['b', 'c'], Integer do |segment, id|
|
|
28
|
+
# # for a request for /a/b/1
|
|
29
|
+
# # matchers: ["a", ["b", "c"], Integer], block_args: ["b", 1]
|
|
30
|
+
# end
|
|
31
|
+
#
|
|
32
|
+
# r.get 'd' do
|
|
33
|
+
# # for a request for /d
|
|
34
|
+
# # matchers: ["d", term], block_args: []
|
|
35
|
+
# end
|
|
36
|
+
# end
|
|
37
|
+
module MatchHookArgs
|
|
38
|
+
def self.configure(app)
|
|
39
|
+
app.opts[:match_hook_args] ||= []
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
module ClassMethods
|
|
43
|
+
# Freeze the array of hook methods when freezing the app
|
|
44
|
+
def freeze
|
|
45
|
+
opts[:match_hook_args].freeze
|
|
46
|
+
super
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Add a match hook that will be called with matchers and block args.
|
|
50
|
+
def add_match_hook(&block)
|
|
51
|
+
opts[:match_hook_args] << define_roda_method("match_hook_args", :any, &block)
|
|
52
|
+
|
|
53
|
+
if opts[:match_hook_args].length == 1
|
|
54
|
+
class_eval("alias _match_hook_args #{opts[:match_hook_args].first}", __FILE__, __LINE__)
|
|
55
|
+
else
|
|
56
|
+
class_eval("def _match_hook_args(v, a); #{opts[:match_hook_args].map{|m| "#{m}(v, a)"}.join(';')} end", __FILE__, __LINE__)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
public :_match_hook_args
|
|
60
|
+
|
|
61
|
+
nil
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
module InstanceMethods
|
|
66
|
+
# Default empty method if no match hooks are defined.
|
|
67
|
+
def _match_hook_args(matchers, block_args)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
module RequestMethods
|
|
72
|
+
private
|
|
73
|
+
|
|
74
|
+
# Call the match hook with matchers and block args if yielding to the block before yielding to the block.
|
|
75
|
+
def if_match(v)
|
|
76
|
+
super do |*a|
|
|
77
|
+
scope._match_hook_args(v, a)
|
|
78
|
+
yield(*a)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Call the match hook with nil matchers and blocks before yielding to the block
|
|
83
|
+
def always
|
|
84
|
+
scope._match_hook_args(nil, nil)
|
|
85
|
+
super
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
register_plugin :match_hook_args, MatchHookArgs
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|