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 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: []