bayserver-docker-cgi 2.2.0
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.
- checksums.yaml +7 -0
- data/lib/baykit/bayserver/docker/cgi/cgi_docker.rb +226 -0
- data/lib/baykit/bayserver/docker/cgi/cgi_message.rb +33 -0
- data/lib/baykit/bayserver/docker/cgi/cgi_req_content_handler.rb +136 -0
- data/lib/baykit/bayserver/docker/cgi/cgi_std_err_yacht.rb +81 -0
- data/lib/baykit/bayserver/docker/cgi/cgi_std_out_yacht.rb +158 -0
- data/lib/baykit/bayserver/docker/cgi/cgi_train.rb +182 -0
- data/lib/baykit/bayserver/docker/cgi/php_cgi_docker.rb +41 -0
- metadata +63 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 8c40b3461b0d48853cda84ce66339ccd38cb7c8df440545db4704bc977d7d222
|
4
|
+
data.tar.gz: 55fbb0b776f0f507ea2c992d42e763ee8b4be06c3832f9bf0edb639a22724604
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: aab5f4a311b0d0b1f5290485b8bffa43f149dc34b541618ead9b4c814494505f9d353c37cc129f4859d439b30aa123bf8012e0f25a9a7c377d744846401d2d42
|
7
|
+
data.tar.gz: d2e34ba6288296842337128f1bd13dc35b219fb6ad6dce045e0ba6aa963a36bfc2c92a2b12eefe4d99407395a449f9666d0f5dc7d7b526a5e07c10a4d4d3dcaf
|
@@ -0,0 +1,226 @@
|
|
1
|
+
require 'baykit/bayserver/bcf/package'
|
2
|
+
require 'baykit/bayserver/agent/transporter/plain_transporter'
|
3
|
+
require 'baykit/bayserver/agent/transporter/spin_read_transporter'
|
4
|
+
require 'baykit/bayserver/tours/tour'
|
5
|
+
require 'baykit/bayserver/tours/read_file_taxi'
|
6
|
+
require 'baykit/bayserver/docker/base/club_base'
|
7
|
+
require 'baykit/bayserver/docker/harbor'
|
8
|
+
require 'baykit/bayserver/docker/cgi/cgi_req_content_handler'
|
9
|
+
require 'baykit/bayserver/docker/cgi/cgi_std_out_yacht'
|
10
|
+
require 'baykit/bayserver/docker/cgi/cgi_std_err_yacht'
|
11
|
+
require 'baykit/bayserver/docker/cgi/cgi_message'
|
12
|
+
require 'baykit/bayserver/taxi/taxi_runner'
|
13
|
+
require 'baykit/bayserver/util/http_status'
|
14
|
+
require 'baykit/bayserver/util/cgi_util'
|
15
|
+
require 'baykit/bayserver/util/sys_util'
|
16
|
+
|
17
|
+
module Baykit
|
18
|
+
module BayServer
|
19
|
+
module Docker
|
20
|
+
module Cgi
|
21
|
+
class CgiDocker < Baykit::BayServer::Docker::Base::ClubBase
|
22
|
+
include Baykit::BayServer::Bcf
|
23
|
+
include Baykit::BayServer::Util
|
24
|
+
include Baykit::BayServer::Agent
|
25
|
+
include Baykit::BayServer::Agent::Transporter
|
26
|
+
include Baykit::BayServer::Docker
|
27
|
+
include Baykit::BayServer::Docker::Cgi
|
28
|
+
include Baykit::BayServer::Tours
|
29
|
+
include Baykit::BayServer::Taxi
|
30
|
+
|
31
|
+
DEFAULT_PROC_READ_METHOD = Harbor::FILE_SEND_METHOD_TAXI
|
32
|
+
DEFAULT_TIMEOUT_SEC = 60
|
33
|
+
|
34
|
+
attr :interpreter
|
35
|
+
attr :script_base
|
36
|
+
attr :doc_root
|
37
|
+
|
38
|
+
# Method to read stdin/stderr
|
39
|
+
attr :proc_read_method
|
40
|
+
|
41
|
+
def initialize()
|
42
|
+
super
|
43
|
+
@interpreter = nil
|
44
|
+
@script_base = nil
|
45
|
+
@doc_root = nil
|
46
|
+
@proc_read_method = CgiDocker::DEFAULT_PROC_READ_METHOD
|
47
|
+
@timeout_sec = CgiDocker::DEFAULT_TIMEOUT_SEC
|
48
|
+
end
|
49
|
+
|
50
|
+
######################################################
|
51
|
+
# Implements Docker
|
52
|
+
######################################################
|
53
|
+
|
54
|
+
def init(elm, parent)
|
55
|
+
super
|
56
|
+
|
57
|
+
if @proc_read_method == Harbor::FILE_SEND_METHOD_SELECT and !SysUtil.support_select_pipe()
|
58
|
+
BayLog.warn(BayMessage.get(:CGI_PROC_READ_METHOD_SELECT_NOT_SUPPORTED))
|
59
|
+
@proc_read_method = Harbor::FILE_SEND_METHOD_TAXI
|
60
|
+
end
|
61
|
+
|
62
|
+
if @proc_read_method == Harbor::FILE_SEND_METHOD_SPIN and !SysUtil.support_nonblock_pipe_read()
|
63
|
+
BayLog.warn(BayMessage.get(:CGI_PROC_READ_METHOD_SPIN_NOT_SUPPORTED))
|
64
|
+
@proc_read_method = Harbor::FILE_SEND_METHOD_TAXI
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
######################################################
|
70
|
+
# Implements DockerBase
|
71
|
+
######################################################
|
72
|
+
|
73
|
+
def init_key_val(kv)
|
74
|
+
case kv.key.downcase
|
75
|
+
when "interpreter"
|
76
|
+
@interpreter = kv.value
|
77
|
+
|
78
|
+
when "scriptbase"
|
79
|
+
@script_base = kv.value
|
80
|
+
|
81
|
+
when "docroot"
|
82
|
+
@doc_root = kv.value
|
83
|
+
|
84
|
+
when "processreadmethod"
|
85
|
+
case kv.value.downcase()
|
86
|
+
|
87
|
+
when "select"
|
88
|
+
@proc_read_method = Harbor::FILE_SEND_METHOD_SELECT
|
89
|
+
|
90
|
+
when "spin"
|
91
|
+
@proc_read_method = Harbor::FILE_SEND_METHOD_SPIN
|
92
|
+
|
93
|
+
when "taxi"
|
94
|
+
@proc_read_method = Harbor::FILE_SEND_METHOD_TAXI
|
95
|
+
|
96
|
+
when "timeout"
|
97
|
+
@timeout_sec = int(kv.value)
|
98
|
+
|
99
|
+
else
|
100
|
+
raise ConfigException.new(kv.file_name, kv.line_no, BayMessage.get(:CFG_INVALID_PARAMETER_VALUE, kv.value))
|
101
|
+
end
|
102
|
+
else
|
103
|
+
return super
|
104
|
+
end
|
105
|
+
return true
|
106
|
+
end
|
107
|
+
|
108
|
+
######################################################
|
109
|
+
# Implements Club
|
110
|
+
######################################################
|
111
|
+
|
112
|
+
def arrive(tur)
|
113
|
+
|
114
|
+
if tur.req.uri.include?("..")
|
115
|
+
raise HttpException.new(HttpStatus::FORBIDDEN, tur.req.uri)
|
116
|
+
return
|
117
|
+
end
|
118
|
+
|
119
|
+
base = script_base
|
120
|
+
if base == nil
|
121
|
+
base = tur.town.location()
|
122
|
+
end
|
123
|
+
|
124
|
+
if StringUtil.empty?(base)
|
125
|
+
raise HttpException.new(HttpStatus::INTERNAL_SERVER_ERROR, "%s scriptBase of cgi docker or location of town is not specified.", tur.town)
|
126
|
+
end
|
127
|
+
|
128
|
+
root = doc_root
|
129
|
+
if root == nil
|
130
|
+
root = tur.town.location()
|
131
|
+
end
|
132
|
+
|
133
|
+
if StringUtil.empty?(root)
|
134
|
+
raise HttpException.new(HttpStatus::INTERNAL_SERVER_ERROR, "$s docRoot of cgi docker or location of town is not specified.", tur.town)
|
135
|
+
end
|
136
|
+
|
137
|
+
env = CgiUtil.get_env_hash(tur.town.name, root, base, tur)
|
138
|
+
if BayServer.harbor.trace_header?
|
139
|
+
env.keys.each do |name|
|
140
|
+
value = env[name]
|
141
|
+
BayLog.info("%s cgi: env: %s=%s", tur, name, value)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
file_name = env[CgiUtil::SCRIPT_FILENAME]
|
146
|
+
if !File.file?(file_name)
|
147
|
+
raise HttpException.new(HttpStatus::NOT_FOUND, file_name)
|
148
|
+
end
|
149
|
+
|
150
|
+
bufsize = 8192;
|
151
|
+
handler = CgiReqContentHandler.new(self, tur)
|
152
|
+
tur.req.set_content_handler(handler)
|
153
|
+
handler.start_tour(env)
|
154
|
+
fname = "cgi#"
|
155
|
+
|
156
|
+
out_yat = CgiStdOutYacht.new()
|
157
|
+
err_yat = CgiStdErrYacht.new()
|
158
|
+
|
159
|
+
case(@proc_read_method)
|
160
|
+
when Harbor::FILE_SEND_METHOD_SELECT
|
161
|
+
out_tp = PlainTransporter.new(false, bufsize)
|
162
|
+
out_yat.init(tur, out_tp)
|
163
|
+
out_tp.init(tur.ship.agent.non_blocking_handler, handler.std_out[0], out_yat)
|
164
|
+
out_tp.open_valve()
|
165
|
+
|
166
|
+
err_tp = PlainTransporter.new(false, bufsize)
|
167
|
+
err_yat.init(tur)
|
168
|
+
err_tp.init(tur.ship.agent.non_blocking_handler, handler.std_err[0], err_yat)
|
169
|
+
err_tp.open_valve()
|
170
|
+
|
171
|
+
when Harbor::FILE_SEND_METHOD_SPIN
|
172
|
+
|
173
|
+
def eof_checker()
|
174
|
+
begin
|
175
|
+
pid = Process.wait(handler.pid, Process::WNOHANG)
|
176
|
+
return pid != nil
|
177
|
+
rescue Errno::ECHILD => e
|
178
|
+
BayLog.error_e(e)
|
179
|
+
return true
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
out_tp = SpinReadTransporter.new(bufsize)
|
184
|
+
out_yat.init(tur, out_tp)
|
185
|
+
out_tp.init(tur.ship.agent.spin_handler, out_yat, handler.std_out[0], -1, @timeout_sec, eof_checker)
|
186
|
+
out_tp.open_valve()
|
187
|
+
|
188
|
+
err_tp = SpinReadTransporter.new(bufsize)
|
189
|
+
err_yat.init(tur)
|
190
|
+
err_tp.init(tur.ship.agent.spin_handler, err_yat, handler.std_out[0], -1, @timeout_sec, eof_checker)
|
191
|
+
err_tp.open_valve()
|
192
|
+
|
193
|
+
when Harbor::FILE_SEND_METHOD_TAXI
|
194
|
+
out_txi = ReadFileTaxi.new(bufsize)
|
195
|
+
out_yat.init(tur, out_txi)
|
196
|
+
out_txi.init(handler.std_out[0], out_yat)
|
197
|
+
if !TaxiRunner.post(out_txi)
|
198
|
+
raise HttpException.new(HttpStatus.SERVICE_UNAVAILABLE, "Taxi is busy!")
|
199
|
+
end
|
200
|
+
|
201
|
+
err_txi = ReadFileTaxi.new(bufsize)
|
202
|
+
err_yat.init(tur)
|
203
|
+
err_txi.init(handler.std_err[0], err_yat)
|
204
|
+
if !TaxiRunner.post(err_txi)
|
205
|
+
raise HttpException.new(HttpStatus.SERVICE_UNAVAILABLE, "Taxi is busy!")
|
206
|
+
end
|
207
|
+
|
208
|
+
else
|
209
|
+
raise Sink.new();
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
def create_command(env)
|
214
|
+
script = env[CgiUtil::SCRIPT_FILENAME]
|
215
|
+
if @interpreter == nil
|
216
|
+
command = script
|
217
|
+
else
|
218
|
+
command = @interpreter + " " + script
|
219
|
+
end
|
220
|
+
command
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'baykit/bayserver/bayserver'
|
2
|
+
require 'baykit/bayserver/util/message'
|
3
|
+
require 'baykit/bayserver/util/locale'
|
4
|
+
|
5
|
+
module Baykit
|
6
|
+
module BayServer
|
7
|
+
module Docker
|
8
|
+
module Cgi
|
9
|
+
class CgiMessage
|
10
|
+
include Util
|
11
|
+
|
12
|
+
class << self
|
13
|
+
def initialize()
|
14
|
+
self.init()
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
@@msg = Message.new
|
19
|
+
|
20
|
+
def self.init()
|
21
|
+
@msg.init(BayServer.bserv_home + "/lib/conf/cgi_messages", Locale.default())
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.get(key, *args)
|
25
|
+
return @@msg.get(key, *args)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
require 'baykit/bayserver/train/train'
|
2
|
+
require 'baykit/bayserver/tours/req_content_handler'
|
3
|
+
|
4
|
+
require 'baykit/bayserver/util/string_util'
|
5
|
+
require 'baykit/bayserver/util/http_status'
|
6
|
+
|
7
|
+
module Baykit
|
8
|
+
module BayServer
|
9
|
+
module Docker
|
10
|
+
module Cgi
|
11
|
+
class CgiReqContentHandler
|
12
|
+
include Baykit::BayServer::Tours::ReqContentHandler # implements
|
13
|
+
|
14
|
+
include Baykit::BayServer::Agent
|
15
|
+
include Baykit::BayServer::Train
|
16
|
+
include Baykit::BayServer::Tours
|
17
|
+
include Baykit::BayServer::Util
|
18
|
+
|
19
|
+
READ_CHUNK_SIZE = 8192
|
20
|
+
|
21
|
+
attr :cgi_docker
|
22
|
+
attr :tour
|
23
|
+
attr :tour_id
|
24
|
+
attr :available
|
25
|
+
attr :pid
|
26
|
+
attr :std_in
|
27
|
+
attr :std_out
|
28
|
+
attr :std_err
|
29
|
+
attr :std_out_closed
|
30
|
+
attr :std_err_closed
|
31
|
+
|
32
|
+
def initialize(cgi_docker, tur)
|
33
|
+
@cgi_docker = cgi_docker
|
34
|
+
@tour = tur
|
35
|
+
@tour_id = tur.tour_id
|
36
|
+
end
|
37
|
+
|
38
|
+
######################################################
|
39
|
+
# Implements ReqContentHandler
|
40
|
+
######################################################
|
41
|
+
|
42
|
+
def on_read_content(tur, buf, start, len)
|
43
|
+
BayLog.debug("%s CGI:onReadReqContent: len=%d", tur, len)
|
44
|
+
|
45
|
+
wrote_len = @std_in[1].write(buf[start, len])
|
46
|
+
BayLog.debug("%s CGI:onReadReqContent: wrote=%d", tur, wrote_len)
|
47
|
+
tur.req.consumed(Tour::TOUR_ID_NOCHECK, len)
|
48
|
+
end
|
49
|
+
|
50
|
+
def on_end_content(tur)
|
51
|
+
BayLog.trace("%s CGI:endReqContent", tur)
|
52
|
+
end
|
53
|
+
|
54
|
+
def on_abort(tur)
|
55
|
+
BayLog.debug("%s CGI:abortReq", tur)
|
56
|
+
if !@std_out_closed
|
57
|
+
@tour.ship.agent.non_blocking_handler.ask_to_close(@std_out[0])
|
58
|
+
end
|
59
|
+
if !@std_err_closed
|
60
|
+
@tour.ship.agent.non_blocking_handler.ask_to_close(@std_err[0])
|
61
|
+
end
|
62
|
+
|
63
|
+
BayLog.debug("%s KILL PROCESS!: %d", tur, @pid)
|
64
|
+
Process.kill('KILL', @pid)
|
65
|
+
|
66
|
+
return false # not aborted immediately
|
67
|
+
end
|
68
|
+
|
69
|
+
######################################################
|
70
|
+
# Other methods
|
71
|
+
######################################################
|
72
|
+
|
73
|
+
def start_tour(env)
|
74
|
+
@available = false
|
75
|
+
|
76
|
+
@std_in = IO.pipe()
|
77
|
+
@std_out = IO.pipe()
|
78
|
+
@std_err = IO.pipe()
|
79
|
+
@std_in[1].set_encoding("ASCII-8BIT")
|
80
|
+
@std_out[0].set_encoding("ASCII-8BIT")
|
81
|
+
@std_err[0].set_encoding("ASCII-8BIT")
|
82
|
+
|
83
|
+
command = @cgi_docker.create_command(env)
|
84
|
+
BayLog.debug("%s Spawn: %s", @tour, command)
|
85
|
+
@pid = Process.spawn(env, command, :in => @std_in[0], :out => @std_out[1], :err => @std_err[1])
|
86
|
+
BayLog.debug("%s created process; %s", @tour, @pid)
|
87
|
+
|
88
|
+
@std_in[0].close()
|
89
|
+
@std_out[1].close()
|
90
|
+
@std_err[1].close()
|
91
|
+
BayLog.debug("#{@tour} PID: #{pid}")
|
92
|
+
|
93
|
+
@std_out_closed = false
|
94
|
+
@std_err_closed = false
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
def std_out_closed()
|
99
|
+
@std_out_closed = true
|
100
|
+
if @std_out_closed && @std_err_closed
|
101
|
+
process_finished()
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def std_err_closed()
|
106
|
+
@std_err_closed = true
|
107
|
+
if @std_out_closed && @std_err_closed
|
108
|
+
process_finished()
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def process_finished()
|
113
|
+
pid, stat = Process.wait2(@pid)
|
114
|
+
|
115
|
+
BayLog.debug("%s CGI Process finished: pid=%s code=%s", @tour, pid, stat.exitstatus)
|
116
|
+
if pid == nil
|
117
|
+
BayLog.error("Process not finished: %d", @pid)
|
118
|
+
end
|
119
|
+
|
120
|
+
begin
|
121
|
+
if stat.exitstatus != 0
|
122
|
+
# Exec failed
|
123
|
+
BayLog.error("%s CGI Invalid exit status pid=%d code=%s", @tour, @pid, stat.exitstatus)
|
124
|
+
@tour.res.send_error(@tour_id, HttpStatus::INTERNAL_SERVER_ERROR, "Invalid exit Status")
|
125
|
+
else
|
126
|
+
@tour.res.end_content(@tour_id)
|
127
|
+
end
|
128
|
+
rescue IOError => e
|
129
|
+
BayLog.error_e(e)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'baykit/bayserver/agent/next_socket_action'
|
2
|
+
require 'baykit/bayserver/watercraft/yacht'
|
3
|
+
require 'baykit/bayserver/util/string_util'
|
4
|
+
require 'baykit/bayserver/util/reusable'
|
5
|
+
|
6
|
+
module Baykit
|
7
|
+
module BayServer
|
8
|
+
module Docker
|
9
|
+
module Cgi
|
10
|
+
class CgiStdErrYacht < Baykit::BayServer::WaterCraft::Yacht
|
11
|
+
|
12
|
+
include Baykit::BayServer::Agent
|
13
|
+
include Baykit::BayServer::Util
|
14
|
+
|
15
|
+
attr :tour
|
16
|
+
attr :tour_id
|
17
|
+
|
18
|
+
def initialize
|
19
|
+
super
|
20
|
+
reset()
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_s()
|
24
|
+
return "CGIErrYat##{@yacht_id}/#{@object_id} tour=#{@tour} id=#{@tour_id}";
|
25
|
+
end
|
26
|
+
|
27
|
+
######################################################
|
28
|
+
# implements Reusable
|
29
|
+
######################################################
|
30
|
+
|
31
|
+
def reset()
|
32
|
+
@tour = nil
|
33
|
+
@tour_id = 0
|
34
|
+
end
|
35
|
+
|
36
|
+
######################################################
|
37
|
+
# implements Yacht
|
38
|
+
######################################################
|
39
|
+
|
40
|
+
def notify_read(buf, adr)
|
41
|
+
|
42
|
+
BayLog.debug("%s CGI StdErr %d bytesd", self, buf.length)
|
43
|
+
if(buf.length() > 0)
|
44
|
+
BayLog.error("CGI Stderr: %s", buf)
|
45
|
+
end
|
46
|
+
|
47
|
+
return NextSocketAction::CONTINUE;
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
def notify_eof()
|
52
|
+
BayLog.debug("%s CGI StdErr: EOF\\(^o^)/", self)
|
53
|
+
return NextSocketAction::CLOSE
|
54
|
+
end
|
55
|
+
|
56
|
+
def notify_close()
|
57
|
+
BayLog.debug("%s CGI StdErr: notifyClose", self)
|
58
|
+
@tour.req.content_handler.std_err_closed()
|
59
|
+
end
|
60
|
+
|
61
|
+
def check_timeout(duration)
|
62
|
+
BayLog.warn("%s invalid timeout check", self)
|
63
|
+
return false
|
64
|
+
end
|
65
|
+
|
66
|
+
######################################################
|
67
|
+
# Custom methods
|
68
|
+
######################################################
|
69
|
+
|
70
|
+
def init(tur)
|
71
|
+
init_yacht()
|
72
|
+
@tour = tur
|
73
|
+
@tour_id = tur.tour_id
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
|
@@ -0,0 +1,158 @@
|
|
1
|
+
require 'baykit/bayserver/agent/next_socket_action'
|
2
|
+
require 'baykit/bayserver/watercraft/yacht'
|
3
|
+
require 'baykit/bayserver/util/string_util'
|
4
|
+
require 'baykit/bayserver/util/reusable'
|
5
|
+
|
6
|
+
module Baykit
|
7
|
+
module BayServer
|
8
|
+
module Docker
|
9
|
+
module Cgi
|
10
|
+
class CgiStdOutYacht < Baykit::BayServer::WaterCraft::Yacht
|
11
|
+
|
12
|
+
include Baykit::BayServer::Agent
|
13
|
+
include Baykit::BayServer::Util
|
14
|
+
|
15
|
+
attr :file_wrote_len
|
16
|
+
|
17
|
+
attr :tour
|
18
|
+
attr :tour_id
|
19
|
+
|
20
|
+
attr :remain
|
21
|
+
attr :header_reading
|
22
|
+
|
23
|
+
def initialize
|
24
|
+
super
|
25
|
+
reset()
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_s()
|
29
|
+
return "CGIYat##{@yacht_id}/#{@object_id} tour=#{@tour} id=#{@tour_id}";
|
30
|
+
end
|
31
|
+
|
32
|
+
######################################################
|
33
|
+
# implements Reusable
|
34
|
+
######################################################
|
35
|
+
|
36
|
+
def reset()
|
37
|
+
@file_wrote_len = 0
|
38
|
+
@tour = nil
|
39
|
+
@tour_id = 0
|
40
|
+
@header_reading = true
|
41
|
+
@remain = ""
|
42
|
+
end
|
43
|
+
|
44
|
+
######################################################
|
45
|
+
# implements Yacht
|
46
|
+
######################################################
|
47
|
+
|
48
|
+
def notify_read(buf, adr)
|
49
|
+
@file_wrote_len += buf.length
|
50
|
+
BayLog.trace("%s read file %d bytes: total=%d", self, buf.length, @file_wrote_len)
|
51
|
+
|
52
|
+
pos = 0
|
53
|
+
if @header_reading
|
54
|
+
|
55
|
+
while true
|
56
|
+
p = buf.index("\n", pos)
|
57
|
+
|
58
|
+
#BayLog.debug("pos: %d", pos)
|
59
|
+
|
60
|
+
if p == nil
|
61
|
+
break
|
62
|
+
end
|
63
|
+
|
64
|
+
line = buf[pos .. p]
|
65
|
+
pos = p + 1
|
66
|
+
|
67
|
+
if @remain.length > 0
|
68
|
+
line = @remain + line
|
69
|
+
end
|
70
|
+
@remain = ""
|
71
|
+
|
72
|
+
line = line.strip()
|
73
|
+
|
74
|
+
# if line is empty ("\r\n")
|
75
|
+
# finish header reading.
|
76
|
+
if StringUtil.empty?(line)
|
77
|
+
@header_reading = false
|
78
|
+
@tour.res.send_headers(@tour_id)
|
79
|
+
break
|
80
|
+
else
|
81
|
+
if BayServer.harbor.trace_header()
|
82
|
+
BayLog.info("%s CGI: res header line: %s", tour, line);
|
83
|
+
end
|
84
|
+
|
85
|
+
sep_pos = line.index(':')
|
86
|
+
if sep_pos != nil
|
87
|
+
key = line[0 .. sep_pos - 1].strip()
|
88
|
+
val = line[sep_pos + 1 .. -1].strip()
|
89
|
+
|
90
|
+
if key.downcase() == "status"
|
91
|
+
begin
|
92
|
+
val = val.split(" ")[0]
|
93
|
+
@tour.res.headers.status = val.to_i()
|
94
|
+
rescue => e
|
95
|
+
BayLog.error_e(e)
|
96
|
+
end
|
97
|
+
else
|
98
|
+
@tour.res.headers.add(key, val);
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
available = true
|
106
|
+
|
107
|
+
if @header_reading
|
108
|
+
@remain += buf[pos .. -1]
|
109
|
+
else
|
110
|
+
if buf.length - pos > 0
|
111
|
+
available = @tour.res.send_content(@tour_id, buf, pos, buf.length - pos);
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
if available
|
116
|
+
return NextSocketAction::CONTINUE;
|
117
|
+
else
|
118
|
+
return NextSocketAction::SUSPEND;
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
def notify_eof()
|
124
|
+
BayLog.debug("%s CGI StdOut: EOF(^o^)", self)
|
125
|
+
return NextSocketAction::CLOSE
|
126
|
+
end
|
127
|
+
|
128
|
+
def notify_close()
|
129
|
+
BayLog.debug("%s CGI StdOut: notifyClose", self)
|
130
|
+
@tour.req.content_handler.std_out_closed()
|
131
|
+
end
|
132
|
+
|
133
|
+
def check_timeout(duration)
|
134
|
+
BayLog.warn("%s invalid timeout check", self)
|
135
|
+
return false
|
136
|
+
end
|
137
|
+
|
138
|
+
######################################################
|
139
|
+
# Custom methods
|
140
|
+
######################################################
|
141
|
+
|
142
|
+
def init(tur, valve)
|
143
|
+
init_yacht()
|
144
|
+
@tour = tur
|
145
|
+
@tour_id = tur.tour_id
|
146
|
+
tur.res.set_consume_listener do |len, resume|
|
147
|
+
if resume
|
148
|
+
valve.open_valve();
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
|
@@ -0,0 +1,182 @@
|
|
1
|
+
require 'baykit/bayserver/train/train'
|
2
|
+
require 'baykit/bayserver/tours/req_content_handler'
|
3
|
+
|
4
|
+
require 'baykit/bayserver/util/string_util'
|
5
|
+
require 'baykit/bayserver/util/http_status'
|
6
|
+
|
7
|
+
module Baykit
|
8
|
+
module BayServer
|
9
|
+
module Docker
|
10
|
+
module Cgi
|
11
|
+
class CgiTrain < Baykit::BayServer::Train::Train
|
12
|
+
include Baykit::BayServer::Tours::ReqContentHandler # implements
|
13
|
+
|
14
|
+
include Baykit::BayServer::Agent
|
15
|
+
include Baykit::BayServer::Train
|
16
|
+
include Baykit::BayServer::Tours
|
17
|
+
include Baykit::BayServer::Util
|
18
|
+
|
19
|
+
READ_CHUNK_SIZE = 8192
|
20
|
+
|
21
|
+
attr :cgi_docker
|
22
|
+
attr :env
|
23
|
+
attr :available
|
24
|
+
attr :lock
|
25
|
+
attr :pid
|
26
|
+
attr :std_in
|
27
|
+
attr :std_out
|
28
|
+
attr :std_err
|
29
|
+
|
30
|
+
def initialize(cgi_docker, tur)
|
31
|
+
super(tur)
|
32
|
+
@cgi_docker = cgi_docker
|
33
|
+
end
|
34
|
+
|
35
|
+
def start_tour(env)
|
36
|
+
@env = env
|
37
|
+
@available = false
|
38
|
+
@lock = Mutex.new()
|
39
|
+
|
40
|
+
@std_in = IO.pipe()
|
41
|
+
@std_out = IO.pipe()
|
42
|
+
@std_err = IO.pipe()
|
43
|
+
@std_in[1].set_encoding("ASCII-8BIT")
|
44
|
+
@std_out[0].set_encoding("ASCII-8BIT")
|
45
|
+
@std_err[0].set_encoding("ASCII-8BIT")
|
46
|
+
|
47
|
+
command = @cgi_docker.create_command(@env)
|
48
|
+
BayLog.debug("%s Spawn: %s", @tour, command)
|
49
|
+
@pid = Process.spawn(@env, command, :in => @std_in[0], :out => @std_out[1], :err => @std_err[1])
|
50
|
+
@std_in[0].close()
|
51
|
+
@std_out[1].close()
|
52
|
+
@std_err[1].close()
|
53
|
+
BayLog.debug("#{@tour} PID: #{pid}")
|
54
|
+
|
55
|
+
@tour.req.set_content_handler(self)
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
def depart
|
60
|
+
|
61
|
+
begin
|
62
|
+
|
63
|
+
###############
|
64
|
+
# Handle StdOut
|
65
|
+
HttpUtil.parse_message_headers(@std_out[0], @tour.res.headers)
|
66
|
+
|
67
|
+
if BayServer.harbor.trace_header?
|
68
|
+
@tour.res.headers.names.each do |name|
|
69
|
+
@tour.res.headers.values(name).each do |value|
|
70
|
+
BayLog.info("%s CGI: resHeader: %s=%s", @tour, name, value)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
status = @tour.res.headers.get("Status")
|
76
|
+
#BayLog.debug "Headers: #{@tours.res.headers.headers}"
|
77
|
+
#BayLog.debug "Status: #{status}"
|
78
|
+
if !StringUtil.empty?(status)
|
79
|
+
pos = status.index(" ")
|
80
|
+
if pos
|
81
|
+
code = status[0, pos].to_i
|
82
|
+
else
|
83
|
+
code = status.to_i
|
84
|
+
end
|
85
|
+
@tour.res.headers.status = code
|
86
|
+
end
|
87
|
+
|
88
|
+
@tour.res.set_consume_listener do |len, resume|
|
89
|
+
if resume
|
90
|
+
@available = true
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
@tour.res.send_headers(@tour_id)
|
95
|
+
|
96
|
+
#BayLog.info("Reading STDOUT")
|
97
|
+
while true
|
98
|
+
buf = StringUtil.alloc(READ_CHUNK_SIZE)
|
99
|
+
c = std_out[0].read(READ_CHUNK_SIZE, buf)
|
100
|
+
if !c
|
101
|
+
break
|
102
|
+
end
|
103
|
+
|
104
|
+
BayLog.trace("%s CGITrain: read stdout bytes: len=%d", @tour, buf.length)
|
105
|
+
@available = @tour.res.send_content(@tour_id, buf, 0, buf.length)
|
106
|
+
while !@available
|
107
|
+
sleep(0.1)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
#BayLog.info("Reading STDERR")
|
112
|
+
###############
|
113
|
+
# Handle StdErr
|
114
|
+
###############
|
115
|
+
while true
|
116
|
+
buf = StringUtil.alloc(READ_CHUNK_SIZE)
|
117
|
+
c = std_err[0].read(READ_CHUNK_SIZE, buf)
|
118
|
+
if !c
|
119
|
+
break
|
120
|
+
end
|
121
|
+
|
122
|
+
BayLog.warn("%s CGITrain: read stderr bytes: %d", @tour, buf.length)
|
123
|
+
BayLog.warn(buf)
|
124
|
+
end
|
125
|
+
|
126
|
+
@tour.res.end_content @tour_id
|
127
|
+
|
128
|
+
rescue HttpException => e
|
129
|
+
raise e
|
130
|
+
rescue => e
|
131
|
+
BayLog.error("%s CGITrain: Catch error: %s", @tour, e)
|
132
|
+
BayLog.error_e(e)
|
133
|
+
raise HttpException.new(HttpStatus::INTERNAL_SERVER_ERROR, "CGI error")
|
134
|
+
ensure
|
135
|
+
begin
|
136
|
+
BayLog.debug("%s CGITrain: waiting process end", @tour)
|
137
|
+
Process.wait(@pid)
|
138
|
+
close_pipes()
|
139
|
+
|
140
|
+
BayLog.debug("%s CGITrain: process ended", @tour)
|
141
|
+
rescue => e
|
142
|
+
BayLog.error_e(e)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def on_read_content(tur, buf, start, len)
|
148
|
+
BayLog.info("%s CGITrain:onReadContent: len=%d", tur, len)
|
149
|
+
|
150
|
+
wrote_len = @std_in[1].write(buf[start, len])
|
151
|
+
BayLog.info("%s CGITrain:onReadContent: wrote=%d", tur, wrote_len)
|
152
|
+
tur.req.consumed(Tour::TOUR_ID_NOCHECK, len)
|
153
|
+
end
|
154
|
+
|
155
|
+
def on_end_content(tur)
|
156
|
+
BayLog.trace("%s CGITrain:endContent", tur)
|
157
|
+
|
158
|
+
if !TrainRunner.post(self)
|
159
|
+
raise HttpException.new(HttpStatus::SERVICE_UNAVAILABLE, "TrainRunner is busy")
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def on_abort(tur)
|
164
|
+
BayLog.debug("%s CGITrain:abort", tur)
|
165
|
+
close_pipes()
|
166
|
+
|
167
|
+
BayLog.debug("%s KILL PROCESS!: %d", tur, @pid)
|
168
|
+
Process.kill('KILL', @pid)
|
169
|
+
|
170
|
+
return false # not aborted immediately
|
171
|
+
end
|
172
|
+
|
173
|
+
def close_pipes()
|
174
|
+
@std_in[1].close()
|
175
|
+
@std_out[0].close()
|
176
|
+
@std_err[0].close()
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'baykit/bayserver/bcf/package'
|
2
|
+
require 'baykit/bayserver/docker/cgi/cgi_docker'
|
3
|
+
|
4
|
+
module Baykit
|
5
|
+
module BayServer
|
6
|
+
module Docker
|
7
|
+
module Cgi
|
8
|
+
class PhpCgiDocker < Baykit::BayServer::Docker::Cgi::CgiDocker
|
9
|
+
include Baykit::BayServer::Util
|
10
|
+
|
11
|
+
ENV_PHP_SELF = "PHP_SELF"
|
12
|
+
ENV_REDIRECT_STATUS = "REDIRECT_STATUS"
|
13
|
+
|
14
|
+
######################################################
|
15
|
+
# Implements Docker
|
16
|
+
######################################################
|
17
|
+
|
18
|
+
def init(elm, parent)
|
19
|
+
super
|
20
|
+
|
21
|
+
if @interpreter == nil
|
22
|
+
@interpreter = "php-cgi";
|
23
|
+
end
|
24
|
+
|
25
|
+
BayLog.debug("PHP interpreter: " + interpreter)
|
26
|
+
end
|
27
|
+
|
28
|
+
######################################################
|
29
|
+
# Override CgiDocker
|
30
|
+
######################################################
|
31
|
+
|
32
|
+
def create_command(env)
|
33
|
+
env[ENV_PHP_SELF] = env[CgiUtil::SCRIPT_NAME]
|
34
|
+
env[ENV_REDIRECT_STATUS] = 200.to_s
|
35
|
+
super
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
metadata
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bayserver-docker-cgi
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Michisuke-P
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-08-29 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bayserver-core
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 2.2.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 2.2.0
|
27
|
+
description: AJP docker of BayServer
|
28
|
+
email: michisukep@gmail.com
|
29
|
+
executables: []
|
30
|
+
extensions: []
|
31
|
+
extra_rdoc_files: []
|
32
|
+
files:
|
33
|
+
- lib/baykit/bayserver/docker/cgi/cgi_docker.rb
|
34
|
+
- lib/baykit/bayserver/docker/cgi/cgi_message.rb
|
35
|
+
- lib/baykit/bayserver/docker/cgi/cgi_req_content_handler.rb
|
36
|
+
- lib/baykit/bayserver/docker/cgi/cgi_std_err_yacht.rb
|
37
|
+
- lib/baykit/bayserver/docker/cgi/cgi_std_out_yacht.rb
|
38
|
+
- lib/baykit/bayserver/docker/cgi/cgi_train.rb
|
39
|
+
- lib/baykit/bayserver/docker/cgi/php_cgi_docker.rb
|
40
|
+
homepage: https://baykit.yokohama
|
41
|
+
licenses:
|
42
|
+
- MIT
|
43
|
+
metadata: {}
|
44
|
+
post_install_message:
|
45
|
+
rdoc_options: []
|
46
|
+
require_paths:
|
47
|
+
- lib
|
48
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
53
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '0'
|
58
|
+
requirements: []
|
59
|
+
rubygems_version: 3.1.6
|
60
|
+
signing_key:
|
61
|
+
specification_version: 4
|
62
|
+
summary: AJP docker of BayServer
|
63
|
+
test_files: []
|