1 | #
|
---|
2 | # cgihandler.rb -- CGIHandler Class
|
---|
3 | #
|
---|
4 | # Author: IPR -- Internet Programming with Ruby -- writers
|
---|
5 | # Copyright (c) 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
|
---|
6 | # Copyright (c) 2002 Internet Programming with Ruby writers. All rights
|
---|
7 | # reserved.
|
---|
8 | #
|
---|
9 | # $IPR: cgihandler.rb,v 1.27 2003/03/21 19:56:01 gotoyuzo Exp $
|
---|
10 |
|
---|
11 | require 'rbconfig'
|
---|
12 | require 'tempfile'
|
---|
13 | require 'webrick/config'
|
---|
14 | require 'webrick/httpservlet/abstract'
|
---|
15 |
|
---|
16 | module WEBrick
|
---|
17 | module HTTPServlet
|
---|
18 |
|
---|
19 | class CGIHandler < AbstractServlet
|
---|
20 | Ruby = File::join(::Config::CONFIG['bindir'],
|
---|
21 | ::Config::CONFIG['ruby_install_name'])
|
---|
22 | Ruby << ::Config::CONFIG['EXEEXT']
|
---|
23 | CGIRunner = "\"#{Ruby}\" \"#{Config::LIBDIR}/httpservlet/cgi_runner.rb\""
|
---|
24 |
|
---|
25 | def initialize(server, name)
|
---|
26 | super
|
---|
27 | @script_filename = name
|
---|
28 | @tempdir = server[:TempDir]
|
---|
29 | @cgicmd = "#{CGIRunner} #{server[:CGIInterpreter]}"
|
---|
30 | end
|
---|
31 |
|
---|
32 | def do_GET(req, res)
|
---|
33 | data = nil
|
---|
34 | status = -1
|
---|
35 |
|
---|
36 | cgi_in = IO::popen(@cgicmd, "wb")
|
---|
37 | cgi_out = Tempfile.new("webrick.cgiout.", @tempdir)
|
---|
38 | cgi_err = Tempfile.new("webrick.cgierr.", @tempdir)
|
---|
39 | begin
|
---|
40 | cgi_in.sync = true
|
---|
41 | meta = req.meta_vars
|
---|
42 | meta["SCRIPT_FILENAME"] = @script_filename
|
---|
43 | meta["PATH"] = @config[:CGIPathEnv]
|
---|
44 | if /mswin|bccwin|mingw/ =~ RUBY_PLATFORM
|
---|
45 | meta["SystemRoot"] = ENV["SystemRoot"]
|
---|
46 | end
|
---|
47 | dump = Marshal.dump(meta)
|
---|
48 |
|
---|
49 | cgi_in.write("%8d" % cgi_out.path.size)
|
---|
50 | cgi_in.write(cgi_out.path)
|
---|
51 | cgi_in.write("%8d" % cgi_err.path.size)
|
---|
52 | cgi_in.write(cgi_err.path)
|
---|
53 | cgi_in.write("%8d" % dump.size)
|
---|
54 | cgi_in.write(dump)
|
---|
55 |
|
---|
56 | if req.body and req.body.size > 0
|
---|
57 | cgi_in.write(req.body)
|
---|
58 | end
|
---|
59 | ensure
|
---|
60 | cgi_in.close
|
---|
61 | status = $?.exitstatus
|
---|
62 | sleep 0.1 if /mswin|bccwin|mingw/ =~ RUBY_PLATFORM
|
---|
63 | data = cgi_out.read
|
---|
64 | cgi_out.close(true)
|
---|
65 | if errmsg = cgi_err.read
|
---|
66 | if errmsg.size > 0
|
---|
67 | @logger.error("CGIHandler: #{@script_filename}:\n" + errmsg)
|
---|
68 | end
|
---|
69 | end
|
---|
70 | cgi_err.close(true)
|
---|
71 | end
|
---|
72 |
|
---|
73 | if status != 0
|
---|
74 | @logger.error("CGIHandler: #{@script_filename} exit with #{status}")
|
---|
75 | end
|
---|
76 |
|
---|
77 | data = "" unless data
|
---|
78 | raw_header, body = data.split(/^[\xd\xa]+/on, 2)
|
---|
79 | raise HTTPStatus::InternalServerError,
|
---|
80 | "Premature end of script headers: #{@script_filename}" if body.nil?
|
---|
81 |
|
---|
82 | begin
|
---|
83 | header = HTTPUtils::parse_header(raw_header)
|
---|
84 | if /^(\d+)/ =~ header['status'][0]
|
---|
85 | res.status = $1.to_i
|
---|
86 | header.delete('status')
|
---|
87 | end
|
---|
88 | if header.has_key?('set-cookie')
|
---|
89 | header['set-cookie'].each{|k|
|
---|
90 | res.cookies << Cookie.parse_set_cookie(k)
|
---|
91 | }
|
---|
92 | header.delete('set-cookie')
|
---|
93 | end
|
---|
94 | header.each{|key, val| res[key] = val.join(", ") }
|
---|
95 | rescue => ex
|
---|
96 | raise HTTPStatus::InternalServerError, ex.message
|
---|
97 | end
|
---|
98 | res.body = body
|
---|
99 | end
|
---|
100 | alias do_POST do_GET
|
---|
101 | end
|
---|
102 |
|
---|
103 | end
|
---|
104 | end
|
---|