knjappserver 0.0.16 → 0.0.17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. data/VERSION +1 -1
  2. data/bin/knjappserver_start.rb +17 -25
  3. data/knjappserver.gemspec +17 -6
  4. data/lib/conf/conf_example.rb +3 -3
  5. data/lib/files/database_schema.rb +1 -2
  6. data/lib/include/class_customio.rb +8 -25
  7. data/lib/include/class_erbhandler.rb +7 -1
  8. data/lib/include/class_httpserver.rb +50 -34
  9. data/lib/include/class_httpsession.rb +138 -101
  10. data/lib/include/class_httpsession_contentgroup.rb +52 -24
  11. data/lib/include/class_httpsession_http_request.rb +203 -0
  12. data/lib/include/{class_httpresp.rb → class_httpsession_http_response.rb} +27 -28
  13. data/lib/include/class_httpsession_post_multipart.rb +117 -0
  14. data/lib/include/class_knjappserver.rb +146 -96
  15. data/lib/include/class_knjappserver_cleaner.rb +74 -68
  16. data/lib/include/class_knjappserver_cmdline.rb +23 -17
  17. data/lib/include/class_knjappserver_errors.rb +121 -104
  18. data/lib/include/class_knjappserver_leakproxy_client.rb +6 -0
  19. data/lib/include/class_knjappserver_leakproxy_server.rb +56 -0
  20. data/lib/include/class_knjappserver_logging.rb +25 -25
  21. data/lib/include/class_knjappserver_mailing.rb +84 -56
  22. data/lib/include/class_knjappserver_sessions.rb +15 -22
  23. data/lib/include/class_knjappserver_threadding.rb +70 -43
  24. data/lib/include/class_knjappserver_threadding_timeout.rb +20 -4
  25. data/lib/include/class_knjappserver_translations.rb +6 -4
  26. data/lib/include/class_knjappserver_web.rb +87 -35
  27. data/lib/include/class_log.rb +9 -9
  28. data/lib/include/class_log_link.rb +4 -4
  29. data/lib/include/class_session.rb +8 -4
  30. data/lib/include/gettext_funcs.rb +8 -6
  31. data/lib/include/magic_methods.rb +4 -0
  32. data/lib/pages/debug_database_connections.rhtml +46 -0
  33. data/lib/pages/debug_http_sessions.rhtml +40 -0
  34. data/lib/pages/error_notfound.rhtml +12 -0
  35. data/lib/pages/spec.rhtml +1 -1
  36. data/lib/pages/spec_post.rhtml +3 -0
  37. data/lib/pages/spec_thread_joins.rhtml +21 -0
  38. data/lib/pages/spec_threadded_content.rhtml +2 -0
  39. data/lib/pages/tests.rhtml +14 -0
  40. data/lib/scripts/benchmark.rb +25 -8
  41. data/lib/scripts/knjappserver_cgi.rb +60 -0
  42. data/lib/scripts/knjappserver_fcgi.rb +135 -0
  43. data/lib/scripts/leakproxy.rb +27 -0
  44. data/spec/knjappserver_spec.rb +16 -5
  45. data/spec/leakproxy_spec.rb +56 -0
  46. metadata +38 -27
  47. data/lib/include/class_httpsession_knjengine.rb +0 -154
  48. data/lib/include/class_httpsession_mongrel.rb +0 -75
  49. data/lib/include/class_httpsession_webrick.rb +0 -75
@@ -19,7 +19,7 @@
19
19
  end
20
20
 
21
21
  if _get["choice"] == "get_cookies"
22
- print Knj::Php.json_encode(_cookie)
22
+ print JSON.generate(_cookie)
23
23
  exit
24
24
  end
25
25
 
@@ -0,0 +1,3 @@
1
+ <%
2
+ print _post["test"]
3
+ %>
@@ -0,0 +1,21 @@
1
+ <%
2
+ print "1"
3
+
4
+ cont = "2"
5
+ t1 = _kas.thread do
6
+ sleep 0.5
7
+ cont << "4"
8
+ end
9
+
10
+ t2 = _kas.thread do
11
+ sleep 0.1
12
+ cont << "3"
13
+ end
14
+
15
+ t1.join
16
+ t2.join_error
17
+
18
+ cont << "5"
19
+
20
+ print cont
21
+ %>
@@ -30,7 +30,9 @@
30
30
  print "8"
31
31
  end
32
32
 
33
+ #This will first finish after the printing has starter - it should still be printed correct.
33
34
  _kas.threadded_content do
35
+ sleep 1
34
36
  print "9"
35
37
  end
36
38
 
@@ -0,0 +1,14 @@
1
+ <%
2
+ print "Test 1: #{_testvar1}<br />\n"
3
+ print "Test 2: #{_testvar2}<br />\n"
4
+ %>
5
+
6
+ <table style="width: 1000px;">
7
+ <%
8
+ print Knj::Web.inputs([{
9
+ :title => "FCKEditor test",
10
+ :type => :fckeditor,
11
+ :name => :textest
12
+ }])
13
+ %>
14
+ </table>
@@ -1,12 +1,9 @@
1
1
  #!/usr/bin/env ruby1.9.1
2
2
 
3
3
  Dir.chdir(File.dirname(__FILE__))
4
- require "rubygems"
5
- require "../knjappserver.rb"
6
- require "knjrbfw"
7
- require "erubis"
4
+
5
+ require "optparse"
8
6
  require "sqlite3" if RUBY_ENGINE != "jruby"
9
- require "knj/autoload"
10
7
 
11
8
  begin
12
9
  args = {
@@ -19,12 +16,16 @@ begin
19
16
  opts.on("-f FILENAME", "--file FILENAME", "The filename that should be requested from the server.") do |t|
20
17
  args[:filename] = t
21
18
  end
19
+
20
+ opts.on("-k PATH", "--knjrbfw PATH", "The path of knjrbfw if it should not be loaded from gems.") do |path|
21
+ args[:knjrbfw_path] = path
22
+ end
22
23
  end.parse!
23
24
  end
24
25
 
25
26
  db_path = "#{File.dirname(__FILE__)}/benchmark_db.sqlite3"
26
27
 
27
- appsrv = Knjappserver.new(
28
+ appserver_args = {
28
29
  :debug => false,
29
30
  :port => 15081,
30
31
  :doc_root => "#{File.dirname(__FILE__)}/../pages",
@@ -33,11 +34,26 @@ appsrv = Knjappserver.new(
33
34
  :path => db_path,
34
35
  :return_keys => "symbols"
35
36
  }
36
- )
37
+ }
38
+
39
+ require "rubygems"
40
+ require "erubis"
41
+ require "#{args[:knjrbfw_path]}/knjrbfw.rb"
42
+ require "../knjappserver.rb"
43
+
44
+ if args[:knjrbfw_path]
45
+ appserver_args[:knjrbfw_path] = args[:knjrbfw_path]
46
+ else
47
+ require "knjrbfw"
48
+ end
49
+
50
+ require "knj/autoload"
51
+
52
+ appsrv = Knjappserver.new(appserver_args)
37
53
  appsrv.start
38
54
 
39
55
  count_requests = 0
40
- 1.upto(100) do |count_thread|
56
+ 1.upto(50) do |count_thread|
41
57
  Knj::Thread.new(count_thread) do |count_thread|
42
58
  print "Thread #{count_thread} started.\n"
43
59
 
@@ -51,6 +67,7 @@ count_requests = 0
51
67
  loop do
52
68
  resp = http.get(args[:filename])
53
69
  count_requests += 1
70
+ raise "Invalid code: #{resp.code}\n" if resp.code.to_i != 200
54
71
  end
55
72
  end
56
73
  end
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env ruby1.9.1
2
+
3
+ time_begin = Time.now
4
+
5
+ #This scripts start an appserver, executes a HTTP-request and terminates.
6
+ #Good for programming appserver-supported projects without running an appserver all the time,
7
+ #but really slow because of startup for every request.
8
+
9
+ begin
10
+ require "knj/autoload"
11
+ require "#{File.dirname(Knj::Os.realpath(__FILE__))}/../knjappserver.rb"
12
+
13
+ raise "No HTTP_KNJAPPSERVER_CGI_CONFIG-header was given." if !ENV["HTTP_KNJAPPSERVER_CGI_CONFIG"]
14
+ require ENV["HTTP_KNJAPPSERVER_CGI_CONFIG"]
15
+
16
+ begin
17
+ conf = Knjappserver::CGI_CONF
18
+ rescue NameError
19
+ raise "No 'Knjappserver::CGI_CONF'-constant was spawned by '#{ENV["HTTP_KNJAPPSERVER_CGI_CONFIG"]}'."
20
+ end
21
+
22
+
23
+ headers = {}
24
+ ENV.each do |key, val|
25
+ if key[0, 5] == "HTTP_" and key != "HTTP_KNJAPPSERVER_CGI_CONFIG"
26
+ key = Knj::Php.ucwords(key[5, key.length].gsub("_", " ")).gsub(" ", "-")
27
+ headers[key] = val
28
+ end
29
+ end
30
+
31
+ knjappserver_conf = Knjappserver::CGI_CONF["knjappserver"].merge(
32
+ :cmdline => false,
33
+ :events => false,
34
+ :cleaner => false,
35
+ :dbrev => false,
36
+ :mail_require => false,
37
+ :port => 0 #Ruby picks random port and we get the actual port after starting the appserver.
38
+ )
39
+ knjappserver = Knjappserver.new(knjappserver_conf)
40
+ knjappserver.start
41
+ port = knjappserver.port
42
+
43
+
44
+ #Make request.
45
+ http = Knj::Http2.new(:host => "localhost", :port => port)
46
+
47
+ count = 0
48
+ http.get(ENV["PATH_INFO"][1, ENV["PATH_INFO"].length], {
49
+ :default_headers => headers,
50
+ :cookies => false,
51
+ :on_content => proc{|line|
52
+ print line if count > 0
53
+ count += 1
54
+ }
55
+ })
56
+ rescue Exception => e
57
+ print "Content-Type: text/html\r\n"
58
+ print "\n\n"
59
+ print Knj::Errors.error_str(e, {:html => true})
60
+ end
@@ -0,0 +1,135 @@
1
+ #!/usr/bin/env ruby1.9.1
2
+
3
+ #This scripts start an appserver, executes a HTTP-request for every FCGI-request and terminates when FCGI terminates.
4
+ #Good for programming appserver-supported projects that doesnt need threadding without running an appserver all the time.
5
+
6
+ #It doesnt support shared threadding or objects because multiple instances in form of processes will be executed.
7
+
8
+ #Its a bit slower because it needs to flush writes to the database at end of every request and re-read them on spawn, because multiple instances might be present.
9
+
10
+ require "rubygems"
11
+ require "fcgi"
12
+
13
+ require "knj/autoload"
14
+ require "#{File.dirname(Knj::Os.realpath(__FILE__))}/../knjappserver.rb"
15
+
16
+ class Knjappserver
17
+ def self.fcgi_start(cgi)
18
+ raise "No HTTP_KNJAPPSERVER_CGI_CONFIG-header was given." if !cgi.env_table["HTTP_KNJAPPSERVER_CGI_CONFIG"]
19
+ require cgi.env_table["HTTP_KNJAPPSERVER_CGI_CONFIG"]
20
+
21
+ begin
22
+ conf = Knjappserver::CGI_CONF
23
+ rescue NameError
24
+ raise "No 'Knjappserver::CGI_CONF'-constant was spawned by '#{cgi.env_table["HTTP_KNJAPPSERVER_CGI_CONFIG"]}'."
25
+ end
26
+
27
+ knjappserver_conf = Knjappserver::CGI_CONF["knjappserver"]
28
+ knjappserver_conf.merge!(
29
+ :cmdline => false,
30
+ :port => 0 #Ruby picks random port and we get the actual port after starting the appserver.
31
+ )
32
+
33
+ knjappserver = Knjappserver.new(knjappserver_conf)
34
+ knjappserver.start
35
+
36
+ port = knjappserver.port
37
+ http = Knj::Http2.new(:host => "localhost", :port => port)
38
+
39
+ return [knjappserver, http]
40
+ end
41
+
42
+ def self.convert_fcgi_post(params)
43
+ post_hash = {}
44
+
45
+ params.each do |key, val|
46
+ post_hash[key] = val.first
47
+ end
48
+
49
+ return post_hash
50
+ end
51
+ end
52
+
53
+ knjappserver = nil
54
+ port = nil
55
+ http = nil
56
+ thread_spawn = nil
57
+ loadfp = "#{File.basename(__FILE__).slice(0..-6)}.rhtml"
58
+
59
+ FCGI.each_cgi do |cgi|
60
+ begin
61
+ $cgi = cgi
62
+
63
+ if !knjappserver
64
+ knjappserver, http = Knjappserver.fcgi_start(cgi)
65
+ end
66
+
67
+ thread_spawn.join if thread_spawn
68
+
69
+ #FCGI will keep resetting the stdout. Force it to appserver instead.
70
+ $stdout = knjappserver.cio
71
+
72
+ headers = {}
73
+ cgi.env_table.each do |key, val|
74
+ if key[0, 5] == "HTTP_" and key != "HTTP_KNJAPPSERVER_CGI_CONFIG"
75
+ key = Knj::Php.ucwords(key[5, key.length].gsub("_", " ")).gsub(" ", "-")
76
+ headers[key] = val
77
+ end
78
+ end
79
+
80
+ #Make request.
81
+ if cgi.env_table["PATH_INFO"].length > 0 and cgi.env_table["PATH_INFO"] != "/"
82
+ url = cgi.env_table["PATH_INFO"][1, cgi.env_table["PATH_INFO"].length]
83
+ else
84
+ url = "index.rhtml"
85
+ end
86
+
87
+ if cgi.env_table["QUERY_STRING"].to_s.length > 0
88
+ url << "?#{cgi.env_table["QUERY_STRING"]}"
89
+ end
90
+
91
+ #cgi.print "Content-Type: text/html\r\n"
92
+ #cgi.print "\r\n"
93
+ #cgi.print Knj::Php.print_r(cgi.params, true)
94
+
95
+ if cgi.request_method == "POST" and cgi.content_type.to_s.downcase.index("multipart/form-data") != nil
96
+ count = 0
97
+ http.post_multipart(url, Knjappserver.convert_fcgi_post(cgi.params), {
98
+ :default_headers => headers,
99
+ :cookies => false,
100
+ :on_content => proc{|line|
101
+ cgi.print(line) if count > 0
102
+ count += 1
103
+ }
104
+ })
105
+ elsif cgi.request_method == "POST"
106
+ count = 0
107
+ http.post(url, Knjappserver.convert_fcgi_post(cgi.params), {
108
+ :default_headers => headers,
109
+ :cookies => false,
110
+ :on_content => proc{|line|
111
+ cgi.print(line) if count > 0
112
+ count += 1
113
+ }
114
+ })
115
+ else
116
+ count = 0
117
+ http.get(url, {
118
+ :default_headers => headers,
119
+ :cookies => false,
120
+ :on_content => proc{|line|
121
+ cgi.print(line) if count > 0
122
+ count += 1
123
+ }
124
+ })
125
+ end
126
+
127
+ thread_spawn = Thread.new do
128
+ knjappserver.sessions_reset
129
+ end
130
+ rescue Exception => e
131
+ cgi.print "Content-Type: text/html\r\n"
132
+ cgi.print "\r\n"
133
+ cgi.print Knj::Errors.error_str(e, {:html => true})
134
+ end
135
+ end
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby1.9.1
2
+
3
+ data = Marshal.load($stdin.gets)
4
+
5
+ require "#{data[:knjrbfw_path]}knjrbfw"
6
+ require "#{File.dirname(__FILE__)}/../knjappserver.rb"
7
+ require "#{File.dirname(__FILE__)}/../include/class_knjappserver_leakproxy_client.rb"
8
+
9
+ require "#{$knjpath}/process"
10
+
11
+ process = Knj::Process.new(
12
+ :in => $stdin,
13
+ :out => $stdout,
14
+ :listen => true,
15
+ :on_rec => proc{|d|
16
+ d.answer("unknown command")
17
+ }
18
+ )
19
+
20
+
21
+
22
+ process.send(
23
+ "type" => "print",
24
+ "msg" => "Test?\n"
25
+ )
26
+
27
+ process.join
@@ -6,12 +6,13 @@ describe "Knjappserver" do
6
6
  require "knjappserver"
7
7
  require "knjrbfw"
8
8
  require "tmpdir"
9
+ require "knj/autoload"
9
10
 
10
11
  db_path = "#{Dir.tmpdir}/knjappserver_rspec.sqlite3"
11
12
  File.unlink(db_path) if File.exists?(db_path)
12
13
 
13
14
  require "knj/knjdb/libknjdb.rb"
14
- require "sqlite3" if RUBY_ENGINE != "jruby"
15
+ #require "sqlite3" if RUBY_ENGINE != "jruby"
15
16
 
16
17
  begin
17
18
  db = Knj::Db.new(
@@ -60,7 +61,7 @@ describe "Knjappserver" do
60
61
  raise "Unexpected HTML: '#{data["data"]}'." if data["data"].to_s != "Test"
61
62
 
62
63
  #Check that URL-decoding are being done.
63
- data = $http.get("/spec.rhtml?choice=check_get_parse&value=#{Knj::Php.urlencode("gfx/nopic.png")}")
64
+ data = $http.get("/spec.rhtml?choice=check_get_parse&value=#{Knj::Web.urlenc("gfx/nopic.png")}")
64
65
  raise "Unexpected HTML: '#{data["data"]}'." if data["data"].to_s != "gfx/nopic.png"
65
66
  end
66
67
 
@@ -94,13 +95,11 @@ describe "Knjappserver" do
94
95
  end
95
96
 
96
97
  it "should be able to set and get multiple cookies at the same time." do
97
- require "json"
98
-
99
98
  data = $http.get("/spec.rhtml?choice=test_cookie")
100
99
  raise data["data"] if data["data"].to_s.length > 0
101
100
 
102
101
  data = $http.get("/spec.rhtml?choice=get_cookies")
103
- parsed = Knj::Php.json_decode(data["data"])
102
+ parsed = JSON.parse(data["data"])
104
103
 
105
104
  raise "Unexpected value for 'TestCookie': '#{parsed["TestCookie"]}'." if parsed["TestCookie"] != "TestValue"
106
105
  raise "Unexpected value for 'TestCookie2': '#{parsed["TestCookie2"]}'." if parsed["TestCookie2"] != "TestValue2"
@@ -150,6 +149,18 @@ describe "Knjappserver" do
150
149
  end
151
150
  end
152
151
 
152
+ it "should be able to join threads tarted from _kas.thread." do
153
+ data = $http.get("/spec_thread_joins.rhtml")
154
+ raise data["data"] if data["data"].to_s != "12345"
155
+ end
156
+
157
+ it "should be able to properly parse special characters in post-requests." do
158
+ data = $http.post("/spec_post.rhtml", {
159
+ "test" => "123+456%789%20"
160
+ })
161
+ raise data["data"] if data["data"] != "123+456%789%20"
162
+ end
163
+
153
164
  it "should be able to stop." do
154
165
  $appserver.stop
155
166
  end
@@ -0,0 +1,56 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "Knjappserver" do
4
+ it "should be able to start a sample-server" do
5
+ require "rubygems"
6
+ require "knjappserver"
7
+ require "knjrbfw"
8
+ require "tmpdir"
9
+ require "knj/autoload"
10
+
11
+ db_path = "#{Dir.tmpdir}/knjappserver_rspec.sqlite3"
12
+ File.unlink(db_path) if File.exists?(db_path)
13
+
14
+ require "knj/knjdb/libknjdb.rb"
15
+ #require "sqlite3" if RUBY_ENGINE != "jruby"
16
+
17
+ begin
18
+ db = Knj::Db.new(
19
+ :type => "sqlite3",
20
+ :path => db_path,
21
+ :return_keys => "symbols"
22
+ )
23
+ rescue => e
24
+ STDOUT.puts e.inspect
25
+ STDOUT.puts e.backtrace
26
+
27
+ raise e
28
+ end
29
+
30
+ if RUBY_ENGINE == "jruby"
31
+ mail_require = false
32
+ else
33
+ mail_require = true
34
+ end
35
+
36
+ $appserver = Knjappserver.new(
37
+ :debug => false,
38
+ :autorestart => false,
39
+ :title => "SpecTest",
40
+ :port => 1515,
41
+ :doc_root => "#{File.dirname(__FILE__)}/../lib/pages",
42
+ :locales_gettext_funcs => true,
43
+ :locale_default => "da_DK",
44
+ :db => db,
45
+ :mail_require => mail_require,
46
+ :leakproxy => true
47
+ )
48
+
49
+ $appserver.start
50
+ $appserver.join
51
+ end
52
+
53
+ it "should be able to stop." do
54
+ $appserver.stop
55
+ end
56
+ end