bayserver-docker-cgi 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
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: []