plezi 0.12.22 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +18 -0
  3. data/LICENSE.txt +17 -18
  4. data/README.md +54 -698
  5. data/Rakefile +7 -4
  6. data/bin/config.ru +22 -0
  7. data/{test → bin}/console +4 -6
  8. data/bin/hello_world +52 -0
  9. data/bin/setup +8 -0
  10. data/exe/plezi +145 -0
  11. data/lib/plezi.rb +24 -137
  12. data/lib/plezi/activation.rb +28 -0
  13. data/lib/plezi/api.rb +62 -0
  14. data/lib/plezi/controller/controller.rb +259 -0
  15. data/lib/plezi/controller/controller_class.rb +176 -0
  16. data/lib/plezi/controller/cookies.rb +40 -0
  17. data/lib/plezi/helpers.rb +60 -0
  18. data/lib/plezi/rake.rb +2 -24
  19. data/lib/plezi/render/erb.rb +34 -0
  20. data/lib/plezi/render/has_cache.rb +36 -0
  21. data/lib/plezi/render/markdown.rb +63 -0
  22. data/lib/plezi/render/render.rb +49 -0
  23. data/lib/plezi/render/sass.rb +55 -0
  24. data/lib/plezi/render/slim.rb +33 -0
  25. data/lib/plezi/router/adclient.rb +23 -0
  26. data/lib/plezi/router/assets.rb +67 -0
  27. data/lib/plezi/router/errors.rb +29 -0
  28. data/lib/plezi/router/route.rb +112 -0
  29. data/lib/plezi/router/router.rb +120 -0
  30. data/lib/plezi/version.rb +1 -1
  31. data/lib/plezi/websockets/message_dispatch.rb +91 -0
  32. data/lib/plezi/websockets/redis.rb +55 -0
  33. data/plezi.gemspec +25 -16
  34. data/resources/404.erb +5 -4
  35. data/resources/500.erb +5 -4
  36. data/resources/{500.html → 503.html} +8 -9
  37. data/resources/client.js +253 -0
  38. data/resources/config.ru +5 -36
  39. data/resources/ctrlr.rb +34 -0
  40. data/resources/gemfile +4 -0
  41. data/resources/mini_app.rb +28 -82
  42. data/resources/mini_exec +7 -0
  43. data/resources/mini_welcome_page.html +0 -0
  44. data/resources/procfile +3 -0
  45. data/resources/rakefile +4 -8
  46. data/resources/routes.rb +9 -26
  47. data/resources/{websockets.js → simple-client.js} +3 -3
  48. metadata +60 -85
  49. data/bin/plezi +0 -104
  50. data/docs/async_helpers.md +0 -245
  51. data/docs/controllers.md +0 -27
  52. data/docs/logging.md +0 -49
  53. data/docs/routes.md +0 -209
  54. data/docs/websockets.md +0 -213
  55. data/lib/plezi/builders/ac_model.rb +0 -59
  56. data/lib/plezi/builders/app_builder.rb +0 -137
  57. data/lib/plezi/builders/builder.rb +0 -43
  58. data/lib/plezi/builders/form_builder.rb +0 -27
  59. data/lib/plezi/common/api.rb +0 -92
  60. data/lib/plezi/common/cache.rb +0 -122
  61. data/lib/plezi/common/defer.rb +0 -21
  62. data/lib/plezi/common/dsl.rb +0 -94
  63. data/lib/plezi/common/redis.rb +0 -65
  64. data/lib/plezi/common/renderer.rb +0 -141
  65. data/lib/plezi/common/settings.rb +0 -52
  66. data/lib/plezi/handlers/controller_core.rb +0 -106
  67. data/lib/plezi/handlers/controller_magic.rb +0 -284
  68. data/lib/plezi/handlers/http_router.rb +0 -205
  69. data/lib/plezi/handlers/placebo.rb +0 -112
  70. data/lib/plezi/handlers/route.rb +0 -216
  71. data/lib/plezi/handlers/session.rb +0 -109
  72. data/lib/plezi/handlers/stubs.rb +0 -156
  73. data/lib/plezi/handlers/ws_identity.rb +0 -253
  74. data/lib/plezi/handlers/ws_object.rb +0 -308
  75. data/lib/plezi/helpers/http_sender.rb +0 -84
  76. data/lib/plezi/helpers/magic_helpers.rb +0 -104
  77. data/lib/plezi/helpers/mime_types.rb +0 -1995
  78. data/lib/plezi/oauth.rb +0 -5
  79. data/lib/plezi/oauth/auth_controller.rb +0 -229
  80. data/logo/dark.png +0 -0
  81. data/logo/light.png +0 -0
  82. data/logo/sign.png +0 -0
  83. data/resources/404.haml +0 -121
  84. data/resources/404.html +0 -124
  85. data/resources/404.slim +0 -120
  86. data/resources/500.haml +0 -120
  87. data/resources/500.slim +0 -120
  88. data/resources/Gemfile +0 -86
  89. data/resources/code.rb +0 -8
  90. data/resources/controller.rb +0 -142
  91. data/resources/database.yml +0 -33
  92. data/resources/db_ac_config.rb +0 -59
  93. data/resources/db_dm_config.rb +0 -51
  94. data/resources/db_sequel_config.rb +0 -33
  95. data/resources/en.yml +0 -204
  96. data/resources/haml_config.rb +0 -6
  97. data/resources/i18n_config.rb +0 -14
  98. data/resources/initialize.rb +0 -49
  99. data/resources/mini_exec.rb +0 -7
  100. data/resources/oauth_config.rb +0 -24
  101. data/resources/plezi_client.js +0 -198
  102. data/resources/plezi_websockets.html +0 -47
  103. data/resources/redis_config.rb +0 -42
  104. data/resources/slim_config.rb +0 -11
  105. data/resources/welcome_page.html +0 -272
  106. data/test/dispatch +0 -58
  107. data/test/hello_world +0 -13
  108. data/test/plezi_tests.rb +0 -581
@@ -1,284 +0,0 @@
1
- module Plezi
2
-
3
- # the methods defined in this module will be injected into the Controller class passed to
4
- # Plezi (using the `route` or `shared_route` commands), and will be available
5
- # for the controller to use within it's methods.
6
- #
7
- # for some reason, the documentation ignores the following additional attributes, which are listed here:
8
- #
9
- # request:: the HTTPRequest object containing all the data from the HTTP request. If a WebSocket connection was established, the `request` object will continue to contain the HTTP request establishing the connection (cookies, parameters sent and other information).
10
- # params:: any parameters sent with the request (short-cut for `request.params`), will contain any GET or POST form data sent (including file upload and JSON format support).
11
- # cookies:: a cookie-jar to get and set cookies (set: `cookie\[:name] = data` or get: `cookie\[:name]`). Cookies and some other data must be set BEFORE the response's headers are sent.
12
- # flash:: a temporary cookie-jar, good for one request. this is a short-cut for the `response.flash` which handles this magical cookie style.
13
- # response:: the HTTPResponse **OR** the WSResponse object that formats the response and sends it. use `response << data`. This object can be used to send partial data (such as headers, or partial html content) in blocking mode as well as sending data in the default non-blocking mode.
14
- # host_params:: a copy of the parameters used to create the host and service which accepted the request and created this instance of the controller class.
15
- #
16
- # For Controller Class menthods, please read the documentation about {Plezi::ControllerMagic::ClassMethods}.
17
- #
18
- # For Controller Instance methods, please read the documentation about {Plezi::ControllerMagic::InstanceMethods}.
19
- #
20
- # {include: Plezi::ControllerMagic::InstanceMethods}
21
- #
22
- module ControllerMagic
23
- # @!parse include Plezi::Base::WSObject
24
- # @!parse include InstanceMethods
25
- # @!parse extend ClassMethods
26
-
27
- def self.included base
28
- base.send :include, InstanceMethods
29
- base.extend ClassMethods
30
- end
31
-
32
- module InstanceMethods
33
-
34
- public
35
-
36
- # the request object, type HTTPRequest.
37
- attr_reader :request
38
-
39
- # the :params variable contains all the parameters set by the request (/path?locale=he => params ["locale"] == "he").
40
- attr_reader :params
41
-
42
- # A cookie-jar to get and set cookies (set: `cookie [:name] = data` or get: `cookie [ :name ]`).
43
- #
44
- # Cookies and some other data must be set BEFORE the response's headers are sent.
45
- attr_reader :cookies
46
-
47
- # Session data can be stored here (session data will be stored on the Redis server, if Redis is available).
48
- #
49
- # The first time this method is called, the `n object will be created. The session object must be created BEFORE the headers are set , if it is to be used.
50
- #
51
- # Sessions are not automatically created, because they require more resources. The one exception is the Websocket connection that will force a session object into existence, as it's very common to use session data in Websocket connections and the extra connection time is less relevant for a long term connection.
52
- def session
53
- @session ||= response.session
54
- end
55
-
56
- # the HTTPResponse **OR** the WSResponse object that formats the response and sends it. use `response << data`. This object can be used to send partial data (such as headers, or partial html content) in blocking mode as well as sending data in the default non-blocking mode.
57
- attr_reader :response
58
-
59
- # the :flash is a little bit of a magic hash that sets and reads temporary cookies.
60
- # these cookies will live for one successful request to a Controller and will then be removed.
61
- attr_reader :flash
62
-
63
- # the parameters used to create the host (the parameters passed to the `Plezi.host`).
64
- attr_reader :host_params
65
-
66
- # this method does two things.
67
- #
68
- # 1. sets redirection headers for the response.
69
- # 2. sets the `flash` object (short-time cookies) with all the values passed except the :permanent value.
70
- #
71
- # use:
72
- # redirect_to 'http://google.com', notice: "foo", permanent: true
73
- # # => redirects to 'http://google.com' with status 301 (permanent redirection) and adds notice: "foo" to the flash
74
- # or, a simple temporary redirect:
75
- # redirect_to 'http://google.com'
76
- # # => redirects to 'http://google.com' with status 302 (default temporary redirection)
77
- #
78
- # if the url is a symbol or a hash, the method will try to format it into a url Srting, using the `url_for` method.
79
- #
80
- # if the url is a String, it will be passed along as is.
81
- #
82
- # An empty String or `nil` will be replaced with the root path for the request's specific host (i.e. `http://localhost:3000/`).
83
- #
84
- def redirect_to url, options = {}
85
- return super() if defined? super
86
- url = full_url_for(url, params) unless url.is_a?(String) || url.nil?
87
- # redirect
88
- response.redirect_to url, options
89
- end
90
-
91
- # Returns the RELATIVE url for methods in THIS controller (i.e.: "/path_to_controller/restful/params?non=restful&params=foo")
92
- #
93
- # accepts one parameter:
94
- # dest:: a destination object, either a Hash, a Symbol, a Numerical or a String.
95
- #
96
- # If :dest is a Numerical, a Symbol or a String, it should signify the id of an object or the name of the method this controller should respond to.
97
- #
98
- # If :dest is a Hash, it should contain all the relevant parameters the url should set (i.e. `url_for id: :new, name: "Jhon Doe"`)
99
- #
100
- # If :dest is false (or nil), the String returned will be the url to the index.
101
- #
102
- # * If you use the same controller in different routes, the first route will dictate the returned url's structure (cause by route priority).
103
- #
104
- # * The route's host will be ignored. Even when using {#full_url_for}, the same host as the current request will be assumed. To change hosts, add the new host's address manualy, i.e.: `request.base_url.gsub('//www.', '//admin.') + UserController.url_for(user.id, params)
105
- #
106
- # * Not all controllers support this method. Regexp controller paths and multi-path options will throw an exception.
107
- def url_for dest = nil
108
- self.class.url_for dest, params
109
- end
110
- # same as #url_for, but returns the full URL (protocol:port:://host/path?params=foo)
111
- def full_url_for dest
112
- "#{request.base_url}#{self.class.url_for(dest, params)}"
113
- end
114
-
115
- # Send raw data to be saved as a file or viewed as an attachment. Browser should believe it had recieved a file.
116
- #
117
- # this is useful for sending 'attachments' (data to be downloaded) rather then
118
- # a regular response.
119
- #
120
- # this is also useful for offering a file name for the browser to "save as".
121
- #
122
- # it accepts:
123
- # data:: the data to be sent - this could be a String or an open File handle.
124
- # options:: a hash of any of the options listed furtheron.
125
- #
126
- # the :symbol=>value options are:
127
- # type:: the mime-type of the data to be sent. defaults to empty. if :filename is supplied, an attempt to guess will be made.
128
- # inline:: sets the data to be sent an an inline object (to be viewed rather then downloaded). defaults to false.
129
- # filename:: sets a filename for the browser to "save as". defaults to empty.
130
- #
131
- def send_data data, options = {}
132
- raise 'Cannot use "send_data" after headers were sent' if response.headers_sent?
133
- if response.body && response.body.any?
134
- Plezi.warn 'existing response body was cleared by `#send_data`!'
135
- response.body.close if response.body.respond_to? :close
136
- end
137
- response.body = data
138
-
139
- # set headers
140
- content_disposition = options[:inline] ? 'inline' : 'attachment'
141
- content_disposition << "; filename=#{::File.basename(options[:filename])}" if options[:filename]
142
-
143
- response['content-type'] = (options[:type] ||= options[:filename] && MimeTypeHelper::MIME_DICTIONARY[::File.extname(options[:filename])])
144
- response['content-disposition'] = content_disposition
145
- true
146
- end
147
-
148
- # Renders a template file (.slim/.erb/.haml) to a String and attempts to set the response's 'content-type' header (if it's still empty).
149
- #
150
- # For example, to render the file `body.html.slim` with the layout `main_layout.html.haml`:
151
- # render :body, layout: :main_layout
152
- #
153
- # or, for example, to render the file `json.js.slim`
154
- # render :json, format: 'js'
155
- #
156
- # or, for example, to render the file `template.haml`
157
- # render :template, format: ''
158
- #
159
- # template:: a Symbol for the template to be used.
160
- # options:: a Hash for any options such as `:layout` or `locale`.
161
- # block:: an optional block, in case the template has `yield`, the block will be passed on to the template and it's value will be used inplace of the yield statement.
162
- #
163
- # options aceept the following keys:
164
- # format:: the format for the `:layout' and 'template'. can be any format (the file's sub-extention), such as `"json"`. defaults to `"html"`.
165
- # layout:: a layout template that has at least one `yield` statement where the template will be rendered.
166
- # locale:: the I18n locale for the render. (defaults to params\[:locale]) - only if the I18n gem namespace is defined (`require 'i18n'`).
167
- #
168
- # if template is a string, it will assume the string is an
169
- # absolute path to a template file. it will NOT search for the template but might raise exceptions.
170
- #
171
- # if the template is a symbol, the '_' characters will be used to destinguish sub-folders (NOT a partial template).
172
- #
173
- # returns false if the template or layout files cannot be found.
174
- def render template, options = {}, &block
175
- # make sure templates are enabled
176
- return false if host_params[:templates].nil?
177
- # set up defaults
178
- @warned_type ||= (Iodine.warn("Deprecation warning! `#render` method called with optional `:type`. Use `:format` instead!") && true) if options[:type]
179
- options[:format] ||= (options[:type] || params[:format] || 'html'.freeze).to_s
180
- options[:locale] ||= params[:locale].to_sym if params[:locale]
181
- # render layout using recursion, if exists
182
- if options[:layout]
183
- layout = options.delete(:layout)
184
- inner = render(template, options, &block)
185
- return false unless inner
186
- return render(layout, options) { inner }
187
- end
188
- #update content-type header
189
- case options[:format]
190
- when 'html', 'js', 'txt'
191
- response['content-type'] ||= "#{MimeTypeHelper::MIME_DICTIONARY[".#{options[:format]}".freeze]}; charset=utf-8".freeze
192
- else
193
- response['content-type'] ||= "#{MimeTypeHelper::MIME_DICTIONARY[".#{options[:format]}".freeze]}".freeze
194
- end
195
- # Circumvents I18n persistance issues (live updating and thread data storage).
196
- I18n.locale = options[:locale] || I18n.default_locale if defined?(I18n) # sets the locale to nil for default behavior even if the locale was set by a previous action - removed: # && options[:locale]
197
- # find template and create template object
198
- template = [template] if template.is_a?(String)
199
- filename = ( template.is_a?(Array) ? File.join( host_params[:templates].to_s, *template) : File.join( host_params[:templates].to_s, *template.to_s.split('_'.freeze) ) ) + (options[:format].empty? ? ''.freeze : ".#{options[:format]}".freeze)
200
- ::Plezi::Renderer.render filename, binding, &block
201
- end
202
-
203
- # returns the initial method called (or about to be called) by the router for the HTTP request.
204
- #
205
- # this can be very useful within the before / after filters:
206
- # def before
207
- # return false unless "check credentials" && [:save, :update, :delete].include?(requested_method)
208
- #
209
- # if the controller responds to a WebSockets request (a controller that defines the `on_message` method),
210
- # the value returned is invalid and will remain 'stuck' on :pre_connect
211
- # (which is the last method called before the protocol is switched from HTTP to WebSockets).
212
- def requested_method
213
- # respond to websocket special case
214
- return :pre_connect if request.upgrade?
215
- # respond to save 'new' special case
216
- return (self.class.has_method?(:save) ? :save : false) if (request.request_method =~ /POST|PUT|PATCH/i.freeze) && (params[:id].nil? || params[:id] == 'new'.freeze)
217
- # set DELETE method if simulated
218
- request.request_method = 'DELETE'.freeze if params[:_method] && params[:_method].to_s.downcase == 'delete'.freeze
219
- # respond to special :id routing
220
- params[:id].to_s.downcase.to_sym.tap { |met| return met if self.class.has_exposed_method?(met) } if params[:id]
221
- #review general cases
222
- case request.request_method
223
- when 'GET'.freeze, 'HEAD'.freeze
224
- return (self.class.has_method?(:index) ? :index : false) unless params[:id]
225
- return (self.class.has_method?(:show) ? :show : false)
226
- when 'POST'.freeze, 'PUT'.freeze, 'PATCH'.freeze
227
- return (self.class.has_method?(:update) ? :update : false)
228
- when 'DELETE'.freeze
229
- return (self.class.has_method?(:delete) ? :delete : false)
230
- end
231
- false
232
- end
233
- end
234
-
235
- module ClassMethods
236
- public
237
-
238
- # This class method behaves the same way as the instance method #url_for, but accepts an added `params` Hash
239
- # that will be used to infer any persistent re-write parameters (i.e. `:locale` or `:format`).
240
- # See the instance method's documentation for more details.
241
- def url_for dest, params={}
242
- case dest
243
- when :index, nil, false
244
- dest = {}
245
- when String
246
- dest = {id: dest}
247
- when Numeric, Symbol
248
- dest = {id: dest}
249
- when Hash
250
- true
251
- else
252
- # convert dest.id and dest[:id] to their actual :id value.
253
- dest = {id: (dest.id rescue false) || (raise TypeError, "Expecting a Symbol, Hash, String, Numeric or an object that answers to obj[:id] or obj.id") }
254
- end
255
- ::Plezi::Base::HTTPRouter.url_for self, dest, params
256
- end
257
-
258
- # resets the routing cache
259
- def reset_routing_cache
260
- @inheritance.each {|sub| sub.reset_routing_cache} if @inheritance
261
- end
262
-
263
- protected
264
-
265
- # a callback that resets the class router whenever a method (a potential route) is added
266
- def method_added(id)
267
- reset_routing_cache
268
- end
269
- # a callback that resets the class router whenever a method (a potential route) is removed
270
- def method_removed(id)
271
- reset_routing_cache
272
- end
273
- # a callback that resets the class router whenever a method (a potential route) is undefined (using #undef_method).
274
- def method_undefined(id)
275
- reset_routing_cache
276
- end
277
-
278
- def inherited sub
279
- (@inheritance ||= [].to_set) << sub
280
- end
281
- end
282
-
283
- end
284
- end
@@ -1,205 +0,0 @@
1
- module Plezi
2
-
3
- module Base
4
-
5
- #####
6
- # handles the HTTP Routing
7
- module HTTPRouter
8
-
9
- class Host
10
- attr_reader :params
11
- attr_reader :routes
12
- def initialize params
13
- @params = params
14
- @routes = []
15
- @params[:assets_public_regex] = /^#{params[:assets_public].to_s.chomp('/')}\//i.freeze
16
- @params[:assets_public_length] = @params[:assets_public].to_s.chomp('/').length + 1
17
- @params[:assets_refuse_templates] = /(#{AssetManager.all_extentions.join('|')}|\.\.\/)$/i.freeze
18
- end
19
- end
20
-
21
- # return the upgrade handler (the self.on_upgrade method)
22
- def upgrade_proc
23
- self.method :on_upgrade
24
- end
25
- #handles websocket connection requests.
26
- def on_upgrade request, response
27
- host = get_host(request[:host_name].to_s.downcase) || @hosts[:default]
28
- return false unless host
29
- request[:host_settings] = host.params
30
- # return if a route answered the request
31
- host.routes.each {|r| a = r.on_request(request, response); return a if a}
32
- # websockets should cut out here
33
- false
34
- end
35
- # initializes the HTTP router (the normal Handler for HTTP requests)
36
- #
37
- # the router holds the different hosts and sends them messages/requests.
38
- @hosts = {}
39
- @active_host = nil
40
-
41
- # adds a host to the router (or activates an existing host to add new routes). accepts a host name and any parameters not related to the actual connection (ssl etc') (see {Plezi.host})
42
- def add_host host_name, params = {}
43
- (params = host_name) && (host_name = params.delete(:host)) if host_name.is_a?(Hash)
44
- params[:index_file] ||= 'index.html'
45
- params[:assets_public] ||= '/assets'
46
- params[:assets_public].chomp! '/'
47
- params[:public] ||= params[:root] # backwards compatability
48
- host_name = (host_name.is_a?(String) ? host_name.to_s.downcase : (host_name.is_a?(Regexp) ? host_name : :default))
49
- @active_host = get_host(host_name) || ( @hosts[host_name] = Host.new(params) )
50
- add_alias host_name, *params[:alias] if params[:alias] # && host_name != :default
51
- @active_host
52
- end
53
- # adds an alias to an existing host name (normally through the :alias parameter in the `add_host` method).
54
- def add_alias host_name, *aliases
55
- host = get_host host_name
56
- raise "Couldn't find requested host to add alias." unless host
57
- aliases.each {|a| @hosts[a.to_s.downcase] = host}
58
- true
59
- end
60
-
61
- # adds a route to the active host. The active host is the last host referenced by the `add_host`.
62
- def add_route path, controller, &block
63
- @active_host ||= add_host :default
64
- @active_host.routes << ::Plezi::Base::Route.new(path, controller, &block)
65
- end
66
-
67
- # adds a route to all existing hosts.
68
- def add_shared_route path, controller, &block
69
- add_host :default if @hosts.empty?
70
- @hosts.each {|n, h| h.routes << ::Plezi::Base::Route.new(path, controller, &block) }
71
- end
72
-
73
- # handles requests send by the HTTP Protocol (HTTPRequest objects)
74
- def call request, response
75
- begin
76
- host = get_host(request[:host_name].to_s.downcase) || @hosts[:default]
77
- return false unless host
78
- request[:host_settings] = host.params
79
- # render any assets?
80
- return true if render_assets request, response, host.params
81
- # send static file, if exists and root is set.
82
- return true if Base::HTTPSender.send_static_file request, response
83
- # return if a route answered the request
84
- host.routes.each {|r| a = r.on_request(request, response); return a if a}
85
- #return error code or 404 not found
86
- return Base::HTTPSender.send_by_code request, response, 404 unless ( @avoid_404 ||= ( Iodine::Http.on_http == ::Iodine::Http::Rack ? 1 : 0 ) ) == 1
87
- rescue => e
88
- # return 500 internal server error.
89
- Iodine.error e
90
- Base::HTTPSender.send_by_code request, response, 500
91
- end
92
- end
93
-
94
- # This method attempts to guess at the desired controller's URL, based on it's first path in order of route creation (ignoring host hierarchy).
95
- #
96
- # This will be usually used by the Controller's #url_for method to get the relative part of the url.
97
- def url_for controller, dest, params = {}
98
- raise TypeError, "Expecting destination parameter to be a Hash" unless dest.is_a?(Hash)
99
- host = nil
100
- @hosts.values.each do |h|
101
- h.routes.each {|r| (host = h) && (controller = r.controller) && break if r.controller && r.controller.ancestors.include?(controller) }
102
- break if host
103
- end
104
- raise "couldn't find Controller's route and host." unless host
105
- url = []
106
- dest = dest.dup
107
- dest.default_proc = Plezi::Base::Helpers::HASH_SYM_PROC
108
- host.routes.each do |r|
109
- if r.controller == false
110
- add = []
111
- r.url_array.each do |sec|
112
- next if sec == '*'
113
- param_name = (::Plezi::Base::Route::REGEXP_OPTIONAL_PARAMS.match(sec) || ::Plezi::Base::Route::REGEXP_FORMATTED_OPTIONAL_PARAMS.match(sec) || ::Plezi::Base::Route::REGEXP_REQUIRED_PARAMS.match(sec) || ::Plezi::Base::Route::REGEXP_FORMATTED_REQUIRED_PARAMS.match(sec))
114
- param_name = param_name[1].to_sym if param_name
115
-
116
- if param_name && (dest[param_name] || params[param_name])
117
- add << Plezi::Base::Helpers.encode_url(dest.delete(param_name) || params[param_name])
118
- elsif !param_name
119
- add << sec
120
- else
121
- add.clear
122
- next
123
- end
124
- end if r.url_array
125
- url.concat add
126
- end
127
- if r.controller == controller
128
- raise NotImplementedError, "#url_for isn't implemented for this controller's route - could this be a Regexp based or special route?" unless r.url_array
129
- r.url_array.each do |sec|
130
- next if sec == '*'
131
- param_name = (::Plezi::Base::Route::REGEXP_OPTIONAL_PARAMS.match(sec) || ::Plezi::Base::Route::REGEXP_FORMATTED_OPTIONAL_PARAMS.match(sec) || ::Plezi::Base::Route::REGEXP_REQUIRED_PARAMS.match(sec) || ::Plezi::Base::Route::REGEXP_FORMATTED_REQUIRED_PARAMS.match(sec))
132
- param_name = param_name[1].to_sym if param_name
133
- if param_name && dest[param_name]
134
- url << Plezi::Base::Helpers.encode_url(dest.delete(param_name))
135
- elsif !param_name
136
- url << sec
137
- elsif ::Plezi::Base::Route::REGEXP_REQUIRED_PARAMS === sec || ::Plezi::Base::Route::REGEXP_OPTIONAL_PARAMS === sec
138
- url << ''.freeze
139
- elsif ::Plezi::Base::Route::REGEXP_FORMATTED_REQUIRED_PARAMS === sec
140
- raise ArgumentError, "URL can't be formatted becuse a required parameter (#{param_name.to_s}) isn't specified and it requires a special format (#{::Plezi::Base::Route::REGEXP_FORMATTED_REQUIRED_PARAMS.match(sec)[2]})."
141
- end
142
- end
143
- return "/#{url.join '/'.freeze}#{"?#{dest.map {|k,v| "#{Plezi::Base::Helpers.encode_url k}=#{Plezi::Base::Helpers.encode_url v}" } .join('&'.freeze)}" if dest.any?}"
144
- end
145
- end
146
- false
147
- end
148
-
149
- protected
150
-
151
- def get_host host_name
152
- @hosts.each {|k, v| return v if k === host_name}
153
- nil
154
- end
155
-
156
- ###############
157
- ## asset rendering and responses
158
-
159
- # renders assets, if necessary, and places the rendered result in the cache and in the public folder.
160
- def render_assets request, response, params
161
- # contine only if assets are defined and called for
162
- return false unless params[:assets] && (request.path =~ params[:assets_public_regex])
163
- # review callback, if defined
164
- return true if params[:assets_callback] && params[:assets_callback].call(request, response)
165
-
166
- # get file requested
167
- source_file = File.join(params[:assets], *(request.path[params[:assets_public_length]..-1].split('/')))
168
-
169
-
170
- # stop if file name is reserved / has security issues
171
- return false if File.directory?(source_file) || source_file =~ params[:assets_refuse_templates]
172
-
173
- # set where to store the rendered asset
174
- target_file = File.join( params[:public].to_s, *request.path.split('/') )
175
-
176
- # send the file if it exists (no render needed)
177
- if File.exists?(source_file)
178
- data = if ::Plezi::Cache::CACHABLE.include?(::File.extname(source_file)[1..-1])
179
- Plezi.cache_needs_update?(source_file) ? Plezi.save_file(target_file, Plezi.reload_file(source_file), (params[:public] && params[:save_assets])) : Plezi.load_file(source_file)
180
- else
181
- ::File.new source_file, 'rb'
182
- end
183
- return (data ? Base::HTTPSender.send_raw_data(request, response, data, MimeTypeHelper::MIME_DICTIONARY[::File.extname(source_file)]) : false)
184
- end
185
-
186
- # render the file if it's a registered asset
187
- data = ::Plezi::AssetManager.render source_file, binding
188
- if data
189
- return ::Plezi::Base::HTTPSender.send_raw_data request, response, Plezi.save_file(target_file, data, (params[:public] && params[:save_assets])), MimeTypeHelper::MIME_DICTIONARY[::File.extname(source_file)]
190
- end
191
-
192
- # send the data if it's a cached asset (map files and similar assets that were cached while rendering)
193
- if Plezi.cached?(source_file)
194
- return Base::HTTPSender.send_raw_data(request, response, Plezi.get_cached(source_file), MimeTypeHelper::MIME_DICTIONARY[::File.extname(source_file)])
195
- end
196
-
197
- # return false if an asset couldn't be rendered and wasn't found.
198
- return false
199
- end
200
- extend self
201
- end
202
- Iodine::Http.on_http ::Plezi::Base::HTTPRouter
203
- Iodine::Http.on_websocket ::Plezi::Base::HTTPRouter.upgrade_proc
204
- end
205
- end