knjappserver 0.0.16 → 0.0.17

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.
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