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