knjappserver 0.0.16 → 0.0.17
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/bin/knjappserver_start.rb +17 -25
- data/knjappserver.gemspec +17 -6
- data/lib/conf/conf_example.rb +3 -3
- data/lib/files/database_schema.rb +1 -2
- data/lib/include/class_customio.rb +8 -25
- data/lib/include/class_erbhandler.rb +7 -1
- data/lib/include/class_httpserver.rb +50 -34
- data/lib/include/class_httpsession.rb +138 -101
- data/lib/include/class_httpsession_contentgroup.rb +52 -24
- data/lib/include/class_httpsession_http_request.rb +203 -0
- data/lib/include/{class_httpresp.rb → class_httpsession_http_response.rb} +27 -28
- data/lib/include/class_httpsession_post_multipart.rb +117 -0
- data/lib/include/class_knjappserver.rb +146 -96
- data/lib/include/class_knjappserver_cleaner.rb +74 -68
- data/lib/include/class_knjappserver_cmdline.rb +23 -17
- data/lib/include/class_knjappserver_errors.rb +121 -104
- data/lib/include/class_knjappserver_leakproxy_client.rb +6 -0
- data/lib/include/class_knjappserver_leakproxy_server.rb +56 -0
- data/lib/include/class_knjappserver_logging.rb +25 -25
- data/lib/include/class_knjappserver_mailing.rb +84 -56
- data/lib/include/class_knjappserver_sessions.rb +15 -22
- data/lib/include/class_knjappserver_threadding.rb +70 -43
- data/lib/include/class_knjappserver_threadding_timeout.rb +20 -4
- data/lib/include/class_knjappserver_translations.rb +6 -4
- data/lib/include/class_knjappserver_web.rb +87 -35
- data/lib/include/class_log.rb +9 -9
- data/lib/include/class_log_link.rb +4 -4
- data/lib/include/class_session.rb +8 -4
- data/lib/include/gettext_funcs.rb +8 -6
- data/lib/include/magic_methods.rb +4 -0
- data/lib/pages/debug_database_connections.rhtml +46 -0
- data/lib/pages/debug_http_sessions.rhtml +40 -0
- data/lib/pages/error_notfound.rhtml +12 -0
- data/lib/pages/spec.rhtml +1 -1
- data/lib/pages/spec_post.rhtml +3 -0
- data/lib/pages/spec_thread_joins.rhtml +21 -0
- data/lib/pages/spec_threadded_content.rhtml +2 -0
- data/lib/pages/tests.rhtml +14 -0
- data/lib/scripts/benchmark.rb +25 -8
- data/lib/scripts/knjappserver_cgi.rb +60 -0
- data/lib/scripts/knjappserver_fcgi.rb +135 -0
- data/lib/scripts/leakproxy.rb +27 -0
- data/spec/knjappserver_spec.rb +16 -5
- data/spec/leakproxy_spec.rb +56 -0
- metadata +38 -27
- data/lib/include/class_httpsession_knjengine.rb +0 -154
- data/lib/include/class_httpsession_mongrel.rb +0 -75
- data/lib/include/class_httpsession_webrick.rb +0 -75
data/lib/pages/spec.rhtml
CHANGED
data/lib/scripts/benchmark.rb
CHANGED
@@ -1,12 +1,9 @@
|
|
1
1
|
#!/usr/bin/env ruby1.9.1
|
2
2
|
|
3
3
|
Dir.chdir(File.dirname(__FILE__))
|
4
|
-
|
5
|
-
require "
|
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
|
-
|
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(
|
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
|
data/spec/knjappserver_spec.rb
CHANGED
@@ -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::
|
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 =
|
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
|