knjappserver 0.0.15 → 0.0.16

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/Gemfile +4 -2
  2. data/Gemfile.lock +24 -10
  3. data/README.rdoc +298 -1
  4. data/VERSION +1 -1
  5. data/bin/check_running.rb +2 -2
  6. data/knjappserver.gemspec +23 -5
  7. data/lib/files/database_schema.rb +124 -111
  8. data/lib/include/class_customio.rb +19 -5
  9. data/lib/include/class_erbhandler.rb +5 -22
  10. data/lib/include/class_httpresp.rb +66 -28
  11. data/lib/include/class_httpserver.rb +27 -14
  12. data/lib/include/class_httpsession.rb +161 -212
  13. data/lib/include/class_httpsession_contentgroup.rb +144 -0
  14. data/lib/include/class_httpsession_knjengine.rb +33 -68
  15. data/lib/include/class_httpsession_mongrel.rb +1 -1
  16. data/lib/include/class_httpsession_webrick.rb +1 -1
  17. data/lib/include/class_knjappserver.rb +105 -130
  18. data/lib/include/class_knjappserver_cleaner.rb +20 -13
  19. data/lib/include/class_knjappserver_cmdline.rb +44 -0
  20. data/lib/include/class_knjappserver_errors.rb +4 -1
  21. data/lib/include/class_knjappserver_logging.rb +48 -8
  22. data/lib/include/class_knjappserver_mailing.rb +36 -14
  23. data/lib/include/class_knjappserver_sessions.rb +78 -0
  24. data/lib/include/class_knjappserver_threadding.rb +18 -45
  25. data/lib/include/class_knjappserver_threadding_timeout.rb +78 -0
  26. data/lib/include/class_knjappserver_translations.rb +30 -0
  27. data/lib/include/class_knjappserver_web.rb +55 -3
  28. data/lib/include/class_log.rb +31 -3
  29. data/lib/include/class_log_access.rb +0 -15
  30. data/lib/include/class_log_data.rb +0 -15
  31. data/lib/include/class_log_data_link.rb +1 -14
  32. data/lib/include/class_log_data_value.rb +5 -17
  33. data/lib/include/class_session.rb +6 -18
  34. data/lib/include/magic_methods.rb +12 -14
  35. data/lib/pages/benchmark.rhtml +0 -0
  36. data/lib/pages/benchmark_print.rhtml +14 -0
  37. data/lib/pages/benchmark_simple.rhtml +3 -0
  38. data/lib/pages/benchmark_threadded_content.rhtml +21 -0
  39. data/lib/pages/spec.rhtml +26 -0
  40. data/lib/pages/spec_test_multiple_clients.rhtml +3 -0
  41. data/lib/pages/spec_threadded_content.rhtml +38 -0
  42. data/lib/scripts/benchmark.rb +65 -0
  43. data/spec/knjappserver_spec.rb +87 -43
  44. metadata +54 -20
data/Gemfile CHANGED
@@ -3,9 +3,10 @@ source "http://rubygems.org"
3
3
  # Example:
4
4
  # gem "activesupport", ">= 2.3.5"
5
5
 
6
- gem "knjrbfw", ">= 0.0.7"
6
+ gem "knjrbfw", ">= 0.0.8"
7
7
  gem "erubis"
8
8
  gem "knjdbrevision", ">= 0.0.2"
9
+ gem "mail"
9
10
 
10
11
  # Add dependencies to develop your gem here.
11
12
  # Include everything needed to run rake, tests, features, etc.
@@ -14,5 +15,6 @@ group :development do
14
15
  gem "bundler", "~> 1.0.0"
15
16
  gem "jeweler", "~> 1.6.3"
16
17
  gem "rcov", ">= 0"
17
- gem "sqlite3"
18
+ gem "sqlite3" if RUBY_ENGINE != "jruby"
19
+ gem "json"
18
20
  end
data/Gemfile.lock CHANGED
@@ -1,19 +1,28 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
- diff-lcs (1.1.2)
4
+ diff-lcs (1.1.3)
5
5
  erubis (2.7.0)
6
6
  git (1.2.5)
7
- jeweler (1.6.3)
7
+ i18n (0.6.0)
8
+ jeweler (1.6.4)
8
9
  bundler (~> 1.0)
9
10
  git (>= 1.2.5)
10
11
  rake
11
- knjdbrevision (0.0.2)
12
- knjrbfw
13
- knjrbfw (0.0.7)
14
- rake (0.9.2)
15
- rcov (0.9.9)
16
- rcov (0.9.9-java)
12
+ json (1.6.1)
13
+ json (1.6.1-java)
14
+ knjdbrevision (0.0.3)
15
+ knjrbfw (>= 0.0.3)
16
+ knjrbfw (0.0.8)
17
+ mail (2.3.0)
18
+ i18n (>= 0.4.0)
19
+ mime-types (~> 1.16)
20
+ treetop (~> 1.4.8)
21
+ mime-types (1.17.2)
22
+ polyglot (0.3.2)
23
+ rake (0.9.2.2)
24
+ rcov (0.9.11)
25
+ rcov (0.9.11-java)
17
26
  rspec (2.3.0)
18
27
  rspec-core (~> 2.3.0)
19
28
  rspec-expectations (~> 2.3.0)
@@ -22,7 +31,10 @@ GEM
22
31
  rspec-expectations (2.3.0)
23
32
  diff-lcs (~> 1.1.2)
24
33
  rspec-mocks (2.3.0)
25
- sqlite3 (1.3.3)
34
+ sqlite3 (1.3.4)
35
+ treetop (1.4.10)
36
+ polyglot
37
+ polyglot (>= 0.3.1)
26
38
 
27
39
  PLATFORMS
28
40
  java
@@ -32,8 +44,10 @@ DEPENDENCIES
32
44
  bundler (~> 1.0.0)
33
45
  erubis
34
46
  jeweler (~> 1.6.3)
47
+ json
35
48
  knjdbrevision (>= 0.0.2)
36
- knjrbfw (>= 0.0.7)
49
+ knjrbfw (>= 0.0.8)
50
+ mail
37
51
  rcov
38
52
  rspec (~> 2.3.0)
39
53
  sqlite3
data/README.rdoc CHANGED
@@ -1,6 +1,9 @@
1
1
  = knjappserver
2
2
 
3
- Description goes here.
3
+ This is a multithreadded webserver that runs under Ruby 1.9.2 or JRuby. It runs under one single process and is able to handle multiple simultanious HTTP requests with thread-safety.
4
+
5
+ It uses ERubis to parse .rhtml files and caches the bytecode for Ruby-files.
6
+
4
7
 
5
8
  == Contributing to knjappserver
6
9
 
@@ -17,3 +20,297 @@ Description goes here.
17
20
  Copyright (c) 2011 Kasper Johansen. See LICENSE.txt for
18
21
  further details.
19
22
 
23
+ == Installing
24
+
25
+ gem install knjappserver
26
+
27
+
28
+ == Usage
29
+
30
+ === Basic example
31
+
32
+ Create a file called "start.rb":
33
+
34
+ require "rubygems"
35
+ require "knjappserver"
36
+
37
+ require "knjrbfw"
38
+ require "knj/knjdb/libknjdb.rb"
39
+ require "sqlite3"
40
+
41
+ appsrv = Knjappserver.new(
42
+ :port => 10080,
43
+ :doc_root => "#{File.dirname(__FILE__)}/doc_root",
44
+ :db => Knj::Db.new(
45
+ :type => "sqlite3",
46
+ :path => "#{File.dirname(__FILE__)}/test.sqlite3"
47
+ )
48
+ )
49
+ appsrv.update_db #creates missing tables, columns, indexes or other stuff it needs.
50
+ appsrv.start
51
+ appsrv.join
52
+
53
+
54
+ Place a file called "index.rhtml" with the start-script and write something like:
55
+
56
+ <%
57
+ print "Hello world."
58
+ %>
59
+
60
+
61
+ Then go to your browser and type "localhost:10080".
62
+
63
+
64
+ === How to send a header
65
+
66
+ <%
67
+ _kas.header("SomeHeader", "SomeValue")
68
+ %>
69
+
70
+ If you have trouble, because the server already began to send the content while the page was not fully generated, then you can increase the size for when it should begin sending content like this:
71
+
72
+ appsrv = Knjappserver.new(
73
+ ...
74
+ :send_size => 4096
75
+ ...
76
+ )
77
+
78
+ Or you can do it for just one page dynamically (this should be done VERY early - like before the first lines gets printed out):
79
+
80
+ <%
81
+ _kas.headers_send_size = 4096
82
+ %>
83
+
84
+ You can also test if the headers are sent for your HTTP-session or not like this:
85
+
86
+ <%
87
+ if _kas.headers_sent?
88
+ print "The headers are sent!"
89
+ else
90
+ print "The headers are not sent yet - we can still add headers!"
91
+ end
92
+ %>
93
+
94
+ === How to send set a cookie
95
+
96
+ <%
97
+ _kas.cookie(
98
+ "name" => "MyCookie",
99
+ "value" => "SomeValue",
100
+ "expires" => Time.new + 3600,
101
+ "path" => "/"
102
+ )
103
+ %>
104
+
105
+ === How to do threadded content
106
+
107
+ <%
108
+ _kas.threadded_content do
109
+ sleep 4
110
+ print "Test 1<br />"
111
+ end
112
+
113
+ _kas.threadded_content do
114
+ sleep 1
115
+ print "Test 2<br />"
116
+ end
117
+
118
+ _kas.threadded_content do
119
+ sleep 3
120
+ print "Test 3<br />"
121
+ end
122
+ %>
123
+
124
+ It should print in the right order, even though "Test 1" will finish as the last thread:
125
+ Test 1
126
+ Test 2
127
+ Test 3
128
+
129
+
130
+ === How to access request data
131
+ <%
132
+ puts _get
133
+ puts _post
134
+ puts _meta
135
+ puts _cookie
136
+ puts _session
137
+ puts _session_hash
138
+ %>
139
+
140
+
141
+ === How to set session variables:
142
+ _session[:logged_in] = true
143
+
144
+
145
+ === How to set other objects that cant be marshalled on sessions (variables will die after restart):
146
+ _session_hash[:mythread] = Thread.new do
147
+ do_some_stuff
148
+ end
149
+
150
+
151
+ === How to access the database
152
+ <%
153
+ _db.q("SELECT * FROM Session") do |data|
154
+ puts data
155
+ end
156
+ %>
157
+
158
+
159
+ === How to create a thread with database access that runs in background via the threadpool
160
+ <%
161
+ _kas.thread do
162
+ sleep 2
163
+ print "Trala!\n" #will be outputted to the command line, since the thread is being executed in the background and the http-request wont depend on it!
164
+ end
165
+ %>
166
+
167
+
168
+ === How to do execute something every 10 seconds.
169
+ <%
170
+ _kas.timeout(:time => 10) do
171
+ print "This will be printed to the command line every 10 secs.\n"
172
+ end
173
+ %>
174
+
175
+
176
+ === How to send a mail
177
+
178
+ 1. Be sure to start the appserver with SMTP arguments:
179
+ appsrv = Knjappserver.new(
180
+ ...
181
+ :smtp_paras => {
182
+ "smtp_host" => "hostname",
183
+ "smtp_port" => 465,
184
+ "smtp_user" => "username,
185
+ "smtp_passwd" => "password",
186
+ "ssl" => true
187
+ }
188
+ ...
189
+ )
190
+
191
+ 2. Do something like this:
192
+ <%
193
+ _kas.mail(
194
+ :to => "friends@email.com",
195
+ :subject => "The subject",
196
+ :html => "The HTML content.",
197
+ :from => "your@email.com"
198
+ )
199
+ %>
200
+
201
+ You can also make the appserver send you an email every time an error occurrs:
202
+ <%
203
+ appsrv = Knjappserver.new(
204
+ ...
205
+ :error_report_emails => ["your@email.com", "another@email.com"],
206
+ :error_report_from => "robot@domain.com"
207
+ ...
208
+ )
209
+ %>
210
+
211
+
212
+ === How to use Gettext / Locales
213
+
214
+ 1. Make folders and po-files so you have something like: "locales/en_GB/LC_MESSAGES/default.po".
215
+
216
+ 2. Start the appserver with the following arguments:
217
+ appsrv = Knjappserver.new(
218
+ ...
219
+ :locales_root => "#{File.dirname(__FILE__)}/../locales",
220
+ :locales_gettext_funcs => true,
221
+ :locale_default => "da_DK",
222
+ ...
223
+ )
224
+
225
+ 3. Use gettext like your normally would:
226
+ <%
227
+ print _("Hello world.")
228
+ %>
229
+
230
+ 4. Dont do "require 'gettext'" or anything like this - the appserver does it all for you!
231
+
232
+
233
+ === How to use multithreadded MySQL without mutex'ing around it.
234
+
235
+ 1. Install the 'mysql2' gem.
236
+ gem install mysql2
237
+
238
+ 2. Start the appserver with the following arguments:
239
+ appsrv = Knjappserver.new(
240
+ ...
241
+ :db => {
242
+ :type => "mysql",
243
+ :subtype => "mysql2",
244
+ :host => "localhost",
245
+ :user => "username",
246
+ :pass => "password",
247
+ :db => "database",
248
+ :return_keys => "symbols",
249
+ :threadsafe => true,
250
+ :encoding => "utf8",
251
+ :query_args => {:cast => false}
252
+ }
253
+ ...
254
+ )
255
+
256
+
257
+ === How to make a cron-script that checks if my app is running through the appserver.
258
+
259
+ 1. Be sure to start the appserver with a title:
260
+ appsrv = Knjappserver.new(
261
+ ...
262
+ :title => "MyApp"
263
+ ...
264
+ )
265
+
266
+ 2. Add this command to your cron-config:
267
+ /bin/bash -l -c "ruby ~/.rvm/gems/ruby-1.9.2-head/gems/knjappserver-0.0.9/bin/check_running.rb --title=MyApp --forking=1 --command=\"ruby /path/to/app/start_script.rb\""
268
+
269
+
270
+ === How to restart the appserver from Ruby or restart it based on memory usage.
271
+
272
+ 1. Be sure to start the appserver with a restart-command:
273
+ appsrv = Knjappserver.new(
274
+ ...
275
+ :restart_cmd => "/usr/bin/ruby1.9.1 /path/to/app/start.rb"
276
+ ...
277
+ )
278
+
279
+ 2. You can also make it restart itself based on memory usage:
280
+ appsrv = Knjappserver.new(
281
+ ...
282
+ :restart_when_used_memory => 384
283
+ ...
284
+ )
285
+
286
+ 3. You can restart it dynamically (or test that it is able to restart itself with your given arguments) by doing something like this:
287
+ <%
288
+ _kas.should_restart = true
289
+ %>
290
+
291
+ When it restarts it will wait for a window with no running HTTP requests before restarting.
292
+
293
+
294
+ === How to use helper methods.
295
+
296
+ 1. This will show a message by using javascript in execute history.back(-1) afterwards.
297
+ _kas.alert("You can only view this page if you are logged in.").back if !logged_in
298
+
299
+ 2. This will show the error message and execute history.back(-1) afterwards.
300
+ _kas.on_error_go_back do
301
+ raise "test"
302
+ end
303
+
304
+ 3. This will redirect the user and not execute anything after it:
305
+ _kas.redirect("?show=frontpage")
306
+
307
+ 4. We also add the method "html" to the String-class so escaping it is painless:
308
+ print "<b>Will this be bold?</b>".html
309
+
310
+ 5. This is how you can escape SQL-stuff:
311
+ data = _db.query("SELECT * FROM Session WHERE id ='#{_db.esc(some_var)}'").fetch
312
+
313
+ 6. Print strings using short-tag:
314
+ <div>
315
+ My name is <%=name_var%>.
316
+ </div>
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.15
1
+ 0.0.16
data/bin/check_running.rb CHANGED
@@ -58,8 +58,8 @@ tmppath = "#{tmpdir}/run_#{options[:title]}"
58
58
  count = 0
59
59
 
60
60
  if File.exists?(tmppath)
61
- pid = File.read(tmppath)
62
- count = Knj::Unix_proc.list("pids" => [pid]).length
61
+ pid = File.read(tmppath).to_s.strip
62
+ count = Knj::Unix_proc.list("pids" => [pid]).length if pid.to_s.length > 0
63
63
  end
64
64
 
65
65
  exit if count > 0
data/knjappserver.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{knjappserver}
8
- s.version = "0.0.15"
8
+ s.version = "0.0.16"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Kasper Johansen"]
12
- s.date = %q{2011-08-03}
12
+ s.date = %q{2011-11-15}
13
13
  s.description = %q{Which supports a lot of undocumented stuff.}
14
14
  s.email = %q{k@spernj.org}
15
15
  s.executables = ["check_running.rb", "knjappserver_start.rb"]
@@ -39,15 +39,20 @@ Gem::Specification.new do |s|
39
39
  "lib/include/class_httpresp.rb",
40
40
  "lib/include/class_httpserver.rb",
41
41
  "lib/include/class_httpsession.rb",
42
+ "lib/include/class_httpsession_contentgroup.rb",
42
43
  "lib/include/class_httpsession_knjengine.rb",
43
44
  "lib/include/class_httpsession_mongrel.rb",
44
45
  "lib/include/class_httpsession_webrick.rb",
45
46
  "lib/include/class_knjappserver.rb",
46
47
  "lib/include/class_knjappserver_cleaner.rb",
48
+ "lib/include/class_knjappserver_cmdline.rb",
47
49
  "lib/include/class_knjappserver_errors.rb",
48
50
  "lib/include/class_knjappserver_logging.rb",
49
51
  "lib/include/class_knjappserver_mailing.rb",
52
+ "lib/include/class_knjappserver_sessions.rb",
50
53
  "lib/include/class_knjappserver_threadding.rb",
54
+ "lib/include/class_knjappserver_threadding_timeout.rb",
55
+ "lib/include/class_knjappserver_translations.rb",
51
56
  "lib/include/class_knjappserver_web.rb",
52
57
  "lib/include/class_log.rb",
53
58
  "lib/include/class_log_access.rb",
@@ -59,9 +64,16 @@ Gem::Specification.new do |s|
59
64
  "lib/include/gettext_funcs.rb",
60
65
  "lib/include/magic_methods.rb",
61
66
  "lib/knjappserver.rb",
67
+ "lib/pages/benchmark.rhtml",
68
+ "lib/pages/benchmark_print.rhtml",
69
+ "lib/pages/benchmark_simple.rhtml",
70
+ "lib/pages/benchmark_threadded_content.rhtml",
62
71
  "lib/pages/logs_latest.rhtml",
63
72
  "lib/pages/logs_show.rhtml",
64
73
  "lib/pages/spec.rhtml",
74
+ "lib/pages/spec_test_multiple_clients.rhtml",
75
+ "lib/pages/spec_threadded_content.rhtml",
76
+ "lib/scripts/benchmark.rb",
65
77
  "spec/knjappserver_spec.rb",
66
78
  "spec/spec_helper.rb"
67
79
  ]
@@ -75,33 +87,39 @@ Gem::Specification.new do |s|
75
87
  s.specification_version = 3
76
88
 
77
89
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
78
- s.add_runtime_dependency(%q<knjrbfw>, [">= 0.0.7"])
90
+ s.add_runtime_dependency(%q<knjrbfw>, [">= 0.0.8"])
79
91
  s.add_runtime_dependency(%q<erubis>, [">= 0"])
80
92
  s.add_runtime_dependency(%q<knjdbrevision>, [">= 0.0.2"])
93
+ s.add_runtime_dependency(%q<mail>, [">= 0"])
81
94
  s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
82
95
  s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
83
96
  s.add_development_dependency(%q<jeweler>, ["~> 1.6.3"])
84
97
  s.add_development_dependency(%q<rcov>, [">= 0"])
85
98
  s.add_development_dependency(%q<sqlite3>, [">= 0"])
99
+ s.add_development_dependency(%q<json>, [">= 0"])
86
100
  else
87
- s.add_dependency(%q<knjrbfw>, [">= 0.0.7"])
101
+ s.add_dependency(%q<knjrbfw>, [">= 0.0.8"])
88
102
  s.add_dependency(%q<erubis>, [">= 0"])
89
103
  s.add_dependency(%q<knjdbrevision>, [">= 0.0.2"])
104
+ s.add_dependency(%q<mail>, [">= 0"])
90
105
  s.add_dependency(%q<rspec>, ["~> 2.3.0"])
91
106
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
92
107
  s.add_dependency(%q<jeweler>, ["~> 1.6.3"])
93
108
  s.add_dependency(%q<rcov>, [">= 0"])
94
109
  s.add_dependency(%q<sqlite3>, [">= 0"])
110
+ s.add_dependency(%q<json>, [">= 0"])
95
111
  end
96
112
  else
97
- s.add_dependency(%q<knjrbfw>, [">= 0.0.7"])
113
+ s.add_dependency(%q<knjrbfw>, [">= 0.0.8"])
98
114
  s.add_dependency(%q<erubis>, [">= 0"])
99
115
  s.add_dependency(%q<knjdbrevision>, [">= 0.0.2"])
116
+ s.add_dependency(%q<mail>, [">= 0"])
100
117
  s.add_dependency(%q<rspec>, ["~> 2.3.0"])
101
118
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
102
119
  s.add_dependency(%q<jeweler>, ["~> 1.6.3"])
103
120
  s.add_dependency(%q<rcov>, [">= 0"])
104
121
  s.add_dependency(%q<sqlite3>, [">= 0"])
122
+ s.add_dependency(%q<json>, [">= 0"])
105
123
  end
106
124
  end
107
125