plezi 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/CHANGELOG.md +450 -0
  4. data/Gemfile +4 -0
  5. data/KNOWN_ISSUES.md +13 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +341 -0
  8. data/Rakefile +2 -0
  9. data/TODO.md +19 -0
  10. data/bin/plezi +301 -0
  11. data/lib/plezi.rb +125 -0
  12. data/lib/plezi/base/cache.rb +77 -0
  13. data/lib/plezi/base/connections.rb +33 -0
  14. data/lib/plezi/base/dsl.rb +177 -0
  15. data/lib/plezi/base/engine.rb +85 -0
  16. data/lib/plezi/base/events.rb +84 -0
  17. data/lib/plezi/base/io_reactor.rb +41 -0
  18. data/lib/plezi/base/logging.rb +62 -0
  19. data/lib/plezi/base/rack_app.rb +89 -0
  20. data/lib/plezi/base/services.rb +57 -0
  21. data/lib/plezi/base/timers.rb +71 -0
  22. data/lib/plezi/handlers/controller_magic.rb +383 -0
  23. data/lib/plezi/handlers/http_echo.rb +27 -0
  24. data/lib/plezi/handlers/http_host.rb +215 -0
  25. data/lib/plezi/handlers/http_router.rb +69 -0
  26. data/lib/plezi/handlers/magic_helpers.rb +43 -0
  27. data/lib/plezi/handlers/route.rb +272 -0
  28. data/lib/plezi/handlers/stubs.rb +143 -0
  29. data/lib/plezi/server/README.md +33 -0
  30. data/lib/plezi/server/helpers/http.rb +169 -0
  31. data/lib/plezi/server/helpers/mime_types.rb +999 -0
  32. data/lib/plezi/server/protocols/http_protocol.rb +318 -0
  33. data/lib/plezi/server/protocols/http_request.rb +133 -0
  34. data/lib/plezi/server/protocols/http_response.rb +294 -0
  35. data/lib/plezi/server/protocols/websocket.rb +208 -0
  36. data/lib/plezi/server/protocols/ws_response.rb +92 -0
  37. data/lib/plezi/server/services/basic_service.rb +224 -0
  38. data/lib/plezi/server/services/no_service.rb +196 -0
  39. data/lib/plezi/server/services/ssl_service.rb +193 -0
  40. data/lib/plezi/version.rb +3 -0
  41. data/plezi.gemspec +26 -0
  42. data/resources/404.erb +68 -0
  43. data/resources/404.haml +64 -0
  44. data/resources/404.html +67 -0
  45. data/resources/404.slim +63 -0
  46. data/resources/500.erb +68 -0
  47. data/resources/500.haml +63 -0
  48. data/resources/500.html +67 -0
  49. data/resources/500.slim +63 -0
  50. data/resources/Gemfile +85 -0
  51. data/resources/anorexic_gray.png +0 -0
  52. data/resources/anorexic_websockets.html +47 -0
  53. data/resources/code.rb +8 -0
  54. data/resources/config.ru +39 -0
  55. data/resources/controller.rb +139 -0
  56. data/resources/db_ac_config.rb +58 -0
  57. data/resources/db_dm_config.rb +51 -0
  58. data/resources/db_sequel_config.rb +42 -0
  59. data/resources/en.yml +204 -0
  60. data/resources/environment.rb +41 -0
  61. data/resources/haml_config.rb +6 -0
  62. data/resources/i18n_config.rb +14 -0
  63. data/resources/rakefile.rb +22 -0
  64. data/resources/redis_config.rb +35 -0
  65. data/resources/routes.rb +26 -0
  66. data/resources/welcome_page.html +72 -0
  67. data/websocket chatroom.md +639 -0
  68. metadata +141 -0
@@ -0,0 +1,193 @@
1
+ module Plezi
2
+
3
+ # test connections with: openssl s_client -connect localhost:3000
4
+
5
+ # this class is a basic TCP socket service with SSL.
6
+ #
7
+ # a protocol should be assigned, or the service will fall back to an echo service.
8
+ #
9
+ # to-do: fix self certificate issue (fails).
10
+ class SSLService < BasicService
11
+
12
+ # instance methods
13
+
14
+ attr_reader :ssl_socket
15
+
16
+ # creates a new connection wrapper object for the new socket that was recieved from the `accept_nonblock` method call.
17
+ def initialize soc, parameters = {}
18
+ context = OpenSSL::SSL::SSLContext.new
19
+ context.set_params verify_mode: OpenSSL::SSL::VERIFY_NONE# OpenSSL::SSL::VERIFY_PEER #OpenSSL::SSL::VERIFY_NONE
20
+ # context.options DoNotReverseLookup: true
21
+ if parameters[:ssl_cert] && parameters[:ssl_key]
22
+ context.cert = parameters[:ssl_cert]
23
+ context.key = parameters[:ssl_key]
24
+ else
25
+ context.cert, context.key = self.class.self_cert
26
+ end
27
+ context.cert_store = OpenSSL::X509::Store.new
28
+ context.cert_store.set_default_paths
29
+ @ssl_socket = OpenSSL::SSL::SSLSocket.new(soc, context)
30
+ @ssl_socket.sync_close = true
31
+ @socket = soc
32
+ @ssl_socket.accept
33
+ super
34
+ end
35
+ # identification markers
36
+
37
+ #returns the service type - set to normal
38
+ def service_type
39
+ 'encrypted'
40
+ end
41
+ #returns true if the service is encrypted using the OpenSSL library.
42
+ def ssl?
43
+ true
44
+ end
45
+
46
+ # returns an IO-like object used for reading/writing (unlike the original IO object, this can be an SSL layer or any other wrapper object).
47
+ def io
48
+ touch
49
+ @ssl_socket
50
+ end
51
+
52
+ # reads from the connection
53
+ def read size = 1048576
54
+ data = ''
55
+ begin
56
+ loop { data << ssl_socket.read_nonblock( size) }
57
+ rescue Exception => e
58
+
59
+ end
60
+ touch unless data.empty?
61
+ data
62
+ end
63
+
64
+ protected
65
+
66
+ #sends data over the connection
67
+ def _send data
68
+ ssl_socket.write data
69
+ end
70
+
71
+ #closes the connection
72
+ def _close
73
+ ssl_socket.flush rescue true
74
+ ssl_socket.close
75
+ end
76
+
77
+ # checks if the connection is closed
78
+ def _disconnected?
79
+ ssl_socket.closed? || ssl_socket.io.closed? rescue true # || ssl_socket.io.stat.mode == 0140222 <= if mode is read only, it's the same as closed.
80
+ end
81
+
82
+
83
+ # SSL certificate
84
+
85
+ # returns the current self-signed certificate - or creates a new one, if there is no current certificate.
86
+ def self.self_cert bits=2048, cn=nil, comment='a self signed certificate for when we only need encryption and no more.'
87
+ @@self_cert ||= create_cert
88
+ return *@@self_cert
89
+ end
90
+ #creates a self-signed certificate
91
+ def self.create_cert bits=2048, cn=nil, comment='a self signed certificate for when we only need encryption and no more.'
92
+ unless cn
93
+ host_name = Socket::gethostbyname(Socket::gethostname)[0].split('.')
94
+ cn = ''
95
+ host_name.each {|n| cn << "/DC=#{n}"}
96
+ cn << "/CN=#{host_name.join('.')}"
97
+ end
98
+ # cn ||= "CN=#{Socket::gethostbyname(Socket::gethostname)[0] rescue Socket::gethostname}"
99
+
100
+ rsa = OpenSSL::PKey::RSA.new(bits)
101
+ cert = OpenSSL::X509::Certificate.new
102
+ cert.version = 2
103
+ cert.serial = 1
104
+ name = OpenSSL::X509::Name.parse(cn)
105
+ cert.subject = name
106
+ cert.issuer = name
107
+ cert.not_before = Time.now
108
+ cert.not_after = Time.now + (365*24*60*60)
109
+ cert.public_key = rsa.public_key
110
+
111
+ ef = OpenSSL::X509::ExtensionFactory.new(nil,cert)
112
+ ef.issuer_certificate = cert
113
+ cert.extensions = [
114
+ ef.create_extension("basicConstraints","CA:FALSE"),
115
+ ef.create_extension("keyUsage", "keyEncipherment"),
116
+ ef.create_extension("subjectKeyIdentifier", "hash"),
117
+ ef.create_extension("extendedKeyUsage", "serverAuth"),
118
+ ef.create_extension("nsComment", comment),
119
+ ]
120
+ aki = ef.create_extension("authorityKeyIdentifier",
121
+ "keyid:always,issuer:always")
122
+ cert.add_extension(aki)
123
+ cert.sign(rsa, OpenSSL::Digest::SHA1.new)
124
+
125
+ return cert, rsa
126
+ end
127
+
128
+ # def self.cert_test
129
+ # #Creating a CA
130
+ # root_key = OpenSSL::PKey::RSA.new 2048 # the CA's public/private key
131
+ # root_ca = OpenSSL::X509::Certificate.new
132
+ # root_ca.version = 2 # cf. RFC 5280 - to make it a "v3" certificate
133
+ # root_ca.serial = 1
134
+ # root_ca.subject = OpenSSL::X509::Name.parse "/DC=org/DC=ruby-lang/CN=Ruby CA"
135
+ # root_ca.issuer = root_ca.subject # root CA's are "self-signed"
136
+ # root_ca.public_key = root_key.public_key
137
+ # root_ca.not_before = Time.now
138
+ # root_ca.not_after = root_ca.not_before + 2 * 365 * 24 * 60 * 60 # 2 years validity
139
+ # ef = OpenSSL::X509::ExtensionFactory.new
140
+ # ef.subject_certificate = root_ca
141
+ # ef.issuer_certificate = root_ca
142
+ # root_ca.add_extension(ef.create_extension("basicConstraints","CA:TRUE",true))
143
+ # root_ca.add_extension(ef.create_extension("keyUsage","keyCertSign, cRLSign", true))
144
+ # root_ca.add_extension(ef.create_extension("subjectKeyIdentifier","hash",false))
145
+ # root_ca.add_extension(ef.create_extension("authorityKeyIdentifier","keyid:always",false))
146
+ # root_ca.sign(root_key, OpenSSL::Digest::SHA256.new)
147
+ # #Creating an End-Point Certificate
148
+ # key = OpenSSL::PKey::RSA.new 2048
149
+ # cert = OpenSSL::X509::Certificate.new
150
+ # cert.version = 2
151
+ # cert.serial = 2
152
+ # cert.subject = OpenSSL::X509::Name.parse "/DC=org/DC=ruby-lang/CN=Ruby certificate"
153
+ # cert.issuer = root_ca.subject # root CA is the issuer
154
+ # cert.public_key = key.public_key
155
+ # cert.not_before = Time.now
156
+ # cert.not_after = cert.not_before + 1 * 365 * 24 * 60 * 60 # 1 years validity
157
+ # ef = OpenSSL::X509::ExtensionFactory.new
158
+ # ef.subject_certificate = cert
159
+ # ef.issuer_certificate = root_ca
160
+ # cert.add_extension extension_factory.create_extension('keyUsage', 'keyEncipherment,dataEncipherment,digitalSignature')
161
+ # cert.add_extension(ef.create_extension("subjectKeyIdentifier","hash",false))
162
+ # cert.sign(root_key, OpenSSL::Digest::SHA256.new)
163
+
164
+ # # #Creating a Certificate
165
+ # # name = OpenSSL::X509::Name.parse 'CN=localhost/DC=localhost'
166
+ # # cert = OpenSSL::X509::Certificate.new
167
+ # # cert.version = 2
168
+ # # cert.serial = 0
169
+ # # cert.not_before = Time.now
170
+ # # cert.not_after = Time.now + 3600
171
+ # # key = OpenSSL::PKey::RSA.new 2048
172
+ # # cert.public_key = key.public_key
173
+ # # cert.subject = name
174
+
175
+ # # # Certificate Extensions
176
+ # # cert.add_extension extension_factory.create_extension('basicConstraints', 'CA:FALSE', true)
177
+ # # cert.add_extension extension_factory.create_extension('keyUsage', 'keyEncipherment,dataEncipherment,digitalSignature')
178
+ # # cert.add_extension extension_factory.create_extension('subjectKeyIdentifier', 'hash')
179
+
180
+ # # # Signing a Certificate
181
+ # # cert.issuer = name
182
+ # # cert.sign key, OpenSSL::Digest::SHA1.new
183
+
184
+ # #server
185
+ # context = OpenSSL::SSL::SSLContext.new
186
+ # context.cert = cert
187
+ # context.key = key
188
+ # tcp_server = TCPServer.new 8080
189
+ # ssl_server = OpenSSL::SSL::SSLServer.new tcp_server, context
190
+ # ssl_socket = ssl_server.accept
191
+ # end
192
+ end
193
+ end
@@ -0,0 +1,3 @@
1
+ module Plezi
2
+ VERSION = "0.7.0"
3
+ end
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'plezi/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "plezi"
8
+ spec.version = Plezi::VERSION
9
+ spec.authors = ["Boaz Segev"]
10
+ spec.email = ['boaz@2be.co.il']
11
+ spec.summary = %q{The Ruby Websocket Framework with RESTful and HTTP streaming support.}
12
+ spec.description = %q{Plezi is The Ruby Websocket and HTTP streaming Framework. Advance to next step in Ruby evolution - a framework with an integrated server, ready for seamless WebSockets and RESTful applications.}
13
+ spec.homepage = "http://boazsegev.github.io/plezi/"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.7"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+
24
+ spec.post_install_message = "Plezi is hungry - feed it your code!"
25
+
26
+ end
@@ -0,0 +1,68 @@
1
+ <!DOCTYPE html>
2
+ <head>
3
+ <style>
4
+ body, html
5
+ {
6
+ background-color: #eee;
7
+ padding: 0; margin: 0;
8
+ width: 100%;
9
+ }
10
+ h1
11
+ {
12
+ background-color: #ddd;
13
+ color: #008;
14
+ text-align: center;
15
+ border-bottom: 1px solid #000;
16
+ margin: 0;
17
+ padding: 0.5em;
18
+ width: auto;
19
+ }
20
+ p
21
+ {
22
+ color:#004;
23
+ font-size: 1.2em;
24
+ padding: 0 1em;
25
+ }
26
+ #wrapper
27
+ {
28
+ background-color: #fff;
29
+ margin: 1em 5%;
30
+ padding: 0 0 2% 0;
31
+ border-radius: 20px;
32
+ min-height: 50%;
33
+ color: #007;
34
+ }
35
+ #wrapper h2
36
+ {
37
+ background-color: #ddd;
38
+ color: #008;
39
+ text-align: center;
40
+ margin: 0 0 1em 0;
41
+ padding: 0.5em 0;
42
+ width: 100%;
43
+ border-radius: 20px;
44
+ }
45
+ #wrapper p{ padding: 0 2%;}
46
+ #wrapper #missing
47
+ {
48
+ color:#904;
49
+ font-size: 1.4em;
50
+ padding: 0.5em 0;
51
+ text-align: center;
52
+ background-color: #fee;
53
+ border-bottom: 1px solid #800;
54
+ margin: 0;
55
+ }
56
+ </style>
57
+ </head>
58
+ <body>
59
+ <h1>Plezi 404 error code (missing, not broken)...</h1>
60
+ <div id='wrapper'>
61
+ <h2 id='missing'>
62
+ couldn't find
63
+ <%= defined?(request) ? request.path : "what you're looking for..." %>
64
+ </h2>
65
+ <p>Sorry, we couldn't find what you're looking for...</p>
66
+ <p>... but we can always bring you something nice from another location, right?</p>
67
+ </div>
68
+ </body>
@@ -0,0 +1,64 @@
1
+ !!!5
2
+ %head
3
+ :css
4
+ body, html
5
+ {
6
+ background-color: #eee;
7
+ padding: 0; margin: 0;
8
+ width: 100%;
9
+ }
10
+ h1
11
+ {
12
+ background-color: #ddd;
13
+ color: #008;
14
+ text-align: center;
15
+ border-bottom: 1px solid #000;
16
+ margin: 0;
17
+ padding: 0.5em;
18
+ width: auto;
19
+ }
20
+ p
21
+ {
22
+ color:#004;
23
+ font-size: 1.2em;
24
+ padding: 0 1em;
25
+ }
26
+ #wrapper
27
+ {
28
+ background-color: #fff;
29
+ margin: 1em 5%;
30
+ padding: 0 0 2% 0;
31
+ border-radius: 20px;
32
+ min-height: 50%;
33
+ color: #007;
34
+ }
35
+ #wrapper h2
36
+ {
37
+ background-color: #ddd;
38
+ color: #008;
39
+ text-align: center;
40
+ margin: 0 0 1em 0;
41
+ padding: 0.5em 0;
42
+ width: 100%;
43
+ border-radius: 20px;
44
+ }
45
+ #wrapper p{ padding: 0 2%;}
46
+ #wrapper #missing
47
+ {
48
+ color:#904;
49
+ font-size: 1.4em;
50
+ padding: 0.5em 0;
51
+ text-align: center;
52
+ background-color: #fee;
53
+ border-bottom: 1px solid #800;
54
+ margin: 0;
55
+ }
56
+ %body
57
+ %h1< Plezi 404 error code (missing, not broken)...
58
+ #wrapper
59
+ %h2#missing
60
+ couldn't find
61
+ = defined?(request) ? request.path : "what you're looking for..."
62
+ %p Sorry, we couldn't find what you're looking for...
63
+ %p ... but we can always bring you something nice from another location, right?
64
+ / want to use your layout? use the :haml_concat method to wrap the 404 error code message. see http://haml.info/docs/yardoc/Haml/Helpers.html#haml_concat-instance_method .
@@ -0,0 +1,67 @@
1
+ <!DOCTYPE html>
2
+ <head>
3
+ <style>
4
+ body, html
5
+ {
6
+ background-color: #eee;
7
+ padding: 0; margin: 0;
8
+ width: 100%;
9
+ }
10
+ h1
11
+ {
12
+ background-color: #ddd;
13
+ color: #008;
14
+ text-align: center;
15
+ border-bottom: 1px solid #000;
16
+ margin: 0;
17
+ padding: 0.5em;
18
+ width: 100%;
19
+ }
20
+ p
21
+ {
22
+ color:#004;
23
+ font-size: 1.2em;
24
+ padding: 0 1em;
25
+ }
26
+ #wrapper
27
+ {
28
+ background-color: #fff;
29
+ margin: 1em 5%;
30
+ padding: 0 0 2%;
31
+ border-radius: 20px;
32
+ height: auto;
33
+ color: #007;
34
+ }
35
+ #wrapper h2
36
+ {
37
+ background-color: #ddd;
38
+ color: #008;
39
+ text-align: center;
40
+ margin: 0 0 1em 0;
41
+ padding: 0.5em 0;
42
+ width: 100%;
43
+ border-radius: 20px;
44
+ }
45
+ #wrapper p{ padding: 0 2%;}
46
+ #wrapper #missing
47
+ {
48
+ color:#904;
49
+ font-size: 1.4em;
50
+ padding: 0.5em 0;
51
+ text-align: center;
52
+ background-color: #fee;
53
+ border-bottom: 1px solid #800;
54
+ margin: 0;
55
+ }
56
+ </style>
57
+ </head>
58
+ <body>
59
+ <h1>Plezi 404 error code (missing, not broken)...</h1>
60
+ <div id='wrapper'>
61
+ <h2 id='missing'>
62
+ couldn't find your request...
63
+ </h2>
64
+ <p>Sorry, we couldn't find what you're looking for...</p>
65
+ <p>... but we can always bring you something nice from another location, right?</p>
66
+ </div>
67
+ </body>
@@ -0,0 +1,63 @@
1
+ doctype html
2
+ head
3
+ css:
4
+ body, html
5
+ {
6
+ background-color: #eee;
7
+ padding: 0; margin: 0;
8
+ width: 100%;
9
+ }
10
+ h1
11
+ {
12
+ background-color: #ddd;
13
+ color: #008;
14
+ text-align: center;
15
+ border-bottom: 1px solid #000;
16
+ margin: 0;
17
+ padding: 0.5em;
18
+ width: auto;
19
+ }
20
+ p
21
+ {
22
+ color:#004;
23
+ font-size: 1.2em;
24
+ padding: 0 1em;
25
+ }
26
+ #wrapper
27
+ {
28
+ background-color: #fff;
29
+ margin: 1em 5%;
30
+ padding: 0 0 2% 0;
31
+ border-radius: 20px;
32
+ min-height: 50%;
33
+ color: #007;
34
+ }
35
+ #wrapper h2
36
+ {
37
+ background-color: #ddd;
38
+ color: #008;
39
+ text-align: center;
40
+ margin: 0 0 1em 0;
41
+ padding: 0.5em 0;
42
+ width: 100%;
43
+ border-radius: 20px;
44
+ }
45
+ #wrapper p { padding: 0 2%; }
46
+ #wrapper #missing
47
+ {
48
+ color:#904;
49
+ font-size: 1.4em;
50
+ padding: 0.5em 0;
51
+ text-align: center;
52
+ background-color: #fee;
53
+ border-bottom: 1px solid #800;
54
+ margin: 0;
55
+ }
56
+ body
57
+ h1 Plezi 404 error code (missing, not broken)...
58
+ #wrapper
59
+ h2#missing
60
+ | couldn't find
61
+ =< defined?(request) ? request.path : "what you're looking for..."
62
+ p Sorry, we couldn't find what you're looking for...
63
+ p ... but we can always bring you something nice from another location, right?