knjappserver 0.0.15 → 0.0.16
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +4 -2
- data/Gemfile.lock +24 -10
- data/README.rdoc +298 -1
- data/VERSION +1 -1
- data/bin/check_running.rb +2 -2
- data/knjappserver.gemspec +23 -5
- data/lib/files/database_schema.rb +124 -111
- data/lib/include/class_customio.rb +19 -5
- data/lib/include/class_erbhandler.rb +5 -22
- data/lib/include/class_httpresp.rb +66 -28
- data/lib/include/class_httpserver.rb +27 -14
- data/lib/include/class_httpsession.rb +161 -212
- data/lib/include/class_httpsession_contentgroup.rb +144 -0
- data/lib/include/class_httpsession_knjengine.rb +33 -68
- data/lib/include/class_httpsession_mongrel.rb +1 -1
- data/lib/include/class_httpsession_webrick.rb +1 -1
- data/lib/include/class_knjappserver.rb +105 -130
- data/lib/include/class_knjappserver_cleaner.rb +20 -13
- data/lib/include/class_knjappserver_cmdline.rb +44 -0
- data/lib/include/class_knjappserver_errors.rb +4 -1
- data/lib/include/class_knjappserver_logging.rb +48 -8
- data/lib/include/class_knjappserver_mailing.rb +36 -14
- data/lib/include/class_knjappserver_sessions.rb +78 -0
- data/lib/include/class_knjappserver_threadding.rb +18 -45
- data/lib/include/class_knjappserver_threadding_timeout.rb +78 -0
- data/lib/include/class_knjappserver_translations.rb +30 -0
- data/lib/include/class_knjappserver_web.rb +55 -3
- data/lib/include/class_log.rb +31 -3
- data/lib/include/class_log_access.rb +0 -15
- data/lib/include/class_log_data.rb +0 -15
- data/lib/include/class_log_data_link.rb +1 -14
- data/lib/include/class_log_data_value.rb +5 -17
- data/lib/include/class_session.rb +6 -18
- data/lib/include/magic_methods.rb +12 -14
- data/lib/pages/benchmark.rhtml +0 -0
- data/lib/pages/benchmark_print.rhtml +14 -0
- data/lib/pages/benchmark_simple.rhtml +3 -0
- data/lib/pages/benchmark_threadded_content.rhtml +21 -0
- data/lib/pages/spec.rhtml +26 -0
- data/lib/pages/spec_test_multiple_clients.rhtml +3 -0
- data/lib/pages/spec_threadded_content.rhtml +38 -0
- data/lib/scripts/benchmark.rb +65 -0
- data/spec/knjappserver_spec.rb +87 -43
- metadata +54 -20
@@ -1,111 +1,124 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
}
|
1
|
+
class Knjappserver
|
2
|
+
DATABASE_SCHEMA = {
|
3
|
+
"tables" => {
|
4
|
+
"Log" => {
|
5
|
+
"columns" => [
|
6
|
+
{"name" => "id", "type" => "bigint", "autoincr" => true, "primarykey" => true},
|
7
|
+
{"name" => "text_value_id", "type" => "bigint"},
|
8
|
+
{"name" => "date_saved", "type" => "datetime"},
|
9
|
+
{"name" => "get_keys_data_id", "type" => "bigint"},
|
10
|
+
{"name" => "get_values_data_id", "type" => "bigint"},
|
11
|
+
{"name" => "post_keys_data_id", "type" => "bigint"},
|
12
|
+
{"name" => "post_values_data_id", "type" => "bigint"},
|
13
|
+
{"name" => "cookie_keys_data_id", "type" => "bigint"},
|
14
|
+
{"name" => "cookie_values_data_id", "type" => "bigint"},
|
15
|
+
{"name" => "meta_keys_data_id", "type" => "bigint"},
|
16
|
+
{"name" => "meta_values_data_id", "type" => "bigint"},
|
17
|
+
{"name" => "tag_data_id", "type" => "bigint"},
|
18
|
+
{"name" => "comment_data_id", "type" => "bigint"}
|
19
|
+
],
|
20
|
+
"indexes" => [
|
21
|
+
{"name" => "text_value_id", "columns" => ["text_value_id"]},
|
22
|
+
{"name" => "tag_data_id", "columns" => ["tag_data_id"]},
|
23
|
+
{"name" => "comment_data_id", "columns" => ["comment_data_id"]}
|
24
|
+
]
|
25
|
+
},
|
26
|
+
"Log_access" => {
|
27
|
+
"columns" => [
|
28
|
+
{"name" => "id", "type" => "bigint", "autoincr" => true, "primarykey" => true},
|
29
|
+
{"name" => "session_id", "type" => "bigint"},
|
30
|
+
{"name" => "date_request", "type" => "datetime"},
|
31
|
+
{"name" => "ip_data_id", "type" => "bigint"},
|
32
|
+
{"name" => "get_keys_data_id", "type" => "bigint"},
|
33
|
+
{"name" => "get_values_data_id", "type" => "bigint"},
|
34
|
+
{"name" => "post_keys_data_id", "type" => "bigint"},
|
35
|
+
{"name" => "post_values_data_id", "type" => "bigint"},
|
36
|
+
{"name" => "cookie_keys_data_id", "type" => "bigint"},
|
37
|
+
{"name" => "cookie_values_data_id", "type" => "bigint"},
|
38
|
+
{"name" => "meta_keys_data_id", "type" => "bigint"},
|
39
|
+
{"name" => "meta_values_data_id", "type" => "bigint"}
|
40
|
+
],
|
41
|
+
"indexes" => [
|
42
|
+
{"name" => "session_id", "columns" => ["session_id"]},
|
43
|
+
{"name" => "date_request", "columns" => ["date_request"]}
|
44
|
+
]
|
45
|
+
},
|
46
|
+
"Log_data" => {
|
47
|
+
"columns" => [
|
48
|
+
{"name" => "id", "type" => "bigint", "autoincr" => true, "primarykey" => true},
|
49
|
+
{"name" => "id_hash", "type" => "varchar"}
|
50
|
+
],
|
51
|
+
"indexes" => [
|
52
|
+
{"name" => "id_hash", "columns" => ["id_hash"]}
|
53
|
+
]
|
54
|
+
},
|
55
|
+
"Log_data_link" => {
|
56
|
+
"columns" => [
|
57
|
+
{"name" => "id", "type" => "bigint", "autoincr" => true, "primarykey" => true},
|
58
|
+
{"name" => "no", "type" => "int"},
|
59
|
+
{"name" => "data_id", "type" => "bigint"},
|
60
|
+
{"name" => "value_id", "type" => "bigint"}
|
61
|
+
],
|
62
|
+
"indexes" => [
|
63
|
+
{"name" => "data_id", "columns" => ["data_id"]},
|
64
|
+
{"name" => "value_id", "columns" => ["value_id"]}
|
65
|
+
]
|
66
|
+
},
|
67
|
+
"Log_data_value" => {
|
68
|
+
"columns" => [
|
69
|
+
{"name" => "id", "type" => "bigint", "autoincr" => true, "primarykey" => true},
|
70
|
+
{"name" => "value", "type" => "text"}
|
71
|
+
]
|
72
|
+
},
|
73
|
+
"Log_link" => {
|
74
|
+
"columns" => [
|
75
|
+
{"name" => "id", "type" => "bigint", "autoincr" => true, "primarykey" => true},
|
76
|
+
{"name" => "log_id", "type" => "bigint"},
|
77
|
+
{"name" => "object_class_value_id", "type" => "bigint"},
|
78
|
+
{"name" => "object_id", "type" => "bigint"}
|
79
|
+
],
|
80
|
+
"indexes" => [
|
81
|
+
{"name" => "log_id", "columns" => ["log_id"]},
|
82
|
+
{"name" => "object_id", "columns" => ["object_id"]},
|
83
|
+
{"name" => "object_class_value_id", "columns" => ["object_class_value_id"]},
|
84
|
+
{"name" => "object_lookup", "columns" => ["object_class_value_id", "object_id"]},
|
85
|
+
{"name" => "log_lookup", "columns" => ["object_class_value_id", "object_id", "log_id"]}
|
86
|
+
]
|
87
|
+
},
|
88
|
+
"Session" => {
|
89
|
+
"columns" => [
|
90
|
+
{"name" => "id", "type" => "bigint", "autoincr" => true, "primarykey" => true},
|
91
|
+
{"name" => "idhash", "type" => "varchar"},
|
92
|
+
{"name" => "sess_data", "type" => "text"},
|
93
|
+
{"name" => "date_added", "type" => "datetime"},
|
94
|
+
{"name" => "date_lastused", "type" => "datetime", "on_created" => proc{|d| d["db"].query("UPDATE Session SET date_lastused = '#{Knj::Datet.new.dbstr}")}},
|
95
|
+
{"name" => "ip", "type" => "varchar", "maxlength" => 15},
|
96
|
+
{"name" => "user_agent", "type" => "text"},
|
97
|
+
{"name" => "remember", "type" => "enum", "maxlength" => "'0','1'", "default" => 0, "comment" => "If the session should be remembered or not."}
|
98
|
+
],
|
99
|
+
"indexes" => [
|
100
|
+
{"name" => "date_added", "columns" => ["date_added"]},
|
101
|
+
{"name" => "idhash", "columns" => ["idhash"]}
|
102
|
+
],
|
103
|
+
"renames" => ["sessions"]
|
104
|
+
},
|
105
|
+
"Translation" => {
|
106
|
+
"columns" => [
|
107
|
+
{"name" => "id", "type" => "bigint", "autoincr" => true, "primarykey" => true},
|
108
|
+
{"name" => "object_class", "type" => "varchar", "maxlength" => 50},
|
109
|
+
{"name" => "object_id", "type" => "bigint"},
|
110
|
+
{"name" => "key", "type" => "varchar", "maxlength" => 50},
|
111
|
+
{"name" => "locale", "type" => "varchar", "maxlength" => 5},
|
112
|
+
{"name" => "value", "type" => "text"}
|
113
|
+
],
|
114
|
+
"indexes" => [
|
115
|
+
{"name" => "lookup", "columns" => ["object_class", "object_id", "key", "locale"]}
|
116
|
+
],
|
117
|
+
"indexes_remove" => {
|
118
|
+
"object_class" => true
|
119
|
+
},
|
120
|
+
"renames" => ["translations"]
|
121
|
+
}
|
122
|
+
}
|
123
|
+
}
|
124
|
+
end
|
@@ -1,13 +1,23 @@
|
|
1
1
|
class Knjappserver::CustomIO < StringIO
|
2
2
|
def print(str)
|
3
3
|
thread = Thread.current
|
4
|
+
str = str.to_s
|
4
5
|
|
5
|
-
if thread and thread[:knjappserver] and thread[:knjappserver][:
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
if thread and thread[:knjappserver] and thread[:knjappserver][:contentgroup]
|
7
|
+
httpsession = thread[:knjappserver][:httpsession]
|
8
|
+
|
9
|
+
if httpsession
|
10
|
+
wsize = httpsession.written_size
|
11
|
+
wsize += str.size
|
12
|
+
|
13
|
+
if wsize >= httpsession.size_send
|
14
|
+
httpsession.cgroup.write_output
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
thread[:knjappserver][:contentgroup].write(str)
|
9
19
|
else
|
10
|
-
|
20
|
+
STDOUT.print(str) if !STDOUT.closed?
|
11
21
|
end
|
12
22
|
end
|
13
23
|
|
@@ -18,4 +28,8 @@ class Knjappserver::CustomIO < StringIO
|
|
18
28
|
def write(str)
|
19
29
|
self.print(str)
|
20
30
|
end
|
31
|
+
|
32
|
+
def p(str)
|
33
|
+
self.print(str)
|
34
|
+
end
|
21
35
|
end
|
@@ -3,12 +3,10 @@ class Knjappserver::ERBHandler
|
|
3
3
|
@connected = {}
|
4
4
|
end
|
5
5
|
|
6
|
-
def erb_handler(
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
if !@connected[eruby.__id__]
|
6
|
+
def erb_handler(httpsess)
|
7
|
+
eruby = httpsess.eruby
|
8
|
+
|
9
|
+
if !@connected.key?(eruby.__id__)
|
12
10
|
eruby.connect("error") do |e|
|
13
11
|
_kas.handle_error(e)
|
14
12
|
end
|
@@ -16,21 +14,6 @@ class Knjappserver::ERBHandler
|
|
16
14
|
@connected[eruby.__id__] = true
|
17
15
|
end
|
18
16
|
|
19
|
-
|
20
|
-
:with_headers => false,
|
21
|
-
:custom_io => true
|
22
|
-
})
|
23
|
-
headers = eruby.headers
|
24
|
-
eruby.reset_headers
|
25
|
-
|
26
|
-
headers_ret = {}
|
27
|
-
headers.each do |header|
|
28
|
-
headers_ret[header[0]] = [header[1]]
|
29
|
-
end
|
30
|
-
|
31
|
-
Thread.current[:knjappserver].clear
|
32
|
-
Thread.current[:knjappserver] = nil
|
33
|
-
|
34
|
-
return {:headers => headers}
|
17
|
+
eruby.import(httpsess.page_path)
|
35
18
|
end
|
36
19
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require "time"
|
2
2
|
|
3
3
|
class Knjappserver::Httpresp
|
4
|
-
attr_accessor :
|
4
|
+
attr_accessor :nl, :status, :http_version, :headers, :headers_trailing, :headers_sent
|
5
5
|
|
6
6
|
STATUS_CODES = {
|
7
7
|
100 => "Continue",
|
@@ -24,20 +24,41 @@ class Knjappserver::Httpresp
|
|
24
24
|
}
|
25
25
|
NL = "\r\n"
|
26
26
|
|
27
|
-
def initialize
|
27
|
+
def initialize(args)
|
28
|
+
@cgroup = args[:cgroup]
|
29
|
+
end
|
30
|
+
|
31
|
+
def reset(args)
|
28
32
|
@status = 200
|
33
|
+
@http_version = args[:http_version]
|
34
|
+
@close = args[:close]
|
35
|
+
@fileobj = nil
|
36
|
+
@close = true if @http_version == "1.0"
|
37
|
+
@trailers = []
|
38
|
+
|
39
|
+
@headers_sent = false
|
40
|
+
@headers_trailing = {}
|
41
|
+
|
29
42
|
@headers = {
|
30
|
-
"
|
31
|
-
|
43
|
+
"date" => ["Date", Time.now.httpdate]
|
44
|
+
}
|
45
|
+
|
46
|
+
@headers_11 = {
|
32
47
|
"Connection" => "Keep-Alive",
|
33
48
|
"Transfer-Encoding" => "chunked",
|
34
|
-
"Keep-Alive" => "timeout=
|
49
|
+
"Keep-Alive" => "timeout=15, max=30"
|
35
50
|
}
|
51
|
+
|
36
52
|
@cookies = []
|
37
53
|
end
|
38
54
|
|
39
55
|
def header(key, val)
|
40
|
-
|
56
|
+
if !@headers_sent
|
57
|
+
@headers[key.to_s.downcase] = [key, val]
|
58
|
+
else
|
59
|
+
raise "Headers already sent and given header was not in trailing headers: '#{key}'." if @trailers.index(key) == nil
|
60
|
+
@headers_trailing[key.to_s.downcase] = [key, val]
|
61
|
+
end
|
41
62
|
end
|
42
63
|
|
43
64
|
def cookie(cookie)
|
@@ -45,18 +66,32 @@ class Knjappserver::Httpresp
|
|
45
66
|
end
|
46
67
|
|
47
68
|
def header_str
|
48
|
-
|
69
|
+
if @http_version == "1.0"
|
70
|
+
res = "HTTP/1.0 #{@status}"
|
71
|
+
else
|
72
|
+
res = "HTTP/1.1 #{@status}"
|
73
|
+
end
|
74
|
+
|
49
75
|
code = STATUS_CODES[@status]
|
50
76
|
res += " #{code}" if code
|
51
77
|
res += NL
|
52
|
-
#res += "Content-Length: #{@body.length}#{NL}"
|
53
78
|
|
54
79
|
@headers.each do |key, val|
|
55
|
-
res += "#{
|
80
|
+
res += "#{val[0]}: #{val[1]}#{NL}"
|
81
|
+
end
|
82
|
+
|
83
|
+
if @http_version == "1.1"
|
84
|
+
@headers_11.each do |key, val|
|
85
|
+
res += "#{key}: #{val}#{NL}"
|
86
|
+
end
|
87
|
+
|
88
|
+
@trailers.each do |trailer|
|
89
|
+
res += "Trailer: #{trailer}#{NL}"
|
90
|
+
end
|
56
91
|
end
|
57
92
|
|
58
93
|
@cookies.each do |cookie|
|
59
|
-
res += "Set-Cookie: #{cookie}#{NL}"
|
94
|
+
res += "Set-Cookie: #{Knj::Web.cookie_str(cookie)}#{NL}"
|
60
95
|
end
|
61
96
|
|
62
97
|
res += NL
|
@@ -64,28 +99,31 @@ class Knjappserver::Httpresp
|
|
64
99
|
return res
|
65
100
|
end
|
66
101
|
|
67
|
-
def
|
102
|
+
def write(socket)
|
103
|
+
@headers_sent = true
|
68
104
|
socket.write(self.header_str)
|
69
105
|
|
70
|
-
@
|
71
|
-
|
72
|
-
|
73
|
-
|
106
|
+
if @status == 304
|
107
|
+
#do nothing.
|
108
|
+
else
|
109
|
+
case @http_version
|
110
|
+
when "1.0"
|
111
|
+
@cgroup.write_to_socket
|
112
|
+
socket.write("#{NL}#{NL}")
|
113
|
+
when "1.1"
|
114
|
+
@cgroup.write_to_socket
|
115
|
+
socket.write("0#{NL}")
|
116
|
+
|
117
|
+
@headers_trailing.each do |header_id_str, header|
|
118
|
+
socket.write("#{header[0]}: #{header[1]}#{NL}")
|
119
|
+
end
|
120
|
+
|
121
|
+
socket.write(NL)
|
122
|
+
else
|
123
|
+
raise "Could not figure out of HTTP version: '#{@http_version}'."
|
74
124
|
end
|
75
125
|
end
|
76
126
|
|
77
|
-
socket.
|
78
|
-
end
|
79
|
-
|
80
|
-
def content
|
81
|
-
str = self.header_str + @body.string + "\n\n"
|
82
|
-
end
|
83
|
-
|
84
|
-
def destroy
|
85
|
-
@status = nil
|
86
|
-
@status_codes = nil
|
87
|
-
@body = nil
|
88
|
-
@cookies = nil
|
89
|
-
@headers = nil
|
127
|
+
socket.close if @close
|
90
128
|
end
|
91
129
|
end
|