plezi 0.9.2 → 0.10.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +30 -0
- data/README.md +44 -31
- data/bin/plezi +3 -3
- data/lib/plezi.rb +21 -43
- data/lib/plezi/common/defer.rb +21 -0
- data/lib/plezi/common/dsl.rb +115 -91
- data/lib/plezi/common/redis.rb +44 -0
- data/lib/plezi/common/settings.rb +58 -0
- data/lib/plezi/handlers/controller_core.rb +132 -0
- data/lib/plezi/handlers/controller_magic.rb +85 -259
- data/lib/plezi/handlers/http_router.rb +139 -60
- data/lib/plezi/handlers/route.rb +9 -178
- data/lib/plezi/handlers/stubs.rb +2 -2
- data/lib/plezi/helpers/http_sender.rb +72 -0
- data/lib/plezi/helpers/magic_helpers.rb +12 -0
- data/lib/plezi/{server → helpers}/mime_types.rb +0 -0
- data/lib/plezi/version.rb +1 -1
- data/plezi.gemspec +3 -11
- data/resources/Gemfile +20 -21
- data/resources/controller.rb +2 -2
- data/resources/oauth_config.rb +1 -1
- data/resources/redis_config.rb +2 -0
- data/test/plezi_tests.rb +39 -46
- metadata +24 -33
- data/lib/plezi/common/logging.rb +0 -60
- data/lib/plezi/eventmachine/connection.rb +0 -190
- data/lib/plezi/eventmachine/em.rb +0 -98
- data/lib/plezi/eventmachine/io.rb +0 -272
- data/lib/plezi/eventmachine/protocol.rb +0 -54
- data/lib/plezi/eventmachine/queue.rb +0 -51
- data/lib/plezi/eventmachine/ssl_connection.rb +0 -144
- data/lib/plezi/eventmachine/timers.rb +0 -117
- data/lib/plezi/eventmachine/workers.rb +0 -33
- data/lib/plezi/handlers/http_echo.rb +0 -27
- data/lib/plezi/handlers/http_host.rb +0 -214
- data/lib/plezi/handlers/magic_helpers.rb +0 -32
- data/lib/plezi/server/http.rb +0 -129
- data/lib/plezi/server/http_protocol.rb +0 -319
- data/lib/plezi/server/http_request.rb +0 -146
- data/lib/plezi/server/http_response.rb +0 -319
- data/lib/plezi/server/websocket.rb +0 -251
- data/lib/plezi/server/websocket_client.rb +0 -178
- data/lib/plezi/server/ws_response.rb +0 -161
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0a5c7776c37ebc623189d2a99863f6571fbef572
|
4
|
+
data.tar.gz: 82f7af02e2db159f56d3bd8ee4ce4a2cc4553aca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: efa0d7353a2e2e4e07a9c52867397731afe670e9fb51a69ba2e7b3b6f07d2ea54985a1037f50b620b06f47768f53285afb7e10023566da60eaa114f8034b64a4
|
7
|
+
data.tar.gz: 52fd0e21072250e92837cc85cc236c2054c664c3a86e9517c96b796baca9bb26fb7ff9a243172b28a2f477b1cc6c5b6ae51faa6f3c62311bc2f67c45852febb7
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,36 @@
|
|
2
2
|
|
3
3
|
***
|
4
4
|
|
5
|
+
Change log v.0.10.1
|
6
|
+
|
7
|
+
**fix**: fixed an issue where the new Controller's inner router might route to RESTful methods that weren't defined (:show, :save, etc').
|
8
|
+
|
9
|
+
**fix**: fixed an issue with the new Controller's inner router might not reset it's cache when methods are added to the controller after the service has begun.
|
10
|
+
|
11
|
+
***
|
12
|
+
|
13
|
+
Change log v.0.10.0
|
14
|
+
|
15
|
+
**Major Revesion**:
|
16
|
+
|
17
|
+
- The Plezi IO Reactor was extracted to an external gem called [GReactor](https://github.com/boazsegev/GReactor) and optimized.
|
18
|
+
- The Plezi HTTP and Websocket Server was extracted to an external gem called [GRHttp](https://github.com/boazsegev/GRHttp) and optimized.
|
19
|
+
- The Websocket API, implementation and engine were all revised. CAREFUL: **Old Websocket API deprecated**.
|
20
|
+
|
21
|
+
**WebSocket API revisions**:
|
22
|
+
|
23
|
+
- The `#on_connect` callback had been renamed to `#on_open`, for clarity and to conform with the Javascript API.
|
24
|
+
- The `#on_disconnect` callback had been renamed to `#on_close`, for clarity and to conform with the Javascript API.
|
25
|
+
- The `#collect` method had been deprecated due to scaling limitations it had imposed.
|
26
|
+
- The `#broadcast` and `Controller.broadcast` methods had been altered and would no longer accept an optional block of code.
|
27
|
+
- The Redis support had been altered and the redis connection object (if exists) is now available using `Plezi.redis_connection` instead of the older Controller method.
|
28
|
+
|
29
|
+
**Settings API revisions**:
|
30
|
+
|
31
|
+
- The settings API had been moved to the namespace `Plezi::Settings`.
|
32
|
+
|
33
|
+
***
|
34
|
+
|
5
35
|
Change log v.0.9.2
|
6
36
|
|
7
37
|
**Some API deprecation notice**
|
data/README.md
CHANGED
@@ -1,20 +1,18 @@
|
|
1
1
|
# Plezi, The Rack Free Ruby framework for realtime web-apps
|
2
2
|
[![Gem Version](https://badge.fury.io/rb/plezi.svg)](http://badge.fury.io/rb/plezi)
|
3
|
-
[![Inline docs](http://inch-ci.org/github/boazsegev/plezi.svg?branch=master)](http://
|
3
|
+
[![Inline docs](http://inch-ci.org/github/boazsegev/plezi.svg?branch=master)](http://www.rubydoc.info/gems/plezi/)
|
4
4
|
|
5
5
|
> People who are serious about their frameworks, should write their own servers...
|
6
6
|
|
7
|
-
Find more info on [Plezi's framework
|
7
|
+
Find more info on [Plezi's framework documentation](http://www.rubydoc.info/gems/plezi/)
|
8
8
|
|
9
|
-
## About the Plezi framework
|
9
|
+
## About the Plezi framework
|
10
10
|
|
11
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
12
|
|
13
13
|
Plezi works as an asynchronous multi-threaded Ruby 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.
|
14
14
|
|
15
|
-
Plezi
|
16
|
-
|
17
|
-
You can follow our [tutorial to write your first Plezi Chatroom](http://boazsegev.github.io/plezi/websockets.html) - but it's better to start with this readme and explore the WebSockets example given here.
|
15
|
+
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).
|
18
16
|
|
19
17
|
## Installation
|
20
18
|
|
@@ -23,6 +21,7 @@ Add this line to your application's Gemfile:
|
|
23
21
|
```ruby
|
24
22
|
gem 'plezi'
|
25
23
|
```
|
24
|
+
|
26
25
|
Or install it yourself as:
|
27
26
|
|
28
27
|
$ gem install plezi
|
@@ -33,7 +32,9 @@ to create a new barebones app using the Plezi framework, run from terminal:
|
|
33
32
|
|
34
33
|
$ plezi new appname
|
35
34
|
|
36
|
-
That's it, now you have a ready to use basic web server (with some demo code
|
35
|
+
That's it, now you have a ready to use basic web server (with some demo code, such as a websocket chatroom).
|
36
|
+
|
37
|
+
If you're on MacOS or linux you can simply double click the `appname` script file in the `appname` folder. Or, from the terminal, you can type:
|
37
38
|
|
38
39
|
$ cd appname
|
39
40
|
$ ./appname # ( or: plezi s )
|
@@ -44,11 +45,11 @@ the default first port for the app is 3000. you can set the first port to listen
|
|
44
45
|
|
45
46
|
$ ./appname -p 80
|
46
47
|
|
47
|
-
you now have a smart framework app that will happily
|
48
|
+
you now have a smart framework app that will happily assimilate any gem you feed it. it responds extra well to Haml, Sass and Coffee-Script, which you can enable in it's Gemfile.
|
48
49
|
|
49
50
|
## Barebones Web Service
|
50
51
|
|
51
|
-
|
52
|
+
This example is basic, useless, but required for every doc out there...
|
52
53
|
|
53
54
|
"Hello World!" in 3 lines - try it in irb (exit irb to start server):
|
54
55
|
|
@@ -56,11 +57,11 @@ this example is basic, useless, but required for every doc out there...
|
|
56
57
|
listen
|
57
58
|
route(/.?/) { |req, res| res << "Hello World!" }
|
58
59
|
|
59
|
-
After you
|
60
|
+
After you exit irb, the Plezi server will start up. Go to http://localhost:3000/ and see it run :)
|
60
61
|
|
61
62
|
## Plezi Controller classes
|
62
63
|
|
63
|
-
One of the best things about the Plezi is it's ability to take in any class as a controller class and route to the classes methods with special support for RESTful methods (`index`, `show`, `new`, `save`, `update`, `delete`, `before` and `after`) and for WebSockets (`pre_connect`, `
|
64
|
+
One of the best things about the Plezi is it's ability to take in any class as a controller class and route to the classes methods with special support for RESTful methods (`index`, `show`, `new`, `save`, `update`, `delete`, `before` and `after`) and for WebSockets (`pre_connect`, `on_open`, `on_message(data)`, `on_close`, `broadcast`, `unicast`, `on_broadcast(data)`):
|
64
65
|
|
65
66
|
require 'plezi'
|
66
67
|
|
@@ -77,11 +78,11 @@ Except for WebSockets, returning a String will automatically add the string to t
|
|
77
78
|
|
78
79
|
Controllers can even be nested (order matters) or have advanced uses that are definitly worth exploring.
|
79
80
|
|
80
|
-
|
81
|
+
\* please read the demo code for Plezi::StubRESTCtrl and Plezi::StubWSCtrl to learn more. Also, read more about the [GRHttp server](GRHttp websocket and HTTP server) at the core of Plezi to get more information about the amazing [HTTPRequest](http://www.rubydoc.info/gems/grhttp/0.0.6/GRHttp/HTTPRequest) and [HTTPResponse](http://www.rubydoc.info/gems/grhttp/GRHttp/HTTPResponse) objects.
|
81
82
|
|
82
83
|
## Native Websocket and Redis support
|
83
84
|
|
84
|
-
Plezi Controllers have access to native websocket support through the `pre_connect`, `
|
85
|
+
Plezi Controllers have access to native websocket support through the `pre_connect`, `on_open`, `on_message(data)`, `on_close`, `broadcast` and `unicast` methods.
|
85
86
|
|
86
87
|
Here is some demo code for a simple Websocket broadcasting server, where messages sent to the server will be broadcasted back to all the **other** active connections (the connection sending the message will not recieve the broadcast).
|
87
88
|
|
@@ -128,15 +129,18 @@ method names starting with an underscore ('_') will NOT be made public by the ro
|
|
128
129
|
|
129
130
|
Plezi comes with native HTTP streaming support, alowing you to use Plezi Events and Timers to send an Asynchronous response.
|
130
131
|
|
131
|
-
Let's make the classic 'Hello World' use HTTP Streaming
|
132
|
+
Let's make the classic 'Hello World' use HTTP Streaming:
|
132
133
|
|
133
134
|
```ruby
|
134
135
|
require 'plezi'
|
135
136
|
|
136
137
|
class Controller
|
137
138
|
def index
|
138
|
-
response.
|
139
|
-
|
139
|
+
response.stream_async do
|
140
|
+
sleep 0.5
|
141
|
+
response << "Hello ";
|
142
|
+
response.stream_async{ sleep 0.5; response << "World" }
|
143
|
+
end
|
140
144
|
true
|
141
145
|
end
|
142
146
|
end
|
@@ -145,7 +149,9 @@ Let's make the classic 'Hello World' use HTTP Streaming and Asynchronous Plezi E
|
|
145
149
|
route '*' , Controller
|
146
150
|
```
|
147
151
|
|
148
|
-
Notice
|
152
|
+
Notice you can nest calls to the `response.stream_async` method, allowing you to breakdown big blocking tasks into smaller chunks. `response.stream_async` will return immediately, scheduling the task for background processing.
|
153
|
+
|
154
|
+
You can also handle other tasks asynchronously using the [GReactor API](http://www.rubydoc.info/gems/greactor)'s.
|
149
155
|
|
150
156
|
More on asynchronous events and timers later.
|
151
157
|
|
@@ -153,7 +159,7 @@ More on asynchronous events and timers later.
|
|
153
159
|
|
154
160
|
Plezi supports magic routes, in similar formats found in other systems, such as: `route "/:required/(:optional_with_format){[\\d]*}/(:optional)", Plezi::StubRESTCtrl`.
|
155
161
|
|
156
|
-
Plezi assummes all simple
|
162
|
+
Plezi assummes all simple routes to be RESTful routes with the parameter `:id` ( `"/user" == "/user/(:id)"` ).
|
157
163
|
|
158
164
|
require 'plezi'
|
159
165
|
listen
|
@@ -172,7 +178,7 @@ now visit:
|
|
172
178
|
|
173
179
|
## Plezi Virtual Hosts
|
174
180
|
|
175
|
-
Plezi can be used to create virtual hosts for the same service:
|
181
|
+
Plezi can be used to create virtual hosts for the same service, allowing you to handle different domains and subdomains with one app:
|
176
182
|
|
177
183
|
require 'plezi'
|
178
184
|
listen
|
@@ -203,7 +209,7 @@ Now visit:
|
|
203
209
|
|
204
210
|
## Plezi Logging
|
205
211
|
|
206
|
-
The Plezi module (also `PL`)
|
212
|
+
The Plezi module (also `PL`) delegates to the GReactor methods, helping with logging as well as the support you already noticed for dynamic routes, dynamic services and more.
|
207
213
|
|
208
214
|
Logging:
|
209
215
|
|
@@ -211,6 +217,7 @@ Logging:
|
|
211
217
|
|
212
218
|
# simple logging of strings
|
213
219
|
PL.info 'log info'
|
220
|
+
GReactor.info 'This is the same, but more direct.'
|
214
221
|
PL.warn 'log warning'
|
215
222
|
PL.error 'log error'
|
216
223
|
PL.fatal "log a fatal error (shuoldn't be needed)."
|
@@ -223,9 +230,11 @@ Logging:
|
|
223
230
|
PL.error e
|
224
231
|
end
|
225
232
|
|
233
|
+
Please notice it is faster to use the GReactor API directly when using API that is delegated to GReactor.
|
234
|
+
|
226
235
|
## Plezi Events and Timers
|
227
236
|
|
228
|
-
The Plezi module (also `PL`) also
|
237
|
+
The Plezi module (also `PL`) also delegates to the [GReactor's API](http://www.rubydoc.info/gems/greactor/GReactor) to help with asynchronous tasking, callbacks, timers and customized shutdown cleanup.
|
229
238
|
|
230
239
|
Asynchronous callbacks (works only while services are active and running):
|
231
240
|
|
@@ -236,14 +245,17 @@ Asynchronous callbacks (works only while services are active and running):
|
|
236
245
|
end
|
237
246
|
|
238
247
|
# shutdown callbacks
|
239
|
-
|
240
|
-
|
248
|
+
GReactor.on_shutdown(Kernel, :my_shutdown_proc, Time.now) { puts "this will run after shutdown." }
|
249
|
+
GReactor.on_shutdown() { puts "this will run too." }
|
241
250
|
|
242
251
|
# a timer
|
243
|
-
|
252
|
+
GReactor.run_after 2, -> {puts "this will wait 2 seconds to run... too late. for this example"}
|
244
253
|
|
245
254
|
# an asynchronous method call with an optional callback block
|
246
|
-
|
255
|
+
GReactor.callback(Kernel, :puts, "Plezi will start eating our code once we exit terminal.") {puts 'first output finished'}
|
256
|
+
|
257
|
+
GReactor.run_async {puts "notice that the background tasks will only start once the Plezi's engine is running."}
|
258
|
+
GReactor.run_async {puts "exit Plezi to observe the shutdown callbacks."}
|
247
259
|
|
248
260
|
## Re-write Routes
|
249
261
|
|
@@ -313,12 +325,6 @@ As you can see in the example above, Plezi supports Proc routes as well as Class
|
|
313
325
|
|
314
326
|
Please notice that there are some differences between the two. Proc routes less friedly, but plenty powerful and are great for custom 404 error handling.
|
315
327
|
|
316
|
-
## Plezi Settings
|
317
|
-
|
318
|
-
Plezi is ment to be very flexible. please take a look at the Plezi Module for settings you might want to play with (max_threads, idle_sleep, create_logger) or any monkey patching you might enjoy.
|
319
|
-
|
320
|
-
Feel free to fork or contribute. right now I am one person, but together we can make something exciting that will help us enjoy Ruby in this brave new world and (hopefully) set an example that will induce progress in the popular mainstream frameworks such as Rails and Sinatra.
|
321
|
-
|
322
328
|
## OAuth2 and other Helpers
|
323
329
|
|
324
330
|
Plezi has a few helpers that help with common tasks.
|
@@ -366,6 +372,13 @@ Plezi has a some more goodies under the hood.
|
|
366
372
|
|
367
373
|
Whether such goodies are part of the Plezi-App Template (such as rake tasks for ActiveRecord without Rails) or part of the Plezi Framework core (such as descried in the Plezi::ControllerMagic documentation: #flash, #url_for, #render, #send_data, etc'), these goodies are fun to work with and make completion of common tasks a breeze.
|
368
374
|
|
375
|
+
|
376
|
+
## Plezi Settings
|
377
|
+
|
378
|
+
Plezi is meant to be very flexible. please take a look at the Plezi Module for settings you might want to play with (max_threads, idle_sleep, create_logger) or any monkey patching you might enjoy.
|
379
|
+
|
380
|
+
Feel free to fork or contribute. right now I am one person, but together we can make something exciting that will help us enjoy Ruby in this brave new world and (hopefully) set an example that will induce progress in the popular mainstream frameworks such as Rails and Sinatra.
|
381
|
+
|
369
382
|
## Contributing
|
370
383
|
|
371
384
|
1. Fork it ( https://github.com/boazsegev/plezi/fork )
|
data/bin/plezi
CHANGED
@@ -76,9 +76,9 @@ class AppTemplate
|
|
76
76
|
# set up config files
|
77
77
|
app_tree["config"] ||= {}
|
78
78
|
app_tree["config"]["oauth.rb"] ||= IO.read(::File.expand_path(File.join("..", "..", "resources" ,"oauth_config.rb"), __FILE__))
|
79
|
-
app_tree["config"]["
|
80
|
-
app_tree["config"]["
|
81
|
-
app_tree["config"]["
|
79
|
+
app_tree["config"]["active_record.rb"] ||= IO.read(::File.expand_path(File.join("..", "..", "resources" ,"db_ac_config.rb"), __FILE__))
|
80
|
+
app_tree["config"]["sequel.rb"] ||= IO.read(::File.expand_path(File.join("..", "..", "resources" ,"db_sequel_config.rb"), __FILE__))
|
81
|
+
app_tree["config"]["datamapper.rb"] ||= IO.read(::File.expand_path(File.join("..", "..", "resources" ,"db_dm_config.rb"), __FILE__))
|
82
82
|
app_tree["config"]["haml.rb"] ||= IO.read(::File.expand_path(File.join("..", "..", "resources" ,"haml_config.rb"), __FILE__))
|
83
83
|
app_tree["config"]["i18n.rb"] ||= IO.read(::File.expand_path(File.join("..", "..", "resources" ,"i18n_config.rb"), __FILE__))
|
84
84
|
app_tree["config"]["redis.rb"] ||= (IO.read(::File.expand_path(File.join("..", "..", "resources" ,"redis_config.rb"), __FILE__))).gsub('appsecret', "#{ARGV[1]}_#{SecureRandom.hex}")
|
data/lib/plezi.rb
CHANGED
@@ -2,73 +2,51 @@
|
|
2
2
|
|
3
3
|
require 'singleton'
|
4
4
|
require 'pathname'
|
5
|
-
require 'logger'
|
6
|
-
require 'socket'
|
7
|
-
require 'openssl'
|
8
|
-
require 'strscan'
|
9
5
|
require 'base64'
|
10
6
|
require 'digest/sha1'
|
11
7
|
require 'securerandom'
|
12
8
|
require 'time'
|
13
9
|
require 'json'
|
10
|
+
require 'yaml'
|
14
11
|
require 'uri'
|
15
12
|
require 'set'
|
16
13
|
|
14
|
+
# GRHttp servet
|
15
|
+
require 'grhttp'
|
16
|
+
|
17
|
+
|
17
18
|
## erb templating
|
18
19
|
begin
|
19
20
|
require 'erb'
|
20
|
-
rescue
|
21
|
-
|
21
|
+
rescue => e
|
22
|
+
|
22
23
|
end
|
23
24
|
|
24
25
|
### version
|
25
26
|
|
26
27
|
require "plezi/version"
|
27
28
|
|
28
|
-
### common
|
29
|
+
### common
|
29
30
|
|
30
|
-
require 'plezi/common/
|
31
|
+
require 'plezi/common/defer.rb'
|
31
32
|
require 'plezi/common/cache.rb'
|
32
33
|
require 'plezi/common/dsl.rb'
|
34
|
+
require 'plezi/common/redis.rb'
|
35
|
+
require 'plezi/common/settings.rb'
|
33
36
|
|
34
|
-
###
|
35
|
-
|
36
|
-
require "plezi/eventmachine/em.rb"
|
37
|
-
|
38
|
-
require 'plezi/eventmachine/queue.rb'
|
39
|
-
require 'plezi/eventmachine/workers.rb'
|
40
|
-
require 'plezi/eventmachine/timers.rb'
|
41
|
-
require 'plezi/eventmachine/io.rb'
|
42
|
-
require 'plezi/eventmachine/protocol.rb'
|
43
|
-
require 'plezi/eventmachine/connection.rb'
|
44
|
-
require 'plezi/eventmachine/ssl_connection.rb'
|
45
|
-
|
46
|
-
### http and websocket server
|
47
|
-
|
48
|
-
|
49
|
-
require 'plezi/server/mime_types.rb'
|
50
|
-
|
51
|
-
require 'plezi/server/http.rb'
|
52
|
-
require 'plezi/server/http_protocol.rb'
|
53
|
-
require 'plezi/server/http_request.rb'
|
54
|
-
require 'plezi/server/http_response.rb'
|
55
|
-
|
56
|
-
require 'plezi/server/websocket.rb'
|
57
|
-
require 'plezi/server/ws_response.rb'
|
58
|
-
|
59
|
-
### websocket client
|
60
|
-
require 'plezi/server/websocket_client.rb'
|
61
|
-
### Handlers / Framework
|
37
|
+
### helpers
|
62
38
|
|
63
|
-
require
|
64
|
-
require
|
65
|
-
require
|
39
|
+
require 'plezi/helpers/http_sender.rb'
|
40
|
+
require 'plezi/helpers/magic_helpers.rb'
|
41
|
+
require 'plezi/helpers/mime_types.rb'
|
66
42
|
|
67
|
-
require "plezi/handlers/controller_magic"
|
68
|
-
require "plezi/handlers/magic_helpers"
|
69
|
-
require "plezi/handlers/route"
|
70
43
|
|
71
|
-
|
44
|
+
### HTTP and WebSocket Handlers
|
45
|
+
require 'plezi/handlers/http_router.rb'
|
46
|
+
require 'plezi/handlers/route.rb'
|
47
|
+
require 'plezi/handlers/controller_magic.rb'
|
48
|
+
require 'plezi/handlers/controller_core.rb'
|
49
|
+
require 'plezi/handlers/stubs.rb'
|
72
50
|
|
73
51
|
|
74
52
|
##############################################################################
|
@@ -0,0 +1,21 @@
|
|
1
|
+
|
2
|
+
module Plezi
|
3
|
+
|
4
|
+
module_function
|
5
|
+
|
6
|
+
# Defers any missing methods to the GReactor Library.
|
7
|
+
def method_missing name, *args, &block
|
8
|
+
return super unless REACTOR_METHODS.include? name
|
9
|
+
::GReactor.send name, *args, &block
|
10
|
+
end
|
11
|
+
# Defers any missing methods to the GReactor Library.
|
12
|
+
def respond_to_missing?(name, include_private = false)
|
13
|
+
REACTOR_METHODS.include?(name) or super
|
14
|
+
end
|
15
|
+
|
16
|
+
protected
|
17
|
+
|
18
|
+
REACTOR_METHODS = ::GReactor.public_methods(false)
|
19
|
+
|
20
|
+
end
|
21
|
+
|
data/lib/plezi/common/dsl.rb
CHANGED
@@ -1,109 +1,129 @@
|
|
1
1
|
|
2
2
|
module Plezi
|
3
3
|
|
4
|
-
# holds methods that are called by the DSL.
|
5
|
-
#
|
6
4
|
# this isn't part of the public API.
|
7
|
-
module
|
8
|
-
module_function
|
5
|
+
module Base
|
9
6
|
|
10
|
-
#
|
7
|
+
# holds methods that are called by the DSL.
|
11
8
|
#
|
12
|
-
#
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
#
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
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
|
+
@servers = {}
|
18
|
+
@active_router = nil
|
19
|
+
|
20
|
+
|
21
|
+
# public API to add a service to the framework.
|
22
|
+
# accepts a Hash object with any of the following options (Hash keys):
|
23
|
+
# port:: port number. defaults to 3000 or the port specified when the script was called.
|
24
|
+
# host:: the host name. defaults to any host not explicitly defined (a catch-all).
|
25
|
+
# alias:: a String or an Array of Strings which represent alternative host names (i.e. `alias: ["admin.google.com", "admin.gmail.com"]`).
|
26
|
+
# root:: the public root folder. if this is defined, static files will be served from the location.
|
27
|
+
# 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).
|
28
|
+
# 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.
|
29
|
+
# 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.
|
30
|
+
# save_assets:: saves the rendered assets to the filesystem, under the public folder. defaults to false.
|
31
|
+
# templates:: the templates root folder. defaults to nil (no template support). templates can be rendered by a Controller class, using the `render` method.
|
32
|
+
# 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.
|
33
|
+
# ssl_key:: the public key for the SSL service.
|
34
|
+
# ssl_cert:: the certificate for the SSL service.
|
35
|
+
#
|
36
|
+
# some further options, which are unstable and might be removed in future versions, are:
|
37
|
+
# protocol:: the protocol objects (usually a class, but any object answering `#call` will do).
|
38
|
+
# handler:: an optional handling object, to be called upon by the protocol (i.e. #on_message, #on_connect, etc'). this option is used to allow easy protocol switching, such as from HTTP to Websockets.
|
39
|
+
#
|
40
|
+
# Duringn normal Plezi behavior, the optional `handler` object will be returned if `listen` is called more than once for the same port.
|
41
|
+
#
|
42
|
+
# assets:
|
43
|
+
#
|
44
|
+
# assets support will render `.sass`, `.scss` and `.coffee` and save them as local files (`.css`, `.css`, and `.js` respectively)
|
45
|
+
# before sending them as static files.
|
46
|
+
#
|
47
|
+
# templates:
|
48
|
+
#
|
49
|
+
# ERB, Slim and Haml are natively supported.
|
50
|
+
#
|
51
|
+
# @returns [Plezi::Router]
|
52
|
+
#
|
53
|
+
def listen parameters = {}
|
54
|
+
# update default values
|
55
|
+
parameters[:index_file] ||= 'index.html'
|
56
|
+
parameters[:assets_public] ||= '/assets'
|
57
|
+
parameters[:assets_public].chomp! '/'
|
58
|
+
|
59
|
+
#keeps information of past ports.
|
60
|
+
@listeners ||= {}
|
61
|
+
@listeners_locker = Mutex.new
|
62
|
+
|
63
|
+
# check if the port is used twice.
|
64
|
+
@listeners_locker.synchronize do
|
65
|
+
if @listeners[parameters[:port]]
|
66
|
+
puts "WARNING: port aleady in use! returning existing service and attemptin to add host (maybe multiple hosts? use `host` instead)."
|
67
|
+
@active_router = @listeners[parameters[:port]].params[:http_handler]
|
68
|
+
@active_router.add_host parameters[:host], parameters if @active_router.is_a?(HTTPRouter)
|
69
|
+
return @active_router
|
51
70
|
end
|
52
71
|
end
|
53
|
-
|
54
|
-
# re-key params
|
55
|
-
# new_params = {}
|
56
|
-
# env[:params].each {|k,v| HTTP.add_param_to_hash k, v, new_params}
|
57
|
-
# env[:params] = new_params
|
72
|
+
@listeners[parameters[:port]] = parameters
|
58
73
|
|
59
|
-
|
60
|
-
|
74
|
+
# make sure the protocol exists.
|
75
|
+
parameters[:upgrade_handler] = parameters[:http_handler] = HTTPRouter.new
|
61
76
|
|
62
|
-
|
63
|
-
|
64
|
-
|
77
|
+
GRHttp.listen parameters
|
78
|
+
# set the active router to the handler or the protocol.
|
79
|
+
@active_router = parameters[:http_handler]
|
80
|
+
@active_router.add_host(parameters[:host], parameters)
|
65
81
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
#
|
70
|
-
|
82
|
+
# return the current handler or the protocol..
|
83
|
+
@active_router
|
84
|
+
end
|
85
|
+
# adds a route to the last server created
|
86
|
+
def route(path, controller = nil, &block)
|
87
|
+
raise "Must define a listener before adding a route - use `Plezi.listen`." unless @active_router
|
88
|
+
@active_router.add_route path, controller, &block
|
89
|
+
end
|
71
90
|
|
72
|
-
return response if response.is_a?(Array)
|
73
91
|
|
74
|
-
|
92
|
+
# adds a shared route to all existing services and hosts.
|
93
|
+
def shared_route(path, controller = nil, &block)
|
94
|
+
raise "Must have created at least one Pleze service before calling `shared_route` - use `Plezi.listen`." unless @listeners
|
95
|
+
@listeners.values.each {|p| p[:http_handler].add_shared_route path, controller, &block }
|
96
|
+
end
|
75
97
|
|
76
|
-
|
77
|
-
|
78
|
-
#
|
79
|
-
#
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
response.cookies.each {|k,v| headers['Set-Cookie'] << ("#{k.to_s}=#{v.to_s}")}
|
98
|
+
# adds a host to the last server created
|
99
|
+
#
|
100
|
+
# accepts the same parameter(s) as the `listen` command (see Plezi.add_service), except :protocol and :handler are ignored:
|
101
|
+
# alias:: a String or an Array of Strings which represent alternative host names (i.e. `alias: ["admin.google.com", "admin.gmail.com"]`).
|
102
|
+
def host(host_name, params)
|
103
|
+
raise "Must define a listener before adding a route - use `Plezi.listen`." unless @active_router
|
104
|
+
@active_router.add_host host_name, params
|
84
105
|
end
|
85
|
-
[response.status, headers, response.body]
|
86
|
-
end
|
87
106
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
hs
|
93
|
-
|
94
|
-
hs
|
95
|
-
|
96
|
-
hs
|
107
|
+
|
108
|
+
# tweeks a hash object to read both :symbols and strings (similar to Rails but without).
|
109
|
+
def make_hash_accept_symbols hash
|
110
|
+
@magic_hash_proc ||= Proc.new do |hs,k|
|
111
|
+
if k.is_a?(Symbol) && hs.has_key?( k.to_s)
|
112
|
+
hs[k.to_s]
|
113
|
+
elsif k.is_a?(String) && hs.has_key?( k.to_sym)
|
114
|
+
hs[k.to_sym]
|
115
|
+
elsif k.is_a?(Numeric) && hs.has_key?(k.to_s.to_sym)
|
116
|
+
hs[k.to_s.to_sym]
|
117
|
+
end
|
97
118
|
end
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
119
|
+
hash.default_proc = @magic_hash_proc
|
120
|
+
hash.values.each do |v|
|
121
|
+
if v.is_a?(Hash)
|
122
|
+
make_hash_accept_symbols v
|
123
|
+
end
|
103
124
|
end
|
104
125
|
end
|
105
126
|
end
|
106
|
-
|
107
127
|
end
|
108
128
|
end
|
109
129
|
|
@@ -116,7 +136,7 @@ PL = Plezi
|
|
116
136
|
# shortcut for Plezi::DSL.listen.
|
117
137
|
#
|
118
138
|
def listen(params = {})
|
119
|
-
Plezi::DSL.listen params
|
139
|
+
Plezi::Base::DSL.listen params
|
120
140
|
end
|
121
141
|
|
122
142
|
# adds a virtul host to the current service (the last `listen` call) or switches to an existing host within the active service.
|
@@ -125,7 +145,7 @@ end
|
|
125
145
|
# host_name: a String with the full host name (i.e. "www.google.com" / "mail.google.com")
|
126
146
|
# params:: any of the parameters accepted by the `listen` command, except `protocol`, `handler`, and `ssl` parameters.
|
127
147
|
def host(host_name = false, params = {})
|
128
|
-
Plezi::DSL.host host_name, params
|
148
|
+
Plezi::Base::DSL.host host_name, params
|
129
149
|
end
|
130
150
|
|
131
151
|
# adds a route to the last server object
|
@@ -162,14 +182,14 @@ end
|
|
162
182
|
# json serving apps are advised to use required parameters, empty sections indicating missing required parameters (i.e. /path///foo/bar///).
|
163
183
|
#
|
164
184
|
def route(path, controller = nil, &block)
|
165
|
-
Plezi::DSL.route(path, controller, &block)
|
185
|
+
Plezi::Base::DSL.route(path, controller, &block)
|
166
186
|
end
|
167
187
|
|
168
188
|
# adds a route to the all the existing servers and hosts.
|
169
189
|
#
|
170
190
|
# accepts same options as route.
|
171
191
|
def shared_route(path, controller = nil, &block)
|
172
|
-
Plezi::DSL.shared_route(path, controller, &block)
|
192
|
+
Plezi::Base::DSL.shared_route(path, controller, &block)
|
173
193
|
end
|
174
194
|
|
175
195
|
# defines a method with a special name, such as "humens.txt".
|
@@ -199,7 +219,11 @@ def start_services
|
|
199
219
|
undef route
|
200
220
|
undef shared_route
|
201
221
|
undef start_services
|
202
|
-
Plezi::
|
222
|
+
puts "Starting Plezi #{Plezi::VERSION} Services using the GRHttp #{GRHttp::VERSION} server."
|
223
|
+
puts "Press ^C to exit."
|
224
|
+
GReactor.on_shutdown { puts "Plezi shutdown. It was fun to serve you." }
|
225
|
+
GReactor.start unless GReactor.running?
|
226
|
+
GReactor.join { puts "\r\nStarting shutdown sequesnce. Press ^C to force quit."}
|
203
227
|
end
|
204
228
|
|
205
229
|
# restarts the Plezi app with the same arguments as when it was started.
|