plezi 0.8.7 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c39d10feca5a72236133883875628f43ae714a86
4
- data.tar.gz: a1accf79bbde62e52e63836158e2e16d32cff059
3
+ metadata.gz: c1b45fb775eeba5ab996d2581da537e38640f7d4
4
+ data.tar.gz: 1060b31518ce6e3ee36cfa315ce916f72e7ab1d2
5
5
  SHA512:
6
- metadata.gz: b94655b0900f4c5c69ac17c81cd3ee83af7c19ce8e459bb523766210b92e9c16c2d56977f4537665c19985dd5a77638bc93505abb85af8a515162d167f378017
7
- data.tar.gz: dcdff9a3dd5ec25ef4c6d6ffb43714b52552df92e49258744841902371ad094dd1232cf0bd951e2a69b0773557d50bd8e29125c9f36016804354878883780f80
6
+ metadata.gz: 030e93b8a30cc04c3ad35c3aae1303e335b5bd1558469e9673cc14e07417c17b43e0a271a4441bee64b53c6785804b2a9460cd391d3402c2cc12e0093fe0a626
7
+ data.tar.gz: d663be79b8da32121b279848fc2cad6b5b66562ccbeedac9de25a41965bfa40380085a1b43af806f4f5e763a5e86eee7314e1f88fda8d5c43a2ba23d01c7fbc3
@@ -2,6 +2,29 @@
2
2
 
3
3
  ***
4
4
 
5
+ Change log v.0.9.0
6
+
7
+ **changes** (might break code):
8
+
9
+ - The error code file handling logic has been changed.
10
+
11
+ Plezi will no longer look the 404 and 505 files in the _public_ `:root` location. Instead the files should be placed at the **templates** folder if defined or at the app's root folder (_if templates folder isn't set_).
12
+
13
+ Also, error code files should now correctly specify that they are html templates - for example, the older '404.erb' should be renamed as '404.html.erb'
14
+
15
+ To update your application **please rename the error code files and move them to the app template's folder** (`appname/app/views`).
16
+
17
+ - Updated the template's welcome page and database configuration support. Existing applications shouldn't be effected.
18
+
19
+
20
+ **feature**: auto-pinging can now be customized for different hosting-server timeouts and it can also be disabled using the `Plezi.ping_interval` setter and getter.
21
+
22
+ **feature**: The Plezi framework can now impose limits on Websocket message sizes (even messages split across a number of frames) by using the `Plezi.ws_message_size_limit=` method.
23
+
24
+ **fix**: Outgoing Websocket messages would break for messages over 32KB (and sometimes over 16KB). This was caused by an issue in the frame splitting algorithm which is now resolved.
25
+
26
+ ***
27
+
5
28
  Change log v.0.8.7
6
29
 
7
30
  **minor performance**: streamlined the ping/pong Websocket process.
data/bin/plezi CHANGED
@@ -46,10 +46,21 @@ class AppTemplate
46
46
  app_tree["app"]["models"] ||= {}
47
47
  app_tree["app"]["views"] ||= {}
48
48
 
49
+ # set up templates for status error codes
50
+ app_tree["app"]["views"]["404.html"] ||= IO.read(::File.expand_path(File.join("..", "..", "resources" ,"404.html"), __FILE__))
51
+ app_tree["app"]["views"]["500.html"] ||= IO.read(::File.expand_path(File.join("..", "..", "resources" ,"500.html"), __FILE__))
52
+ app_tree["app"]["views"]["404.html.erb"] ||= IO.read(::File.expand_path(File.join("..", "..", "resources" ,"404.erb"), __FILE__))
53
+ app_tree["app"]["views"]["500.html.erb"] ||= IO.read(::File.expand_path(File.join("..", "..", "resources" ,"500.erb"), __FILE__))
54
+ app_tree["app"]["views"]["404.html.slim"] ||= IO.read(::File.expand_path(File.join("..", "..", "resources" ,"404.slim"), __FILE__))
55
+ app_tree["app"]["views"]["500.html.slim"] ||= IO.read(::File.expand_path(File.join("..", "..", "resources" ,"500.slim"), __FILE__))
56
+ app_tree["app"]["views"]["404.html.haml"] ||= IO.read(::File.expand_path(File.join("..", "..", "resources" ,"404.haml"), __FILE__))
57
+ app_tree["app"]["views"]["500.html.haml"] ||= IO.read(::File.expand_path(File.join("..", "..", "resources" ,"500.haml"), __FILE__))
58
+
49
59
  # set up the assets folder
50
60
  app_tree["assets"] ||= {}
51
61
  app_tree["assets"]["stylesheets"] ||= {}
52
62
  app_tree["assets"]["javascripts"] ||= {}
63
+ app_tree["assets"]["javascripts"]["websocket.js"] ||= IO.read(::File.expand_path(File.join("..", "..", "resources" ,"websockets.js"), __FILE__)).gsub('appname', ARGV[1])
53
64
  app_tree["assets"]["welcome.html"] ||= IO.read(::File.expand_path(File.join("..", "..", "resources" ,"welcome_page.html"), __FILE__)).gsub('appname', ARGV[1])
54
65
 
55
66
  # app core files.
@@ -92,19 +103,10 @@ class AppTemplate
92
103
 
93
104
  # set up a public folder for static file service
94
105
  app_tree["public"] ||= {}
95
- app_tree["public"]["404.slim"] ||= IO.read(::File.expand_path(File.join("..", "..", "resources" ,"404.slim"), __FILE__))
96
- app_tree["public"]["500.slim"] ||= IO.read(::File.expand_path(File.join("..", "..", "resources" ,"500.slim"), __FILE__))
97
- app_tree["public"]["404.html"] ||= IO.read(::File.expand_path(File.join("..", "..", "resources" ,"404.html"), __FILE__))
98
- app_tree["public"]["500.html"] ||= IO.read(::File.expand_path(File.join("..", "..", "resources" ,"500.html"), __FILE__))
99
- app_tree["public"]["404.erb"] ||= IO.read(::File.expand_path(File.join("..", "..", "resources" ,"404.erb"), __FILE__))
100
- app_tree["public"]["500.erb"] ||= IO.read(::File.expand_path(File.join("..", "..", "resources" ,"500.erb"), __FILE__))
101
- app_tree["public"]["404.haml"] ||= IO.read(::File.expand_path(File.join("..", "..", "resources" ,"404.haml"), __FILE__))
102
- app_tree["public"]["500.haml"] ||= IO.read(::File.expand_path(File.join("..", "..", "resources" ,"500.haml"), __FILE__))
103
106
  app_tree["public"]["assets"] ||= {}
104
107
  app_tree["public"]["assets"]["stylesheets"] ||= {}
105
108
  app_tree["public"]["assets"]["javascripts"] ||= {}
106
109
  app_tree["public"]["images"] ||= {}
107
- app_tree["public"]["images"]['plezi_gray.png'] ||= IO.read(::File.expand_path(File.join("..", "..", "resources" ,"plezi_gray.png"), __FILE__))
108
110
 
109
111
  end
110
112
 
@@ -113,7 +113,7 @@ Encoding.default_external = 'utf-8'
113
113
  # PL is a shortcut for the Plezi module, so that `PL == Plezi`.
114
114
  PL = Plezi
115
115
 
116
- # shortcut for Plezi.listen.
116
+ # shortcut for Plezi::DSL.listen.
117
117
  #
118
118
  def listen(params = {})
119
119
  Plezi::DSL.listen params
@@ -74,6 +74,7 @@ module Plezi
74
74
  rescue => e
75
75
  EventMachine.queue( [@socket], REMOVE_CONNECTION_PROC)
76
76
  end
77
+ true
77
78
  end
78
79
 
79
80
  # the non-blocking proc used for send_nonblock
@@ -106,10 +107,13 @@ module Plezi
106
107
  @protocol = false
107
108
  end
108
109
  end
109
- # closes the connection.
110
+
111
+ # the non-blocking proc used for send_nonblock
112
+ FLUSH_AND_CLOSE_PROC = Proc.new {|c| c.flush; EventMachine.remove_io c.socket}
113
+
114
+ # Closes the connection. This is always asynchronous and will return immidiately.
110
115
  def close
111
- flush
112
- EventMachine.queue [@socket], REMOVE_CONNECTION_PROC
116
+ EventMachine.queue [self], FLUSH_AND_CLOSE_PROC
113
117
  end
114
118
  alias :disconnect :close
115
119
 
@@ -213,7 +213,7 @@ module Plezi
213
213
  Plezi.run_every(3_600) {GC.start; Plezi.info "Refreshing worker threads."; EventMachine.stop; EventMachine.start Plezi.max_threads}
214
214
  # run_every( 1 , Proc.new() { Plezi.info "#{IO_CONNECTION_DIC.length} active connections ( #{ IO_CONNECTION_DIC.select{|k,v| v.protocol.is_a?(WSProtocol)} .length } websockets)." })
215
215
  # run_every 10 , -> {Plezi.info "Cache report: #{CACHE_STORE.length} objects cached." }
216
- puts "** Deprecation Warning:\n- The current code for default error pages will be changed in version 0.9.0.\n- Default error pages will follow a different naming and location conventions.\n- The updated design will be part of the updated `plezi` helper script.\nPlease review your code before upgrading to the 0.9.0 version.\n"
216
+ # puts "** Deprecation Warning:\n- The current code for default error pages will be changed in version 0.9.0.\n- Default error pages will follow a different naming and location conventions.\n- The updated design will be part of the updated `plezi` helper script.\nPlease review your code before upgrading to the 0.9.0 version.\n"
217
217
  puts "Services running Plezi version #{Plezi::VERSION}. Press ^C to stop"
218
218
  EventMachine.start Plezi.max_threads
219
219
 
@@ -95,18 +95,17 @@ module Plezi
95
95
  # sends a response for an error code, rendering the relevent file (if exists).
96
96
  def send_by_code request, code, headers = {}
97
97
  begin
98
- if params[:root]
99
- if defined?(::Slim) && Plezi.file_exists?(File.join(params[:root], "#{code}.slim"))
100
- Plezi.cache_data File.join(params[:root], "#{code}.slim"), Slim::Template.new( File.join( params[:root], "#{code}.slim" ) ) unless Plezi.cached? File.join(params[:root], "#{code}.slim")
101
- return send_raw_data request, Plezi.get_cached( File.join(params[:root], "#{code}.slim") ).render( self, request: request ), 'text/html', code, headers
102
- elsif defined?(::Haml) && Plezi.file_exists?(File.join(params[:root], "#{code}.haml"))
103
- Plezi.cache_data File.join(params[:root], "#{code}.haml"), Haml::Engine.new( IO.read( File.join( params[:root], "#{code}.haml" ) ) ) unless Plezi.cached? File.join(params[:root], "#{code}.haml")
104
- return send_raw_data request, Plezi.get_cached( File.join(params[:root], "#{code}.haml") ).render( self ), 'text/html', code, headers
105
- elsif defined?(::ERB) && Plezi.file_exists?(File.join(params[:root], "#{code}.erb"))
106
- return send_raw_data request, ERB.new( Plezi.load_file( File.join(params[:root], "#{code}.erb") ) ).result(binding), 'text/html', code, headers
107
- elsif Plezi.file_exists?(File.join(params[:root], "#{code}.html"))
108
- return send_file(request, File.join(params[:root], "#{code}.html"), code, headers)
109
- end
98
+ @base_code_path ||= params[:templates] || File.expand_path('.')
99
+ if defined?(::Slim) && Plezi.file_exists?(fn = File.join(@base_code_path, "#{code}.html.slim"))
100
+ Plezi.cache_data fn, Slim::Template.new( fn ) unless Plezi.cached? fn
101
+ return send_raw_data request, Plezi.get_cached( fn ).render( self, request: request ), 'text/html', code, headers
102
+ elsif defined?(::Haml) && Plezi.file_exists?(fn = File.join(@base_code_path, "#{code}.html.haml"))
103
+ Plezi.cache_data fn, Haml::Engine.new( IO.read( fn ) ) unless Plezi.cached? fn
104
+ return send_raw_data request, Plezi.get_cached( File.join(@base_code_path, "#{code}.html.haml") ).render( self ), 'text/html', code, headers
105
+ elsif defined?(::ERB) && Plezi.file_exists?(fn = File.join(@base_code_path, "#{code}.html.erb"))
106
+ return send_raw_data request, ERB.new( Plezi.load_file( fn ) ).result(binding), 'text/html', code, headers
107
+ elsif Plezi.file_exists?(fn = File.join(@base_code_path, "#{code}.html"))
108
+ return send_file(request, fn, code, headers)
110
109
  end
111
110
  return true if send_raw_data(request, HTTPResponse::STATUS_CODES[code], 'text/plain', code, headers)
112
111
  rescue Exception => e
@@ -31,11 +31,11 @@ module Plezi
31
31
  def on_message
32
32
  # parse the request
33
33
  parse_message
34
- if (@parser_stage == 1) && @parser_data[:version] >= 1.1
35
- # send 100 continue message????? doesn't work! both Crome and Safari go crazy if this is sent after the request was sent (but before all the packets were recieved... msgs over 1 Mb).
36
- # Plezi.push_event Proc.new { Plezi.info "sending continue signal."; connection.send_nonblock "100 Continue\r\n\r\n" }
37
- # connection.send_unsafe_interrupt "100 Continue\r\n\r\n" # causes double lock on connection
38
- end
34
+ # if (@parser_stage == 1) && @parser_data[:version] >= 1.1
35
+ # # send 100 continue message????? doesn't work! both Crome and Safari go crazy if this is sent after the request was sent (but before all the packets were recieved... msgs over 1 Mb).
36
+ # # Plezi.push_event Proc.new { Plezi.info "sending continue signal."; connection.send_nonblock "100 Continue\r\n\r\n" }
37
+ # # connection.send_unsafe_interrupt "100 Continue\r\n\r\n" # causes double lock on connection
38
+ # end
39
39
  true
40
40
  end
41
41
 
@@ -124,6 +124,7 @@ module Plezi
124
124
  end
125
125
  @parser_data[:step] = 0
126
126
  @parser_stage += 1
127
+ review_message_size
127
128
  end
128
129
  if @parser_stage == 2 && @parser_data[:mask] == 1
129
130
  @parser_data[:mask_key] = data.slice!(0,4)
@@ -187,6 +188,48 @@ module Plezi
187
188
  @parser_data[:body].clear
188
189
  @parser_data[:step] = 0
189
190
  end
191
+ #reviews the message size and closes the connection if expected message size is over the allowed limit.
192
+ def review_message_size
193
+ if ( self.class.message_size_limit.to_i > 0 ) && ( ( @parser_data[:len] + @message.bytesize ) > self.class.message_size_limit.to_i )
194
+ Plezi.callback @connection, :disconnect
195
+ @message.clear
196
+ @parser_data[:step] = 0
197
+ @parser_data[:body].clear
198
+ @parser_stage = -1
199
+ return false
200
+ end
201
+ true
202
+ end
203
+
204
+ # Sets the message byte size limit for a Websocket message. Defaults to 0 (no limit)
205
+ #
206
+ # Although memory will be allocated for the latest TCP/IP frame,
207
+ # this allows the websocket to disconnect if the incoming expected message size exceeds the allowed maximum size.
208
+ #
209
+ # If the sessage size limit is exceeded, the disconnection will be immidiate as an attack will be assumed. The protocol's normal disconnect sequesnce will be discarded.
210
+ def self.message_size_limit=val
211
+ @message_size_limit = val
212
+ end
213
+ # Gets the message byte size limit for a Websocket message. Defaults to 0 (no limit)
214
+ def self.message_size_limit
215
+ @message_size_limit
216
+ end
217
+ message_size_limit = 0
218
+
219
+ end
220
+
221
+ # Sets the message byte size limit for a Websocket message. Defaults to 0 (no limit)
222
+ #
223
+ # Although memory will be allocated for the latest TCP/IP frame,
224
+ # this allows the websocket to disconnect if the incoming expected message size exceeds the allowed maximum size.
225
+ #
226
+ # If the sessage size limit is exceeded, the disconnection will be immidiate as an attack will be assumed. The protocol's normal disconnect sequesnce will be discarded.
227
+ def self.ws_message_size_limit=val
228
+ WSProtocol.message_size_limit = val
229
+ end
230
+ # Gets the message byte size limit for a Websocket message. Defaults to 0 (no limit)
231
+ def self.ws_message_size_limit
232
+ WSProtocol.message_size_limit
190
233
  end
191
234
  end
192
235
 
@@ -52,9 +52,14 @@ module Plezi
52
52
  end
53
53
  alias :close :disconnect
54
54
 
55
- # sends data through the socket. a shortcut for ws_client.response <<
55
+ # Asynchronously sends data through the socket. a shortcut for ws_client.response <<
56
56
  def << data
57
- @response << data
57
+ @response << data
58
+ end
59
+
60
+ # Synchronously sends data through the socket. a shortcut for ws_client.response <<
61
+ def send data
62
+ @response.send data
58
63
  end
59
64
 
60
65
  # Create a simple Websocket Client(!)
@@ -17,7 +17,22 @@ module Plezi
17
17
  #the request.
18
18
  attr_accessor :request
19
19
 
20
- PING_PROC = Proc.new {|res| EventMachine.timed_job 45, 1, [res.ping], PING_PROC unless res.service.disconnected? }
20
+ # Sets the defalt Websockt auto-ping interval.
21
+ #
22
+ # The default ping interval is 45 seconds.
23
+ #
24
+ # It's possible to set the ping interval to false, thereby disabling auto-pinging.
25
+ def self.ping_interval=(val)
26
+ @ping_interval = val
27
+ end
28
+ # Returns the defalt Websockt auto-ping interval.
29
+ #
30
+ # Plezi will automatically send a ping frame to keep websocket connections open.
31
+ # This auto-pinging can be disabled by setting the `ping_interval` to false.
32
+ def self.ping_interval
33
+ @ping_interval ||= 45
34
+ end
35
+ PING_PROC = Proc.new {|res| EventMachine.timed_job ping_interval, 1, [res.ping], PING_PROC unless res.service.disconnected? || !ping_interval }
21
36
 
22
37
  def initialize request
23
38
  @request, @service = request,request.service
@@ -81,20 +96,20 @@ module Plezi
81
96
  service.locker.locked? ? (EventMachine.queue [service], CLOSE_PROC) : (CLOSE_PROC.call(service))
82
97
  end
83
98
 
84
- FRAME_SIZE_LIMIT = 131_072
99
+ FRAME_SIZE_LIMIT = 131_072 # javascript to test: str = '0123456789'; bigstr = ""; for(i = 0; i<=1033200; i+=1) {bigstr += str}; ws = new WebSocket('ws://localhost:3000/ws/size') ; ws.onmessage = function(e) {console.log(e.data.length)};ws. onopen = function(e) {ws.send(bigstr)}
85
100
 
86
- # Dangerzone! ()alters the string, use `send` instead: formats the data as one or more WebSocket frames.
101
+ # Dangerzone! use `send` instead: formats the data as one or more WebSocket frames.
87
102
  def self.frame_data data, op_code = nil, fin = true
88
103
  # set up variables
89
104
  frame = ''.force_encoding('binary')
90
105
  op_code ||= (data.encoding.name == 'UTF-8' ? 1 : 2)
91
106
 
92
107
 
93
- if data[FRAME_SIZE_LIMIT]
108
+ if data[FRAME_SIZE_LIMIT] && fin
94
109
  # fragment big data chuncks into smaller frames - op-code reset for 0 for all future frames.
95
110
  data = data.dup
96
111
  data.force_encoding('binary')
97
- [frame << frame_data(data.slice!(0..FRAME_SIZE_LIMIT), op_code, false), op_code = 0] while data.length > FRAME_SIZE_LIMIT # 1048576
112
+ [frame << frame_data(data.slice!(0...FRAME_SIZE_LIMIT), op_code, false), op_code = 0] while data.length > FRAME_SIZE_LIMIT # 1048576
98
113
  # frame << frame_data(data.slice!(0..1048576), op_code, false)
99
114
  # data =
100
115
  # op_code = 0
@@ -110,7 +125,7 @@ module Plezi
110
125
 
111
126
  if data.length < 125
112
127
  frame << data.length.chr
113
- elsif data.length.bit_length < 16
128
+ elsif data.length.bit_length <= 16
114
129
  frame << 126.chr
115
130
  frame << [data.length].pack('S>')
116
131
  else
@@ -123,4 +138,24 @@ module Plezi
123
138
  frame
124
139
  end
125
140
  end
141
+
142
+ module_function
143
+ # Sets the defalt Websockt auto-ping interval.
144
+ #
145
+ # This method accepts one value, which should be either a number in seconds or `false`.
146
+ #
147
+ # The default ping interval is 45 seconds.
148
+ #
149
+ # It's possible to set the ping interval to false, thereby disabling auto-pinging.
150
+ def ping_interval=(val)
151
+ WSResponse.ping_interval = val
152
+ end
153
+ # Returns the defalt Websockt auto-ping interval.
154
+ #
155
+ # Plezi will automatically send a ping frame to keep websocket connections open.
156
+ # This auto-pinging can be disabled by setting the `ping_interval` to false.
157
+ def ping_interval
158
+ WSResponse.ping_interval
159
+ end
160
+
126
161
  end
@@ -1,3 +1,3 @@
1
1
  module Plezi
2
- VERSION = "0.8.7"
2
+ VERSION = "0.9.0"
3
3
  end
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
8
8
  spec.version = Plezi::VERSION
9
9
  spec.authors = ["Boaz Segev"]
10
10
  spec.email = ['boaz@2be.co.il']
11
- spec.summary = %q{Plezi is the native Ruby Framework for real time web-apps, with Websockets, RESTful routing and HTTP streaming support.}
12
- spec.description = %q{Plezi is the native Ruby Framework for real time web-apps, with Websockets, RESTful routing and HTTP streaming support.}
11
+ spec.summary = %q{Plezi is the native Ruby Framework for real time web-apps. An easy way to write Websockets, RESTful routing and HTTP streaming apps.}
12
+ spec.description = %q{Plezi is the native Ruby Framework for real time web-apps. An easy way to write Websockets, RESTful routing and HTTP streaming apps.}
13
13
  spec.homepage = "http://boazsegev.github.io/plezi/"
14
14
  spec.license = "MIT"
15
15
 
@@ -21,7 +21,7 @@ Gem::Specification.new do |spec|
21
21
  spec.add_development_dependency "bundler", "~> 1.7"
22
22
  spec.add_development_dependency "rake", "~> 10.0"
23
23
 
24
- spec.post_install_message = "** Deprecation Warning:\n- The current code for default error pages will be changed in version 0.9.0.\n- Default error pages will follow a different naming and location conventions.\n- The updated design will be part of the updated `plezi` helper script.\nPlease review your code before upgrading to the 0.9.0 version.\n\nThank you for installing Plezi, the native Ruby Framework for real time web-apps."
25
- spec.post_install_message ||= "Thank you for installing Plezi, the native Ruby Framework for real time web-apps."
24
+ spec.post_install_message = "Thank you for installing Plezi, the native Ruby Framework for real time web-apps."
25
+ # spec.post_install_message = "** Deprecation Warning:\n- The current code for default error pages will be changed in version 0.9.0.\n- Default error pages will follow a different naming and location conventions.\n- The updated design will be part of the updated `plezi` helper script.\nPlease review your code before upgrading to the 0.9.0 version.\n\nThank you for installing Plezi, the native Ruby Framework for real time web-apps."
26
26
 
27
27
  end
@@ -11,21 +11,12 @@
11
11
  # http://sequel.jeremyevans.net
12
12
  if defined? Sequel
13
13
 
14
- if defined? SQLite3
15
- # An in-memory Sqlite3 connection:
16
- # DB = Sequel.sqlite
17
-
18
- # A Sqlite3 connection to a persistent database
19
- DB = Sequel.sqlite(Root.join('db', 'db.sqlite3').to_s)
20
-
21
- elsif defined? PG
22
- if ENV['DYNO']
23
- # A Postgres connection for Heroku:
24
- DB = Sequel.connect(ENV['HEROKU_POSTGRESQL_RED_URL'])
25
- else
26
- # app name is the same as the root app folder: Root.to_s.split(/\/\\/).last
27
- DB = Sequel.connect("postgres://localhost/#{Root.to_s.split(/[\/\\]/).last}")
28
- end
14
+ if defined? PG && ENV['DYNO']
15
+ # A default Postgres connection for Heroku:
16
+ DB = Sequel.connect(ENV['HEROKU_POSTGRESQL_RED_URL'])
17
+ else
18
+ # use db/config.yaml to connect to database
19
+ DB = Sequel.connect( YAML::load( File.open( Root.join('db', 'config.yml').to_s ) )[ ENV["ENV"].to_s ] )
29
20
  end
30
21
  if defined? Rake
31
22
  ##########
@@ -1,28 +1,29 @@
1
-
2
- // remember to set your websocket uri as an absolute path!
3
- var ws_uri = "ws://echo.websocket.org/";
1
+ // 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 += "/";
5
+ // websocket variable.
4
6
  var websocket = NaN
5
7
 
6
8
  function init_websocket()
7
9
  {
8
10
  websocket = new WebSocket(ws_uri);
9
- websocket.onopen = function(e) { on_open(e) };
10
- websocket.onclose = function(e) { on_close(e) };
11
- websocket.onmessage = function(e) { on_message(e) };
12
- websocket.onerror = function(e) { on_error(e) }; }
13
-
14
- function on_open(e) {
11
+ websocket.onopen = function(e) {
15
12
  // what do you want to do now?
16
- }
17
- function on_close(e) {
13
+ };
14
+
15
+ websocket.onclose = function(e) {
18
16
  // you probably want to reopen the websocket if it closes.
19
17
  init_websocket()
20
- }
21
- function on_message(e) {
18
+ };
19
+ websocket.onerror = function(e) {
22
20
  // what do you want to do now?
23
- }
24
- function on_error(e) {
21
+ };
22
+ websocket.onmessage = function(e) {
25
23
  // what do you want to do now?
26
- }
24
+ console.log(e.data);
25
+ // to use JSON, use:
26
+ // msg = JSON.parse(e.data); // remember to use JSON also in your Plezi controller.
27
+ };
27
28
  }
28
- window.addEventListener("load", init, false);
29
+ window.addEventListener("load", init_websocket, false);
@@ -1,30 +1,64 @@
1
- <!DOCTYPE html><head><title>appname - Feed Me!</title><style type="text/css">body, html
1
+ <!DOCTYPE html><head><title>appname - Feed Me!</title>
2
+ <link href='http://fonts.googleapis.com/css?family=Shadows+Into+Light|Architects+Daughter' rel='stylesheet' type='text/css'>
3
+
4
+ <link href="https://fonts.googleapis.com/css?family=Architects+Daughter" rel="stylesheet" type="text/css">
5
+ <style type="text/css">
6
+ /*
7
+ med-blue: #44518E
8
+ dark-gray: #424A70
9
+ blue: #1B2864
10
+ light-blue: #818ECE
11
+ light-gray: #99A3CE
12
+ */
13
+ body, html
2
14
  {
3
- background-color: #eee;
15
+ background-color: #99A3CE;
4
16
  padding: 0; margin: 0;
5
17
  width: 100%;
6
18
  font-size: 1em;
7
19
  }
8
- body, html, h1, #wrapper, #wrapper h2
9
- {
10
- background-image: url(/images/plezi_gray.png);
11
- background-position: center top;
12
- background-origin: inherit;
13
- background-repeat: no-repeat;
14
- background-size: 88% auto;
15
- background-attachment: fixed;
16
-
17
- }
18
20
 
19
21
  h1
20
22
  {
21
- background-color: #ddd;
22
- color: #00a;
23
+ font-family: 'Indie Flower', cursive;
24
+ background-color: #1B2864;
25
+ color: #99A3CE;
23
26
  text-align: center;
24
- border-bottom: 1px solid #000;
27
+ border-bottom: 1px solid #424A70;
25
28
  margin: 0 0 1em 0;
26
29
  padding: 0.5em 0;
27
30
  width: 100%;
31
+
32
+ }
33
+ h2, h3
34
+ {
35
+ background-color: #44518E;
36
+ color: #99A3CE;
37
+ text-align: left;
38
+ margin: 0 0 1em 0;
39
+ padding: 0.5em 5%;
40
+ border-radius: 20px;
41
+ font-family: 'Shadows Into Light', cursive;
42
+ }
43
+ h2:before {
44
+ content: "|||";
45
+ color: #424A70;
46
+ padding-right: 0.3em;
47
+ margin-left: -1.5em;
48
+ }
49
+ h3:before {
50
+ content: "|||||";
51
+ color: #424A70;
52
+ padding-right: 0.3em;
53
+ margin-left: -2em;
54
+ }
55
+ h1 a, h2 a, h3 a
56
+ {
57
+ color: #EBCD86;
58
+ }
59
+ h1 a:hover, h2 a:hover, h3 a:hover
60
+ {
61
+ color: #EBD7A6;
28
62
  }
29
63
  p
30
64
  {
@@ -34,12 +68,12 @@ p
34
68
  }
35
69
  a
36
70
  {
37
- color: #a04;
71
+ color: #D0AC54;
38
72
  text-decoration: none;
39
73
  }
40
74
  a:hover
41
75
  {
42
- color: #70f;
76
+ color: #927121;
43
77
  text-decoration: underline;
44
78
  }
45
79
  #wrapper
@@ -51,15 +85,7 @@ a:hover
51
85
  min-height: 50%;
52
86
  color: #007;
53
87
  }
54
- #wrapper h2
55
- {
56
- background-color: #ddd;
57
- color: #008;
58
- text-align: left;
59
- margin: 0 0 1em 0;
60
- padding: 0.5em 5%;
61
- border-radius: 20px;
62
- }
88
+
63
89
  #wrapper p{ padding: 0 2%;}
64
90
  .bold { font-weight: bold; }
65
91
  #wrapper ol li{ padding: 0 2%;}
@@ -69,4 +95,35 @@ pre
69
95
  padding: 0.5em 0;
70
96
  background-color: #444;
71
97
  color: #ddd;
72
- }</style></head><body><h1>Welcome to <a href="https://github.com/boazsegev/plezi">Plezi</a></h1><div id="wrapper"><h2>Congratulations, appname is running - What's next?</h2><p><span class="bold">Congratulations</span>, you're now running appname and it has so much potential!</p><p>appname started out <a href="https://github.com/boazsegev/plezi">Plezi</a> and it's your quest to feed it your code and make sure appname grows strong and happy.</p><p>You're the master of this quest, and your next steps might include:</p><ol><li><p class="bold">Deciding which gems to use:</p><ul><li>edit Gemfile in the appname folder.</li></ul></li><li><p class="bold">Reviewing the sample code and feeding <a href="https://github.com/boazsegev/plezi">Plezi</a> your code:</p><ul><li>Review the 'sample_controller.rb' file in the appname/app/controllers folder.</li><li>Delete the 'sample_controller.rb' file and this file (appname/assets/welcome.html).</li><li>Write your own controller and code.</li><li>Edit the 'routes.rb' file to set up your routes.</li></ul></li><li><p><span class="bold">Having fun</span> and submitting any issues you discover to the <a href="https://github.com/boazsegev/plezi">Plezi Github Project.</a></p></li></ol><p class="bold">Good Luck!</p></div></body>
98
+ }
99
+
100
+ </style>
101
+ </head>
102
+ <body>
103
+ <h1>Welcome to <a href="https://github.com/boazsegev/plezi">Plezi</a></h1>
104
+ <div id="wrapper">
105
+ <h2>Congratulations, <a href='/'>appname</a> is running - What's next?</h2>
106
+ <p><span class="bold">Congratulations</span>, you're now running appname and it has so much potential!</p>
107
+ <p>appname started out <a href="https://github.com/boazsegev/plezi">Plezi</a> and it's your quest to feed it your code and make sure appname grows strong and happy.</p>
108
+ <p>You're the master of this quest, and your next steps might include:</p>
109
+ <ol><li><p class="bold">Deciding which gems to use:</p>
110
+ <ul>
111
+ <li>edit Gemfile in the appname folder.</li>
112
+ </ul>
113
+ </li>
114
+ <li>
115
+ <p class="bold">Reviewing the sample code and feeding <a href="https://github.com/boazsegev/plezi">Plezi</a> your code:</p>
116
+ <ul>
117
+ <li>Review the 'sample_controller.rb' file in the appname/app/controllers folder.</li>
118
+ <li>Delete the 'sample_controller.rb' file and this file (appname/assets/welcome.html).</li>
119
+ <li>Write your own controller and code.</li>
120
+ <li>Edit the 'routes.rb' file to set up your routes.</li>
121
+ </ul>
122
+ </li>
123
+ <li>
124
+ <p><span class="bold">Having fun</span> and submitting any issues you discover to the <a href="https://github.com/boazsegev/plezi">Plezi Github Project.</a></p>
125
+ </li>
126
+ </ol>
127
+ <p class="bold">Good Luck!</p>
128
+ </div>
129
+ </body>
@@ -135,6 +135,15 @@ class TestCtrl
135
135
  end
136
136
  end
137
137
 
138
+ class WSsizeTestCtrl
139
+ # called when new Websocket data is recieved
140
+ #
141
+ # data is a string that contains binary or UTF8 (message dependent) data.
142
+ def on_message data
143
+ response << data
144
+ end
145
+ end
146
+
138
147
  module PleziTestTasks
139
148
  module_function
140
149
 
@@ -251,7 +260,7 @@ module PleziTestTasks
251
260
  go_test = false
252
261
  end
253
262
  end
254
- ws3 = Plezi::WebsocketClient.connect_to("wss://localhost:3030") do |msg|
263
+ ws3 = Plezi::WebsocketClient.connect_to("ws://localhost:3000") do |msg|
255
264
  if msg.match /uuid: ([^s]*)/
256
265
  ws2 << "to: #{msg.match(/^uuid: ([^s]*)/)[1]}"
257
266
  puts " * Websocket UUID for unicast testing: #{msg.match(/^uuid: ([^s]*)/)[1]}"
@@ -290,6 +299,27 @@ module PleziTestTasks
290
299
  PL.on_shutdown {puts " * Websocket broadcast message test: #{RESULTS[broadcast_test]}" unless broadcast_test}
291
300
  PL.on_shutdown {puts " * Websocket unicast message test: #{RESULTS[unicast_test]}"}
292
301
  end
302
+ def test_websocket_sizes
303
+ should_disconnect = false
304
+ ws = Plezi::WebsocketClient.connect_to("ws://localhost:3000/ws/size") do |msg|
305
+ if should_disconnect
306
+ puts " * Websocket size disconnection test: #{RESULTS[false]}"
307
+ else
308
+ puts " * Websocket message size test: got #{msg.bytesize} bytes"
309
+ end
310
+
311
+ end
312
+ ws.on_disconnect do
313
+ puts " * Websocket size disconnection test: #{RESULTS[should_disconnect]}"
314
+ end
315
+ str = 'a'
316
+ time_now = Time.now
317
+ 6.times {|i| str = str * 2**i;puts " * Websocket message size test: sending #{str.bytesize} bytes"; ws.send str; sleep 0.2 }
318
+ sleep (Time.now - time_now + 1)
319
+ should_disconnect = true
320
+ Plezi.ws_message_size_limit = 1024
321
+ ws << str
322
+ end
293
323
  def test_404
294
324
  puts " * 404 not found and router continuity tests: #{RESULTS[ Net::HTTP.get_response(URI.parse "http://localhost:3000/get404" ).code == '404' ]}"
295
325
 
@@ -323,6 +353,8 @@ route("/ssl") {|req, res| res << "false" }
323
353
  listen port: 3030, ssl: true
324
354
  route("/ssl") {|req, res| res << "true" }
325
355
 
356
+ shared_route 'ws/size', WSsizeTestCtrl
357
+
326
358
  shared_route '/some/:multi{path|another_path}/(:option){route|test}/(:id)/(:optional)', TestCtrl
327
359
  shared_route '/', TestCtrl
328
360
 
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.8.7
4
+ version: 0.9.0
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-06-25 00:00:00.000000000 Z
11
+ date: 2015-07-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -38,8 +38,8 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '10.0'
41
- description: Plezi is the native Ruby Framework for real time web-apps, with Websockets,
42
- RESTful routing and HTTP streaming support.
41
+ description: Plezi is the native Ruby Framework for real time web-apps. An easy way
42
+ to write Websockets, RESTful routing and HTTP streaming apps.
43
43
  email:
44
44
  - boaz@2be.co.il
45
45
  executables:
@@ -106,7 +106,6 @@ files:
106
106
  - resources/haml_config.rb
107
107
  - resources/i18n_config.rb
108
108
  - resources/oauth_config.rb
109
- - resources/plezi_gray.png
110
109
  - resources/plezi_websockets.html
111
110
  - resources/rakefile
112
111
  - resources/redis_config.rb
@@ -119,14 +118,8 @@ homepage: http://boazsegev.github.io/plezi/
119
118
  licenses:
120
119
  - MIT
121
120
  metadata: {}
122
- post_install_message: |-
123
- ** Deprecation Warning:
124
- - The current code for default error pages will be changed in version 0.9.0.
125
- - Default error pages will follow a different naming and location conventions.
126
- - The updated design will be part of the updated `plezi` helper script.
127
- Please review your code before upgrading to the 0.9.0 version.
128
-
129
- Thank you for installing Plezi, the native Ruby Framework for real time web-apps.
121
+ post_install_message: Thank you for installing Plezi, the native Ruby Framework for
122
+ real time web-apps.
130
123
  rdoc_options: []
131
124
  require_paths:
132
125
  - lib
@@ -145,7 +138,7 @@ rubyforge_project:
145
138
  rubygems_version: 2.4.7
146
139
  signing_key:
147
140
  specification_version: 4
148
- summary: Plezi is the native Ruby Framework for real time web-apps, with Websockets,
149
- RESTful routing and HTTP streaming support.
141
+ summary: Plezi is the native Ruby Framework for real time web-apps. An easy way to
142
+ write Websockets, RESTful routing and HTTP streaming apps.
150
143
  test_files:
151
144
  - test/plezi_tests.rb
Binary file