plezi 0.14.4 → 0.14.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/bin/ws_shootout +30 -0
- data/exe/plezi +108 -108
- data/lib/plezi.rb +18 -26
- data/lib/plezi/activation.rb +16 -16
- data/lib/plezi/api.rb +51 -50
- data/lib/plezi/controller/controller.rb +249 -229
- data/lib/plezi/controller/controller_class.rb +189 -174
- data/lib/plezi/controller/cookies.rb +49 -47
- data/lib/plezi/helpers.rb +35 -35
- data/lib/plezi/render/erb.rb +25 -26
- data/lib/plezi/render/has_cache.rb +31 -31
- data/lib/plezi/render/markdown.rb +53 -53
- data/lib/plezi/render/render.rb +36 -38
- data/lib/plezi/render/sass.rb +43 -44
- data/lib/plezi/render/slim.rb +25 -25
- data/lib/plezi/router/adclient.rb +14 -15
- data/lib/plezi/router/assets.rb +59 -61
- data/lib/plezi/router/errors.rb +22 -22
- data/lib/plezi/router/route.rb +98 -100
- data/lib/plezi/router/router.rb +120 -113
- data/lib/plezi/version.rb +1 -1
- data/lib/plezi/websockets/message_dispatch.rb +118 -80
- data/lib/plezi/websockets/redis.rb +42 -43
- data/plezi.gemspec +3 -3
- data/resources/client.js +229 -204
- data/resources/ctrlr.rb +26 -26
- data/resources/mini_app.rb +1 -1
- data/resources/simple-client.js +50 -43
- metadata +9 -8
data/lib/plezi/render/slim.rb
CHANGED
@@ -1,33 +1,33 @@
|
|
1
1
|
require 'plezi/render/has_cache' unless defined? ::Plezi::Base::HasStore
|
2
2
|
module Plezi
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
module Base
|
4
|
+
module RenderSlim
|
5
|
+
extend ::Plezi::Base::HasStore
|
6
6
|
|
7
|
-
|
7
|
+
module_function
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
9
|
+
def call(filename, context, &block)
|
10
|
+
return unless defined? ::Slim
|
11
|
+
return unless File.exist?(filename)
|
12
|
+
engine = load_engine(filename)
|
13
|
+
engine.render(context.receiver, &block)
|
14
|
+
end
|
15
|
+
if ENV['RACK_ENV'.freeze] == 'production'.freeze
|
16
|
+
def load_engine(filename)
|
17
|
+
engine = self[filename]
|
18
|
+
return engine if engine
|
19
|
+
self[filename] = (Slim::Template.new { ::Plezi.try_utf8!(IO.binread(filename)) })
|
20
|
+
end
|
21
|
+
else
|
22
|
+
def load_engine(filename)
|
23
|
+
engine, tm = self[filename]
|
24
|
+
return engine if engine && (tm == File.mtime(filename))
|
25
|
+
self[filename] = [(engine = Slim::Template.new { ::Plezi.try_utf8!(IO.binread(filename)) }), File.mtime(filename)]
|
26
|
+
engine
|
27
|
+
end
|
28
|
+
end
|
14
29
|
end
|
15
|
-
|
16
|
-
def load_engine(filename)
|
17
|
-
engine = self[filename]
|
18
|
-
return engine if engine
|
19
|
-
self[filename] = (Slim::Template.new { ::Plezi.try_utf8!(IO.binread(filename)) })
|
20
|
-
end
|
21
|
-
else
|
22
|
-
def load_engine(filename)
|
23
|
-
engine, tm = self[filename]
|
24
|
-
return engine if engine && (tm == File.mtime(filename))
|
25
|
-
self[filename] = [(engine = Slim::Template.new { ::Plezi.try_utf8!(IO.binread(filename)) }), File.mtime(filename)]
|
26
|
-
engine
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
30
|
+
end
|
31
31
|
end
|
32
32
|
|
33
33
|
::Plezi::Renderer.register :slim, ::Plezi::Base::RenderSlim
|
@@ -1,23 +1,22 @@
|
|
1
1
|
require 'plezi/router/route'
|
2
2
|
require 'plezi/router/errors'
|
3
3
|
require 'plezi/router/assets'
|
4
|
-
require 'rack'
|
5
4
|
|
6
5
|
module Plezi
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
6
|
+
module Base
|
7
|
+
module Router
|
8
|
+
class ADClient
|
9
|
+
def index
|
10
|
+
fname = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'resources', 'client.js'))
|
11
|
+
response.body = File.open(fname)
|
12
|
+
response['X-Sendfile'] = fname
|
13
|
+
true
|
14
|
+
end
|
16
15
|
|
17
|
-
|
18
|
-
|
19
|
-
|
16
|
+
def show
|
17
|
+
index
|
18
|
+
end
|
19
|
+
end
|
20
20
|
end
|
21
|
-
|
22
|
-
end
|
21
|
+
end
|
23
22
|
end
|
data/lib/plezi/router/assets.rb
CHANGED
@@ -1,67 +1,65 @@
|
|
1
|
-
require 'fileutils'
|
2
|
-
require 'set'
|
3
1
|
module Plezi
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
2
|
+
module Base
|
3
|
+
class Assets
|
4
|
+
if ENV['RACK_ENV'.freeze] == 'production'.freeze
|
5
|
+
def index
|
6
|
+
name = File.join(Plezi.assets, *params['*'.freeze]).freeze
|
7
|
+
data = ::Plezi::AssetBaker.bake(name)
|
8
|
+
return false unless data
|
9
|
+
name = File.join(Iodine::Rack.public, request.path_info[1..-1]).freeze if Iodine::Rack.public
|
10
|
+
if data.is_a?(String)
|
11
|
+
FileUtils.mkpath File.dirname(name)
|
12
|
+
IO.binwrite(name, data)
|
13
|
+
end
|
14
|
+
response['X-Sendfile'.freeze] = name
|
15
|
+
response.body = File.open(name)
|
16
|
+
true
|
17
|
+
end
|
18
|
+
else
|
19
|
+
def index
|
20
|
+
name = File.join(Plezi.assets, *params['*'.freeze]).freeze
|
21
|
+
data = ::Plezi::AssetBaker.bake(name)
|
22
|
+
IO.binwrite(name, data) if data.is_a?(String)
|
23
|
+
if File.exist? name
|
24
|
+
response['X-Sendfile'.freeze] = name
|
25
|
+
response.body = File.open(name)
|
26
|
+
return true
|
27
|
+
end
|
28
|
+
false
|
29
|
+
end
|
30
|
+
end
|
33
31
|
|
34
|
-
|
35
|
-
|
32
|
+
def show
|
33
|
+
index
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
# This module is used for asset "baking" (or "belated baking"). It allows us to easily register and support new types of assets.
|
38
|
+
module AssetBaker
|
39
|
+
@drivers = {}
|
40
|
+
# Registers a new Asset Driver of a specific extension (i.e. "css", "js", etc')
|
41
|
+
#
|
42
|
+
# Multiple Asset Drivers can be registered for the same extension. The will be attempted in the order of their registration.
|
43
|
+
#
|
44
|
+
# An Asset Drivers is an object that responsd to `.call(target)`.
|
45
|
+
# If the traget is newly rendered, the driver should return the rendered text.
|
46
|
+
# If the asset didn't change since the last time `.call(target)` was called, the driver should return 'true' (meanning, yet, the asset exists, it's the same).
|
47
|
+
# If the driver doesn't locate the asset, it should return `nil` or `false`, indicating the next driver should be attempted.
|
48
|
+
def self.register(ext, driver)
|
49
|
+
(@drivers[".#{ext}".freeze] ||= [].to_set) << driver
|
36
50
|
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
# This module is used for asset "baking" (or "belated baking"). It allows us to easily register and support new types of assets.
|
40
|
-
module AssetBaker
|
41
|
-
@drivers = {}
|
42
|
-
# Registers a new Asset Driver of a specific extension (i.e. "css", "js", etc')
|
43
|
-
#
|
44
|
-
# Multiple Asset Drivers can be registered for the same extension. The will be attempted in the order of their registration.
|
45
|
-
#
|
46
|
-
# An Asset Drivers is an object that responsd to `.call(target)`.
|
47
|
-
# If the traget is newly rendered, the driver should return the rendered text.
|
48
|
-
# If the asset didn't change since the last time `.call(target)` was called, the driver should return 'true' (meanning, yet, the asset exists, it's the same).
|
49
|
-
# If the driver doesn't locate the asset, it should return `nil` or `false`, indicating the next driver should be attempted.
|
50
|
-
def self.register(ext, driver)
|
51
|
-
(@drivers[".#{ext}".freeze] ||= [].to_set) << driver
|
52
|
-
end
|
53
51
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
52
|
+
# @private
|
53
|
+
# called by Plezi when in need of baking an asset.
|
54
|
+
def self.bake(name)
|
55
|
+
ret = nil
|
56
|
+
ext = File.extname name
|
57
|
+
return false if ext.empty?
|
58
|
+
driver = @drivers[ext]
|
59
|
+
return false if driver.nil?
|
60
|
+
driver.each { |d| ret = d.call(name); return ret if ret }
|
61
|
+
nil
|
62
|
+
end
|
63
|
+
end
|
66
64
|
end
|
67
65
|
require 'plezi/render/sass.rb'
|
data/lib/plezi/router/errors.rb
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
module Plezi
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
2
|
+
module Base
|
3
|
+
class Err404Ctrl
|
4
|
+
def index
|
5
|
+
response.status = 404
|
6
|
+
render('404') || 'Error 404, not found.'
|
7
|
+
end
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
def requested_method
|
10
|
+
:index
|
11
|
+
end
|
12
12
|
|
13
|
-
|
14
|
-
end
|
15
|
-
class Err500Ctrl
|
16
|
-
def index
|
17
|
-
response.status = 500
|
18
|
-
render('500') || 'Internal Error 500.'
|
19
|
-
rescue
|
20
|
-
'Internal Error 500.'
|
13
|
+
include Plezi::Controller
|
21
14
|
end
|
15
|
+
class Err500Ctrl
|
16
|
+
def index
|
17
|
+
response.status = 500
|
18
|
+
render('500') || 'Internal Error 500.'
|
19
|
+
rescue
|
20
|
+
'Internal Error 500.'
|
21
|
+
end
|
22
22
|
|
23
|
-
|
24
|
-
|
23
|
+
def requested_method
|
24
|
+
:index
|
25
|
+
end
|
26
|
+
include Plezi::Controller
|
25
27
|
end
|
26
|
-
|
27
|
-
end
|
28
|
-
end
|
28
|
+
end
|
29
29
|
end
|
data/lib/plezi/router/route.rb
CHANGED
@@ -1,113 +1,111 @@
|
|
1
1
|
require 'plezi/controller/controller'
|
2
|
-
require 'thread'
|
3
|
-
require 'rack'
|
4
|
-
require 'rack/query_parser.rb'
|
5
2
|
|
6
3
|
module Plezi
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
module Base
|
5
|
+
class Route
|
6
|
+
attr_reader :prefix, :controller, :param_names
|
10
7
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
8
|
+
def initialize(path, controller)
|
9
|
+
@route_id = "Route#{object_id.to_s(16)}".to_sym
|
10
|
+
@params_range = (0..0)
|
11
|
+
m = path.match(/([^\:\(\*]*)(.*)/)
|
12
|
+
@prefix = m[1].chomp('/'.freeze)
|
13
|
+
if @prefix.nil? || @prefix == ''.freeze
|
14
|
+
@prefix = '/'.freeze
|
15
|
+
@prefix_length = 1
|
16
|
+
else
|
17
|
+
@prefix = "/#{@prefix}" if @prefix[0] != '/'.freeze
|
18
|
+
@prefix_length = @prefix.length + 1
|
19
|
+
end
|
20
|
+
@controller = controller
|
21
|
+
@param_names = []
|
22
|
+
@origial = path.dup.freeze
|
23
|
+
prep_params(m[2])
|
24
|
+
self.class.qp
|
25
|
+
case @controller
|
26
|
+
when Class
|
27
|
+
prep_controller
|
28
|
+
when Regexp
|
29
|
+
raise "Rewrite Routes can't contain more then one parameter to collect" if @param_names.length > 1
|
30
|
+
else
|
31
|
+
raise 'Controller should be a class object' unless controller.is_a?(Class)
|
32
|
+
end
|
33
|
+
end
|
36
34
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
35
|
+
def call(request, response)
|
36
|
+
return nil unless match(request.path_info, request)
|
37
|
+
c = @controller.new
|
38
|
+
c._pl_respond(request, response, Thread.current[@route_id])
|
39
|
+
end
|
42
40
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
41
|
+
def fits_params(path, request)
|
42
|
+
params = (Thread.current[@route_id] ||= {}).clear
|
43
|
+
params.update request.params.to_h if request && request.params
|
44
|
+
# puts "cutting: #{path[(@prefix_length)..-1] ? path[(@prefix_length + 1)..-1] : 'nil'}"
|
45
|
+
pa = (path[@prefix_length..-1] || ''.freeze).split('/'.freeze)
|
46
|
+
# puts "check param count: #{pa}"
|
47
|
+
return false unless @params_range.include?(pa.length)
|
48
|
+
@param_names.each do |key|
|
49
|
+
next if pa[0].nil?
|
50
|
+
self.class.qp.normalize_params(params, Plezi.try_utf8!(Rack::Utils.unescape(key)),
|
51
|
+
Plezi.try_utf8!(Rack::Utils.unescape(pa.shift)), 100)
|
52
|
+
end
|
53
|
+
params['*'.freeze] = pa unless pa.empty?
|
54
|
+
true
|
55
|
+
end
|
58
56
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
57
|
+
def match(req_path, request = nil)
|
58
|
+
# puts "#{req_path} starts with #{@prefix}? #{req_path.start_with?(@prefix)}"
|
59
|
+
req_path.start_with?(@prefix) && fits_params(req_path, request)
|
60
|
+
end
|
63
61
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
62
|
+
def prep_params(postfix)
|
63
|
+
pfa = postfix.split '/'.freeze
|
64
|
+
start = 0; stop = 0
|
65
|
+
optional = false
|
66
|
+
while pfa.any?
|
67
|
+
name = pfa.shift
|
68
|
+
raise "#{name} is not a valid path section in #{@origial}" unless /^((\:[\w\.\[\]]+)|(\(\:[\w\.\[\]]+\))|(\*))$/.match(name)
|
69
|
+
if name[0] == ':'
|
70
|
+
raise "Cannot have a required parameter after an optional parameter in #{@origial}" if optional
|
71
|
+
@param_names << name[1..-1].freeze
|
72
|
+
elsif name[0] == '('
|
73
|
+
optional = true
|
74
|
+
@param_names << name[2..-2].freeze
|
75
|
+
elsif name[0] == '*'
|
76
|
+
stop += 999_999
|
77
|
+
break
|
78
|
+
else
|
79
|
+
raise "invalid path section #{name} in #{@origial}"
|
80
|
+
end
|
81
|
+
optional ? (stop += 1) : (start += 1)
|
82
|
+
end
|
83
|
+
unless (@param_names.include? 'id'.freeze) || stop >= 999_999
|
84
|
+
@param_names << 'id'.freeze
|
85
|
+
stop += 1
|
86
|
+
end
|
87
|
+
@params_range = (start..(start + stop))
|
88
|
+
@param_names.freeze
|
89
|
+
@params_range.freeze
|
90
|
+
end
|
93
91
|
|
94
|
-
|
95
|
-
|
96
|
-
|
92
|
+
def prep_controller
|
93
|
+
@controller.include Plezi::Controller
|
94
|
+
end
|
97
95
|
|
98
|
-
|
99
|
-
|
96
|
+
def self.qp
|
97
|
+
@qp ||= ::Rack::QueryParser.new(Hash, 65_536, 100)
|
98
|
+
end
|
100
99
|
end
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
100
|
+
class RouteRewrite < Route
|
101
|
+
def call(request, _response)
|
102
|
+
return nil unless match(request.path_info, request)
|
103
|
+
params = Thread.current[@route_id]
|
104
|
+
return nil unless controller =~ params[@param_names[0]]
|
105
|
+
request.path_info = "/#{params.delete('*'.freeze).to_a.join '/'}"
|
106
|
+
request.params.update params
|
107
|
+
nil
|
108
|
+
end
|
110
109
|
end
|
111
|
-
|
112
|
-
end
|
110
|
+
end
|
113
111
|
end
|