plezi 0.10.11 → 0.10.12

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3ae320b0b94bf0515e804c8f578919e46147d349
4
- data.tar.gz: b82256beacdbd56c48b66755d4b086d0293452fb
3
+ metadata.gz: 160e5060bd9cf3f8ec6acf8caa7d672ae238f3c7
4
+ data.tar.gz: d2816045210ac66cec18b0c5f37060a9ec5ae271
5
5
  SHA512:
6
- metadata.gz: ebeaa5a013faf936e694f5d54fd212d1c299f015631f63667c0e0419958321f86086f8087d94111c194656247101d3d65f621fe15177a2931a83199d0ed3be76
7
- data.tar.gz: 8df8144823d9be37ecd9d8d89e01b116c5aed875188781ea5953961b022b5c8765ca84b4c312b20fb2c98ca132f819aa8f296140ea718346d3af914227b3a5c2
6
+ metadata.gz: 59691c8ce5b334a0e1b7223aaeb4e0ae74f5f800e24e803e8ad6e8aeb9492f299c71c50c46ca740a8a1940c7c50e4a28f332365ff40853b9221864cb8e3b2769
7
+ data.tar.gz: f738389e77c3bdc471e6000db4bfd83f8cbb0133814074c0ba4cbc69c5ecae229a18904f5cd3a8ca32253c7266637563c356cda8ca1cb1f2db4936c09d1a3c15
@@ -2,13 +2,23 @@
2
2
 
3
3
  ***
4
4
 
5
+ Change log v.0.10.12
6
+
7
+ **BIG Feature**: Run both your existing Rack app and plezi on he same GRHttp server - augment your app with all of Plezi's amasing features (two frameworks in one).
8
+
9
+ **Updates** updates to the mini template, the testing, the core API code and many more minor updates.
10
+
11
+ **API published**: Most of the private API in the Plezi::Base::DSL module was just made public (moving the methods to the main Plezi namespace). Your app should work as before unless you used private method calls instead of Plezi's published API.
12
+
13
+ ***
14
+
5
15
  Change log v.0.10.11
6
16
 
7
17
  **Feature**: added the mini-app template, for quick websocket oriented apps that are meant to be attached to other frameworks (use `$ plezi mini appname` or `$ plezi m appname`).
8
18
 
9
19
  **Feature**: allow Regexp hosts in the `listen` and `host` methods.
10
20
 
11
- **Fix**: An error in the chache system was introduced when performing slight performance enhancements (two variable names were switched). The issue is now fixed.
21
+ **Fix**: An error in the cache system was introduced when performing slight performance enhancements (two variable names were switched). The issue is now fixed.
12
22
 
13
23
  **Fix**: Correctly handle multiple `listen` calls with the same port number.
14
24
 
data/README.md CHANGED
@@ -1,16 +1,12 @@
1
- # Plezi, The Rack Free Ruby framework for realtime web-apps
1
+ # Plezi, The Ruby framework for realtime web-apps
2
2
  [![Gem Version](https://badge.fury.io/rb/plezi.svg)](http://badge.fury.io/rb/plezi)
3
3
  [![Inline docs](http://inch-ci.org/github/boazsegev/plezi.svg?branch=master)](http://www.rubydoc.info/github/boazsegev/plezi/master)
4
4
 
5
- > People who are serious about their frameworks, should write their own servers...
5
+ Plezi is an easy to use Ruby Websocket Framework, with full RESTful routing support and HTTP streaming support. It's name comes from the word "fun", or "pleasure", since Plezi is a pleasure to work with.
6
6
 
7
- Find more info on [Plezi's framework documentation](http://www.rubydoc.info/github/boazsegev/plezi/master)
7
+ I Believe that Plezi is a wonderful backend solution for developing SPAs, both with it's real-time native Websocket API and with it's RESTful routes that work great for writing easy AJAX requests.
8
8
 
9
- ## About the Plezi framework
10
-
11
- Plezi is an easy to use Ruby Websocket Framework, with full RESTful routing support and HTTP streaming support. It's name comes from the word "fun" in Haitian, since Plezi is really fun to work with and it keeps our code clean and streamlined.
12
-
13
- Plezi can both augment an existing Rails/Sinatra app, by providing it with easy Websocket and Asynchronous Events support, as well as offer an alternative to a Rack/Rails/Sintra/Faye/EM-Websockets combo. It's also great as an alternative to socket.io, allowing for both websockets and long pulling.
9
+ Plezi can both provide a wonderful alternative to existing complex platforms (i.e. Rails/Sinatra/Faye/EM) and augment an existing Rails/Sinatra app, by providing it with easy Websocket and Asynchronous Events support. It's also great as an alternative to socket.io, allowing for both websockets and long pulling.
14
10
 
15
11
  Plezi runs over the [GRHttp server](https://github.com/boazsegev/GRHttp), which is a pure Ruby HTTP and Websocket Generic Server build using [GReactor](https://github.com/boazsegev/GReactor) - a multi-threaded pure ruby alternative to EventMachine with basic process forking support (enjoy it, if your code is scaling ready).
16
12
 
@@ -129,7 +125,37 @@ method names starting with an underscore ('_') will NOT be made public by the ro
129
125
 
130
126
  You already have an amazing WebApp, but now you want to add websocket broadcasting and unicasting support - Plezi makes connection your existing WebApp with your Plezi Websocket backend as easy as it gets.
131
127
 
132
- Simply include the Plezi App in your existing app and call `Plezi.start_placebo` - now you can access all the websocket API that you want from your existing WebApp.
128
+
129
+ There are two easy ways to augment your existing WebApp, depending on your needs and preferences:
130
+
131
+ 1. Let Plezi and GRHttp run your application as a fallback position, defering to your application for anything Plezi doesn't handle (Plezi Websockets and routes will recieve priority).
132
+
133
+ 2. Run Plezi on a seperate process/server and set up communication between the two apps.
134
+
135
+ ### The super easy augmentation - run together
136
+
137
+ The easiest way to augment your existing application is to use GRHttp's Rack adapter to run your Rack app, while Plezi will use GRHttp's native features (such as Websockets and HTTP streaming).
138
+
139
+ You can eaither use your existing Plezi application or create a new mini plezi application inside your existing app folder using:
140
+
141
+ $ plezi mini appname
142
+
143
+ Next, add the `plezi` gem to your `Gemfile` and add the following line somewhere in your apps code:
144
+
145
+ ```ruby
146
+ require './appname/appname.rb'
147
+ Plezi.start_rack
148
+ ```
149
+
150
+ That's it! Now you can use the Plezi API and your existing application's API at the same time and they are both running on the same server.
151
+
152
+ Plezi's route have priority, so that your app can keep handling the 404 (not found) error page.
153
+
154
+ In the next section we will explore how to set up the placebo API for cross process apps... since you are sharing the same space, you won't need it - but you can still use most of the Placebo API if you wish to do so (just **don't** call `Plezi.start_placebo`)
155
+
156
+ ### The easy (but not super easy) augmentation - talking from afar
157
+
158
+ To use Plezi and your App on different processes, without mixing them together, simply include the Plezi App in your existing app and call `Plezi.start_placebo` - now you can access all the websocket API that you want from your existing WebApp.
133
159
 
134
160
  For instance, add the following code to your environment on a Rails or Sinatra app:
135
161
 
data/bin/plezi CHANGED
@@ -99,6 +99,7 @@ class AppTemplate
99
99
  app_tree["config"]["sequel.rb"] ||= IO.read(::File.expand_path(File.join("..", "..", "resources" ,"db_sequel_config.rb"), __FILE__))
100
100
  app_tree["config"]["datamapper.rb"] ||= IO.read(::File.expand_path(File.join("..", "..", "resources" ,"db_dm_config.rb"), __FILE__))
101
101
  app_tree["config"]["haml.rb"] ||= IO.read(::File.expand_path(File.join("..", "..", "resources" ,"haml_config.rb"), __FILE__))
102
+ app_tree["config"]["slim.rb"] ||= IO.read(::File.expand_path(File.join("..", "..", "resources" ,"slim_config.rb"), __FILE__))
102
103
  app_tree["config"]["i18n.rb"] ||= IO.read(::File.expand_path(File.join("..", "..", "resources" ,"i18n_config.rb"), __FILE__))
103
104
  app_tree["config"]["redis.rb"] ||= (IO.read(::File.expand_path(File.join("..", "..", "resources" ,"redis_config.rb"), __FILE__))).gsub('appsecret', "#{ARGV[1]}_#{SecureRandom.hex}")
104
105
 
@@ -30,6 +30,7 @@ require "plezi/version"
30
30
 
31
31
  require 'plezi/common/defer.rb'
32
32
  require 'plezi/common/cache.rb'
33
+ require 'plezi/common/api.rb'
33
34
  require 'plezi/common/dsl.rb'
34
35
  require 'plezi/common/redis.rb'
35
36
  require 'plezi/common/settings.rb'
@@ -0,0 +1,135 @@
1
+
2
+ module Plezi
3
+
4
+ module_function
5
+
6
+ # Defines methods used to set up the Plezi app.
7
+
8
+ # public API to add a service to the framework.
9
+ # accepts a Hash object with any of the following options (Hash keys):
10
+ # port:: port number. defaults to 3000 or the port specified when the script was called.
11
+ # host:: the host name. defaults to any host not explicitly defined (a catch-all). NOTICE: in order to allow for hostname aliases, this is host emulation and the listening socket will bind to all the addresses available. To limit the actual binding use the `:bind` parameter as set by the GReactor's API - in which case host aliases might not work.
12
+ # alias:: a String or an Array of Strings which represent alternative host names (i.e. `alias: ["admin.google.com", "admin.gmail.com"]`).
13
+ # root:: the public root folder. if this is defined, static files will be served from the location.
14
+ # assets:: the assets root folder. defaults to nil (no assets support). if the path is defined, assets will be served from `/assets/...` (or the public_asset path defined) before any static files. assets will not be served if the file in the /public/assets folder if up to date (a rendering attempt will be made for systems that allow file writing).
15
+ # assets_public:: the assets public uri location (uri format, NOT a file path). defaults to `/assets`. assets will be saved (or rendered) to the assets public folder and served as static files.
16
+ # assets_callback:: a method that accepts two parameters: (request, response) and renders any custom assets. the method should return `false` unless it had set the response.
17
+ # save_assets:: saves the rendered assets to the filesystem, under the public folder. defaults to false.
18
+ # templates:: the templates root folder. defaults to nil (no template support). templates can be rendered by a Controller class, using the `render` method.
19
+ # ssl:: if true, an SSL service will be attempted. if no certificate is defined, an attempt will be made to create a self signed certificate.
20
+ # ssl_key:: the public key for the SSL service.
21
+ # ssl_cert:: the certificate for the SSL service.
22
+ #
23
+ # assets:
24
+ #
25
+ # assets support will render `.sass`, `.scss` and `.coffee` and save them as local files (`.css`, `.css`, and `.js` respectively)
26
+ # before sending them as static files.
27
+ #
28
+ # templates:
29
+ #
30
+ # ERB, Slim and Haml are natively supported. Otherwise define an assets_callback (or submit a pull request with a patch).
31
+ #
32
+ # @returns [Plezi::Router]
33
+ #
34
+ def listen parameters = {}
35
+ # update default values
36
+ parameters[:index_file] ||= 'index.html'
37
+ parameters[:assets_public] ||= '/assets'
38
+ parameters[:assets_public].chomp! '/'
39
+
40
+ # check if the port is used twice.
41
+ @routers_locker.synchronize do
42
+ @active_router = GRHttp.listen(parameters)
43
+ unless @active_router[:upgrade_handler]
44
+ @routers << (@active_router[:http_handler] = ::Plezi::Base::HTTPRouter.new)
45
+ @active_router[:upgrade_handler] = @active_router[:http_handler].upgrade_proc
46
+ else
47
+ @active_router.delete :alias
48
+ end
49
+ @active_router[:http_handler].add_host(parameters[:host], @active_router.merge(parameters) )
50
+ @active_router = @active_router[:http_handler]
51
+ end
52
+ # return the current handler or the protocol..
53
+ @active_router
54
+ end
55
+
56
+ # clears all the listeners and routes defined
57
+ def clear_app
58
+ @routers_locker.synchronize {GReactor.clear_listeners; @routers.clear}
59
+ end
60
+ # adds a route to the last server created
61
+ def route(path, controller = nil, &block)
62
+ raise "Must define a listener before adding a route - use `Plezi.listen`." unless @active_router
63
+ @routers_locker.synchronize { @active_router.add_route path, controller, &block }
64
+ end
65
+
66
+
67
+ # adds a shared route to all existing services and hosts.
68
+ def shared_route(path, controller = nil, &block)
69
+ raise "Must have created at least one Pleze service before calling `shared_route` - use `Plezi.listen`." unless @routers
70
+ @routers_locker.synchronize { @routers.each {|r| r.add_shared_route path, controller, &block } }
71
+ end
72
+
73
+ # adds a host to the last server created
74
+ #
75
+ # accepts a host name and a parameter(s) Hash which are the same parameter(s) as {Plezi.listen} accepts:
76
+ def host(host_name, params)
77
+ raise "Must define a listener before adding a route - use `Plezi.listen`." unless @active_router
78
+ @routers_locker.synchronize { @active_router.add_host host_name, params }
79
+ end
80
+
81
+ # starts the Plezi framework server and hangs until the exit signal is given.
82
+ def start
83
+ start_async
84
+ puts "\nPress ^C to exit.\n"
85
+ GReactor.join { puts "\r\nStarting shutdown sequesnce. Press ^C to force quit."}
86
+ end
87
+
88
+ # Makes sure the GRHttp server will be used by Rack (if Rack is available) and disables Plezi's autostart feature.
89
+ #
90
+ # This method is a both a fail safe and a shortcut. Plezi will automatically attempt to diable autostart when discovering Rack
91
+ # but this method also makes sure that the GRHttp is set as the Rack server by setting the ENV\["RACK_HANDLER"] variable.
92
+ #
93
+ # This is used as an alternative to {Plezi.start_placebo}.
94
+ #
95
+ # Use {Plezi.start_placebo} to augment an existing app while operating Plezi on a different process or server.
96
+ #
97
+ # Use {Plezi.start_rack} to augment an existing Rack app (i.e. Rails/Sinatra) by loading both Plezi and the existing Rack app
98
+ # to the GRHtto server (it will set up GRHttp as the Rack server).
99
+ def start_rack
100
+ Object.const_set("NO_PLEZI_AUTO_START", true) unless defined?(NO_PLEZI_AUTO_START)
101
+ ENV["RACK_HANDLER"] = 'grhttp'
102
+ end
103
+ # starts the Plezi framework and returns immidiately,
104
+ # allowing you to run the Plezi framework along side another framework.
105
+ def start_async
106
+ Object.const_set("NO_PLEZI_AUTO_START", true) unless defined?(NO_PLEZI_AUTO_START)
107
+ return GReactor.start if GReactor.running?
108
+ puts "Starting Plezi #{Plezi::VERSION} Services using the GRHttp #{GRHttp::VERSION} server."
109
+ GReactor.on_shutdown { puts "Plezi shutdown. It was fun to serve you." }
110
+ GReactor.start Plezi::Settings.max_threads
111
+ end
112
+ # This allows you to run the Plezi framework along side another framework - WITHOUT running the actual server.
113
+ #
114
+ # The server will not be initiatet and instead you will be able to use Plezi controllers and the Redis auto-config
115
+ # to broadcast Plezi messages to other Plezi processes - allowing for scalable intigration of Plezi into other frameworks.
116
+ def start_placebo
117
+ GReactor.clear_listeners
118
+ redis_connection # make sure the redis connection is activated
119
+ puts "* Plezi #{Plezi::VERSION} Services will start with no Server...\n"
120
+ start_async
121
+ end
122
+
123
+ # this module contains the methods that are used as a DSL and sets up easy access to the Plezi framework.
124
+ #
125
+ # use the`listen`, `host` and `route` functions rather then accessing this object.
126
+ #
127
+ @active_router = nil
128
+ @routers_locker = Mutex.new
129
+ @routers ||= [].to_set
130
+ end
131
+
132
+ Encoding.default_internal = 'utf-8'
133
+ Encoding.default_external = 'utf-8'
134
+
135
+ NO_PLEZI_AUTO_START = true if defined?(::Rack)
@@ -1,268 +1,106 @@
1
+ # PL is a shortcut for the Plezi module, so that `PL == Plezi`.
2
+ PL = Plezi
1
3
 
2
- module Plezi
3
-
4
- # this isn't part of the public API.
5
- module Base
6
-
7
- # holds methods that are called by the DSL.
8
- #
9
- # this isn't part of the public API.
10
- module DSL
11
- module_function
12
-
13
- # this module contains the methods that are used as a DSL and sets up easy access to the Plezi framework.
14
- #
15
- # use the`listen`, `host` and `route` functions rather then accessing this object.
16
- #
17
- @active_router = nil
18
-
19
-
20
- # public API to add a service to the framework.
21
- # accepts a Hash object with any of the following options (Hash keys):
22
- # port:: port number. defaults to 3000 or the port specified when the script was called.
23
- # host:: the host name. defaults to any host not explicitly defined (a catch-all).
24
- # alias:: a String or an Array of Strings which represent alternative host names (i.e. `alias: ["admin.google.com", "admin.gmail.com"]`).
25
- # root:: the public root folder. if this is defined, static files will be served from the location.
26
- # assets:: the assets root folder. defaults to nil (no assets support). if the path is defined, assets will be served from `/assets/...` (or the public_asset path defined) before any static files. assets will not be served if the file in the /public/assets folder if up to date (a rendering attempt will be made for systems that allow file writing).
27
- # assets_public:: the assets public uri location (uri format, NOT a file path). defaults to `/assets`. assets will be saved (or rendered) to the assets public folder and served as static files.
28
- # assets_callback:: a method that accepts two parameters: (request, response) and renders any custom assets. the method should return `false` unless it had set the response.
29
- # save_assets:: saves the rendered assets to the filesystem, under the public folder. defaults to false.
30
- # templates:: the templates root folder. defaults to nil (no template support). templates can be rendered by a Controller class, using the `render` method.
31
- # ssl:: if true, an SSL service will be attempted. if no certificate is defined, an attempt will be made to create a self signed certificate.
32
- # ssl_key:: the public key for the SSL service.
33
- # ssl_cert:: the certificate for the SSL service.
34
- #
35
- # assets:
36
- #
37
- # assets support will render `.sass`, `.scss` and `.coffee` and save them as local files (`.css`, `.css`, and `.js` respectively)
38
- # before sending them as static files.
39
- #
40
- # templates:
41
- #
42
- # ERB, Slim and Haml are natively supported.
43
- #
44
- # @returns [Plezi::Router]
45
- #
46
- def listen parameters = {}
47
- # update default values
48
- parameters[:index_file] ||= 'index.html'
49
- parameters[:assets_public] ||= '/assets'
50
- parameters[:assets_public].chomp! '/'
51
-
52
- if !parameters[:port] && defined? ARGV
53
- if ARGV.find_index('-p')
54
- port_index = ARGV.find_index('-p') + 1
55
- parameters[:port] ||= ARGV[port_index].to_i
56
- ARGV[port_index] = (parameters[:port] + 1).to_s
57
- else
58
- ARGV << '-p'
59
- ARGV << '3001'
60
- parameters[:port] ||= 3000
61
- end
62
- end
63
-
64
- #keeps information of past ports.
65
- @listeners ||= {}
66
- @listeners_locker = Mutex.new
67
-
68
- # check if the port is used twice.
69
- @listeners_locker.synchronize do
70
- if @listeners[parameters[:port]]
71
- puts "WARNING: port aleady in use! returning existing service and attemptin to add host (maybe multiple hosts? use `host` instead)."
72
- @active_router = @listeners[parameters[:port]][:http_handler]
73
- @active_router.add_host parameters[:host], parameters if @active_router.is_a?(HTTPRouter)
74
- return @active_router
75
- end
76
- end
77
- @listeners[parameters[:port]] = parameters
78
-
79
- # make sure the protocol exists.
80
- parameters[:http_handler] = HTTPRouter.new
81
- parameters[:upgrade_handler] = parameters[:http_handler].upgrade_proc
82
-
83
- GRHttp.listen parameters
84
- # set the active router to the handler or the protocol.
85
- @active_router = parameters[:http_handler]
86
- @active_router.add_host(parameters[:host], parameters)
87
-
88
- # return the current handler or the protocol..
89
- @active_router
90
- end
91
- # adds a route to the last server created
92
- def route(path, controller = nil, &block)
93
- raise "Must define a listener before adding a route - use `Plezi.listen`." unless @active_router
94
- @active_router.add_route path, controller, &block
95
- end
96
-
97
-
98
- # adds a shared route to all existing services and hosts.
99
- def shared_route(path, controller = nil, &block)
100
- raise "Must have created at least one Pleze service before calling `shared_route` - use `Plezi.listen`." unless @listeners
101
- @listeners.values.each {|p| p[:http_handler].add_shared_route path, controller, &block }
102
- end
103
-
104
- # adds a host to the last server created
105
- #
106
- # accepts a host name and a parameter(s) Hash which are the same parameter(s) as {Plezi.listen} accepts:
107
- def host(host_name, params)
108
- raise "Must define a listener before adding a route - use `Plezi.listen`." unless @active_router
109
- @active_router.add_host host_name, params
110
- end
111
-
4
+ unless defined? PLEZI_NON_DSL
112
5
 
113
- # tweeks a hash object to read both :symbols and strings (similar to Rails but without).
114
- def make_hash_accept_symbols hash
115
- @magic_hash_proc ||= Proc.new do |hs,k|
116
- if k.is_a?(Symbol) && hs.has_key?( k.to_s)
117
- hs[k.to_s]
118
- elsif k.is_a?(String) && hs.has_key?( k.to_sym)
119
- hs[k.to_sym]
120
- elsif k.is_a?(Numeric) && hs.has_key?(k.to_s.to_sym)
121
- hs[k.to_s.to_sym]
122
- end
123
- end
124
- hash.default_proc = @magic_hash_proc
125
- hash.values.each do |v|
126
- if v.is_a?(Hash)
127
- make_hash_accept_symbols v
128
- end
129
- end
130
- end
131
- end
6
+ # shortcut for Plezi.listen.
7
+ #
8
+ def listen(params = {})
9
+ Plezi.listen params
132
10
  end
133
11
 
134
- # starts the Plezi framework server and hangs until the exit signal is given.
135
- def self.start
136
- start_async
137
- puts "\nPress ^C to exit.\n"
138
- GReactor.join { puts "\r\nStarting shutdown sequesnce. Press ^C to force quit."}
139
- end
140
- # starts the Plezi framework and returns immidiately,
141
- # allowing you to run the Plezi framework along side another framework.
142
- def self.start_async
143
- Object.const_set("NO_PLEZI_AUTO_START", true) unless defined?(NO_PLEZI_AUTO_START)
144
- return GReactor.start if GReactor.running?
145
- puts "Starting Plezi #{Plezi::VERSION} Services using the GRHttp #{GRHttp::VERSION} server."
146
- GReactor.on_shutdown { puts "Plezi shutdown. It was fun to serve you." }
147
- GReactor.start Plezi::Settings.max_threads
148
- end
149
- # This allows you to run the Plezi framework along side another framework - WITHOUT running the actual server.
12
+ # adds a virtul host to the current service (the last `listen` call) or switches to an existing host within the active service.
150
13
  #
151
- # The server will not be initiatet and instead you will be able to use Plezi controllers and the Redis auto-config
152
- # to broadcast Plezi messages to other Plezi processes - allowing for scalable intigration of Plezi into other frameworks.
153
- def self.start_placebo
154
- GReactor.clear_listeners
155
- redis_connection # make sure the redis connection is activated
156
- puts "* Plezi #{Plezi::VERSION} Services will start with no Server...\n"
157
- start_async
14
+ # accepts:
15
+ # host_name: a String with the full host name (i.e. "www.google.com" / "mail.google.com")
16
+ # params:: any of the parameters accepted by the `listen` command, except `protocol`, `handler`, and `ssl` parameters.
17
+ def host(host_name = false, params = {})
18
+ Plezi.host host_name, params
158
19
  end
159
- end
160
20
 
161
- Encoding.default_internal = 'utf-8'
162
- Encoding.default_external = 'utf-8'
163
-
164
- # PL is a shortcut for the Plezi module, so that `PL == Plezi`.
165
- PL = Plezi
166
-
167
- # shortcut for Plezi::DSL.listen.
168
- #
169
- def listen(params = {})
170
- Plezi::Base::DSL.listen params
171
- end
172
-
173
- # adds a virtul host to the current service (the last `listen` call) or switches to an existing host within the active service.
174
- #
175
- # accepts:
176
- # host_name: a String with the full host name (i.e. "www.google.com" / "mail.google.com")
177
- # params:: any of the parameters accepted by the `listen` command, except `protocol`, `handler`, and `ssl` parameters.
178
- def host(host_name = false, params = {})
179
- Plezi::Base::DSL.host host_name, params
180
- end
21
+ # adds a route to the last server object
22
+ #
23
+ # path:: the path for the route
24
+ # controller:: The controller class which will accept the route.
25
+ #
26
+ # `path` parameters has a few options:
27
+ #
28
+ # * `path` can be a Regexp object, forcing the all the logic into controller (typically using the before method).
29
+ #
30
+ # * simple String paths are assumed to be basic RESTful paths:
31
+ #
32
+ # route "/users", Controller => route "/users/(:id)", Controller
33
+ #
34
+ # * routes can define their own parameters, for their own logic:
35
+ #
36
+ # route "/path/:required_paramater/:required_paramater{with_format}/(:optional_paramater)/(:optional){with_format}"
37
+ #
38
+ # * routes can define optional or required routes with regular expressions in them:
39
+ #
40
+ # route "(:locale){en|ru}/path"
41
+ #
42
+ # * routes which use the special '/' charecter within a parameter's format, must escape this charecter using the '\' charecter. **Notice the single quotes** in the following example:
43
+ #
44
+ # route '(:math){[\d\+\-\*\^\%\.\/]}'
45
+ #
46
+ # * or, with double quotes:
47
+ #
48
+ # route "(:math){[\\d\\+\\-\\*\\^\\%\\.\\/]}"
49
+ #
50
+ # magic routes make for difficult debugging - the smarter the routes, the more difficult the debugging.
51
+ # use with care and avoid complex routes when possible. RESTful routes are recommended when possible.
52
+ # json serving apps are advised to use required parameters, empty sections indicating missing required parameters (i.e. /path///foo/bar///).
53
+ #
54
+ def route(path, controller = nil, &block)
55
+ Plezi.route(path, controller, &block)
56
+ end
181
57
 
182
- # adds a route to the last server object
183
- #
184
- # path:: the path for the route
185
- # controller:: The controller class which will accept the route.
186
- #
187
- # `path` parameters has a few options:
188
- #
189
- # * `path` can be a Regexp object, forcing the all the logic into controller (typically using the before method).
190
- #
191
- # * simple String paths are assumed to be basic RESTful paths:
192
- #
193
- # route "/users", Controller => route "/users/(:id)", Controller
194
- #
195
- # * routes can define their own parameters, for their own logic:
196
- #
197
- # route "/path/:required_paramater/:required_paramater{with_format}/(:optional_paramater)/(:optional){with_format}"
198
- #
199
- # * routes can define optional or required routes with regular expressions in them:
200
- #
201
- # route "(:locale){en|ru}/path"
202
- #
203
- # * routes which use the special '/' charecter within a parameter's format, must escape this charecter using the '\' charecter. **Notice the single quotes** in the following example:
204
- #
205
- # route '(:math){[\d\+\-\*\^\%\.\/]}'
206
- #
207
- # * or, with double quotes:
208
- #
209
- # route "(:math){[\\d\\+\\-\\*\\^\\%\\.\\/]}"
210
- #
211
- # magic routes make for difficult debugging - the smarter the routes, the more difficult the debugging.
212
- # use with care and avoid complex routes when possible. RESTful routes are recommended when possible.
213
- # json serving apps are advised to use required parameters, empty sections indicating missing required parameters (i.e. /path///foo/bar///).
214
- #
215
- def route(path, controller = nil, &block)
216
- Plezi::Base::DSL.route(path, controller, &block)
217
- end
58
+ # adds a route to the all the existing servers and hosts.
59
+ #
60
+ # accepts same options as route.
61
+ def shared_route(path, controller = nil, &block)
62
+ Plezi.shared_route(path, controller, &block)
63
+ end
218
64
 
219
- # adds a route to the all the existing servers and hosts.
220
- #
221
- # accepts same options as route.
222
- def shared_route(path, controller = nil, &block)
223
- Plezi::Base::DSL.shared_route(path, controller, &block)
224
- end
65
+ # defines a method with a special name, such as "humens.txt".
66
+ #
67
+ # this could be used in controller classes, to define special routes which might defy
68
+ # normal Ruby naming conventions, such as "/welcome-home", "/play!", etc'
69
+ #
70
+ # could also be used to define methods with special formatting, such as "humans.txt",
71
+ # until a more refined way to deal with formatting will be implemented.
72
+ def def_special_method name, obj=self, &block
73
+ obj.instance_exec { define_method name.to_s.to_sym, &block }
74
+ end
225
75
 
226
- # defines a method with a special name, such as "humens.txt".
227
- #
228
- # this could be used in controller classes, to define special routes which might defy
229
- # normal Ruby naming conventions, such as "/welcome-home", "/play!", etc'
230
- #
231
- # could also be used to define methods with special formatting, such as "humans.txt",
232
- # until a more refined way to deal with formatting will be implemented.
233
- def def_special_method name, obj=self, &block
234
- obj.instance_exec { define_method name.to_s.to_sym, &block }
235
- end
236
76
 
237
77
 
78
+ # finishes setup of the servers and starts them up. This will hange the proceess.
79
+ #
80
+ # this method is called automatically by the Plezi framework.
81
+ #
82
+ # it is recommended that you DO NOT CALL this method.
83
+ # if any post shut-down actions need to be performed, use Plezi.on_shutdown instead.
84
+ def start_services
85
+ return 0 if defined?(NO_PLEZI_AUTO_START)
86
+ undef listen
87
+ undef host
88
+ undef route
89
+ undef shared_route
90
+ Plezi.start
91
+ end
238
92
 
239
- # finishes setup of the servers and starts them up. This will hange the proceess.
240
- #
241
- # this method is called automatically by the Plezi framework.
242
- #
243
- # it is recommended that you DO NOT CALL this method.
244
- # if any post shut-down actions need to be performed, use Plezi.on_shutdown instead.
245
- def start_services
246
- return 0 if defined?(NO_PLEZI_AUTO_START)
247
- undef listen
248
- undef host
249
- undef route
250
- undef shared_route
251
- Plezi.start
252
- end
93
+ # sets information to be used when restarting
94
+ $PL_SCRIPT = $0
95
+ $PL_ARGV = $*.dup
96
+ # restarts the Plezi app with the same arguments as when it was started.
97
+ #
98
+ # EXPERIMENTAL
99
+ def restart_plezi_app
100
+ exec "/usr/bin/env ruby #{$PL_SCRIPT} #{$PL_ARGV.join ' '}"
101
+ end
253
102
 
254
- # restarts the Plezi app with the same arguments as when it was started.
255
- #
256
- # EXPERIMENTAL
257
- def restart_plezi_app
258
- exec "/usr/bin/env ruby #{$PL_SCRIPT} #{$PL_ARGV.join ' '}"
103
+ # sets to start the services once dsl script is finished loading.
104
+ at_exit { start_services }
105
+ GReactor::Settings.force_graceful = false
259
106
  end
260
-
261
- # sets to start the services once dsl script is finished loading.
262
- at_exit { start_services }
263
- GReactor::Settings.force_graceful = false
264
-
265
- # sets information to be used when restarting
266
- $PL_SCRIPT = $0
267
- $PL_ARGV = $*.dup
268
- # $0="Plezi (Ruby)"
@@ -78,7 +78,7 @@ module Plezi
78
78
  # return if a route answered the request
79
79
  host.routes.each {|r| a = r.on_request(request, response); return a if a}
80
80
  #return error code or 404 not found
81
- Base::HTTPSender.send_by_code request, response, 404
81
+ return Base::HTTPSender.send_by_code request, response, 404 unless request[:io].params[:http_handler] == ::GRHttp::Base::Rack
82
82
  rescue => e
83
83
  # return 500 internal server error.
84
84
  GReactor.error e
@@ -10,6 +10,25 @@ module Plezi
10
10
  #
11
11
  # (key type agnostic search Hash proc)
12
12
  HASH_SYM_PROC = Proc.new {|h,k| k = (Symbol === k ? k.to_s : k.to_s.to_sym); h[k] if h.has_key?(k) }
13
+
14
+ # tweeks a hash object to read both :symbols and strings (similar to Rails but without).
15
+ def make_hash_accept_symbols hash
16
+ @magic_hash_proc ||= Proc.new do |hs,k|
17
+ if k.is_a?(Symbol) && hs.has_key?( k.to_s)
18
+ hs[k.to_s]
19
+ elsif k.is_a?(String) && hs.has_key?( k.to_sym)
20
+ hs[k.to_sym]
21
+ elsif k.is_a?(Numeric) && hs.has_key?(k.to_s.to_sym)
22
+ hs[k.to_s.to_sym]
23
+ end
24
+ end
25
+ hash.default_proc = @magic_hash_proc
26
+ hash.values.each do |v|
27
+ if v.is_a?(Hash)
28
+ make_hash_accept_symbols v
29
+ end
30
+ end
31
+ end
13
32
  end
14
33
  end
15
34
 
@@ -1,3 +1,3 @@
1
1
  module Plezi
2
- VERSION = "0.10.11"
2
+ VERSION = "0.10.12"
3
3
  end
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_dependency "grhttp", "~> 0.0.14"
21
+ spec.add_dependency "grhttp", "~> 0.0.15"
22
22
  spec.add_development_dependency "bundler", "~> 1.7"
23
23
  spec.add_development_dependency "rake", "~> 10.0"
24
24
 
@@ -23,6 +23,11 @@
23
23
  ## Coffee Script makes Javascript more fun to code.
24
24
  # gem "coffee-script"
25
25
 
26
+ ## Markdown
27
+ # gem 'redcarpet'
28
+ ## syntax highlighting
29
+ # gem 'rouge'
30
+
26
31
  ####################
27
32
  # Internationalization
28
33
 
@@ -1,16 +1,19 @@
1
1
  # encoding: UTF-8
2
2
 
3
3
  ## Set working directory, load gems and create logs
4
- # Using pathname extentions for setting public folder
4
+ ## Using pathname extentions for setting public folder
5
5
  require 'pathname'
6
- #set up root object, it might be used by the environment and\or the plezi extension gems.
6
+ ## Set up root object, it might be used by the environment and\or the plezi extension gems.
7
7
  Root ||= Pathname.new(File.dirname(__FILE__)).expand_path
8
- # make sure all file access and file loading is relative to the application's root folder
9
- Dir.chdir Root.to_s
10
- # using bundler to load gems (including the plezi gem)
8
+ ## make sure all file access and file loading is relative to the application's root folder
9
+ # Dir.chdir Root.to_s
10
+
11
+ ## Commet the following in order to use use your original app's Gemfile.
12
+ ## If this app is independant, use bundler to load gems (including the plezi gem).
11
13
  require 'bundler'
12
14
  Bundler.require(:default, ENV['ENV'].to_s.to_sym)
13
- ## uncomment to create a log file
15
+
16
+ ## Uncomment to create a log file
14
17
  # GReactor.create_logger File.expand_path(Root.join('server.log').to_s)
15
18
 
16
19
  ## Options for Scaling the app (across processes or machines):
@@ -0,0 +1,11 @@
1
+ # encoding: UTF-8
2
+
3
+ if defined?(Slim)
4
+ require 'rouge/plugins/redcarpet' if defined?(Redcarpet) && defined?(Rouge)
5
+ if defined?(Redcarpet::Render::HTML) && defined?(Rouge::Plugins::Redcarpet)
6
+ Slim::Embedded.options[:markdown] = {
7
+ fenced_code_blocks: true,
8
+ renderer: (Class.new(Redcarpet::Render::HTML) {include Rouge::Plugins::Redcarpet} ).new
9
+ }
10
+ end
11
+ end
@@ -1,22 +1,43 @@
1
+ // Add this file to your html to add websocket support
2
+
1
3
  // Your websocket URI should be an absolute path. The following sets the base URI.
2
- var ws_uri = 'ws://' + window.location.hostname + (window.location.port == '' ? '' : (':' + window.location.port) );
3
- // remember to add the specific controller's path to your websocket URI.
4
- ws_uri += "/";
4
+ // remember to update to the specific controller's path to your websocket URI.
5
+ var ws_controller_path = window.location.pathname; // change to '/controller/path'
6
+ var ws_uri = (window.location.protocol.match(/https/) ? 'wss' : 'ws') + '://' + window.location.hostname + (window.location.port == '' ? '' : (':' + window.location.port) ) + ws_controller_path
5
7
  // websocket variable.
6
8
  var websocket = NaN
9
+ // count failed attempts
10
+ var websocket_fail_count = 0
11
+ // to limit failed reconnection attempts, set this to a number.
12
+ var websocket_fail_limit = NaN
13
+
7
14
 
8
15
  function init_websocket()
9
16
  {
10
17
  websocket = new WebSocket(ws_uri);
11
18
  websocket.onopen = function(e) {
19
+ // reset the count.
20
+ websocket_fail_count = 0
12
21
  // what do you want to do now?
13
22
  };
14
23
 
15
24
  websocket.onclose = function(e) {
25
+ // If the websocket repeatedly you probably want to reopen the websocket if it closes
26
+ if(!isNaN(websocket_fail_limit) && websocket_fail_count >= websocket_fail_limit) {
27
+ // What to do if we can't reconnect so many times?
28
+ return
29
+ };
16
30
  // you probably want to reopen the websocket if it closes.
17
- init_websocket()
31
+ if(isNaN(websocket_fail_limit) || (websocket_fail_count <= websocket_fail_limit) ) {
32
+ // update the count
33
+ websocket_fail_count += 1;
34
+ // try to reconect
35
+ init_websocket();
36
+ };
18
37
  };
19
38
  websocket.onerror = function(e) {
39
+ // update the count.
40
+ websocket_fail_limit += 1
20
41
  // what do you want to do now?
21
42
  };
22
43
  websocket.onmessage = function(e) {
@@ -26,4 +47,5 @@ function init_websocket()
26
47
  // msg = JSON.parse(e.data); // remember to use JSON also in your Plezi controller.
27
48
  };
28
49
  }
50
+ // setup the websocket connection once the page is done loading
29
51
  window.addEventListener("load", init_websocket, false);
@@ -175,7 +175,7 @@ input[type=submit]:active
175
175
  </style>
176
176
  <script type="text/javascript">
177
177
  // Your websocket URI should be an absolute path. The following sets the base URI.
178
- var ws_uri = (window.location.protocol.match(/https/) ? 'wss' : 'ws') + '://' + window.location.hostname + (window.location.port == '' ? '' : (':' + window.location.port) );
178
+ var ws_uri = (window.location.protocol.match(/https/) ? 'wss' : 'ws') + '://' + window.location.hostname + (window.location.port == '' ? '' : (':' + window.location.port) ) + window.location.pathname;
179
179
  // remember to add the specific controller's path to your websocket URI.
180
180
  ws_uri += "/";
181
181
  // websocket variable.
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ Dir.chdir '/Users/2Be/Ruby/plezi/plezi/'
5
+
6
+ require 'benchmark'
7
+ require "bundler/setup"
8
+ require "plezi"
9
+
10
+ # You can add fixtures and/or initialization code here to make experimenting
11
+ # with your gem easier. You can also use a different console, if you like.
12
+
13
+ # (If you use this, don't forget to add pry to your Gemfile!)
14
+ # require "pry"
15
+ # Pry.start
16
+
17
+ require "irb"
18
+ IRB.start
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: plezi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.11
4
+ version: 0.10.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Boaz Segev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-07-22 00:00:00.000000000 Z
11
+ date: 2015-07-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: grhttp
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.0.14
19
+ version: 0.0.15
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.0.14
26
+ version: 0.0.15
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -69,6 +69,7 @@ files:
69
69
  - Rakefile
70
70
  - bin/plezi
71
71
  - lib/plezi.rb
72
+ - lib/plezi/common/api.rb
72
73
  - lib/plezi/common/cache.rb
73
74
  - lib/plezi/common/defer.rb
74
75
  - lib/plezi/common/dsl.rb
@@ -114,8 +115,10 @@ files:
114
115
  - resources/rakefile
115
116
  - resources/redis_config.rb
116
117
  - resources/routes.rb
118
+ - resources/slim_config.rb
117
119
  - resources/websockets.js
118
120
  - resources/welcome_page.html
121
+ - test/console
119
122
  - test/plezi_tests.rb
120
123
  - websocket chatroom.md
121
124
  homepage: http://boazsegev.github.io/plezi/
@@ -145,4 +148,5 @@ specification_version: 4
145
148
  summary: Plezi is the native Ruby Framework for real time web-apps. An easy way to
146
149
  write Websockets, RESTful routing and HTTP streaming apps.
147
150
  test_files:
151
+ - test/console
148
152
  - test/plezi_tests.rb