plezi 0.12.22 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
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