File: webrick/httpservlet/cgihandler.rb

Overview
Module Structure
Class Hierarchy
Code

Overview

Module Structure

  module: <Toplevel Module>
  module: WEBrick#16
  module: HTTPServlet#17
  class: CGIHandler#19
inherits from
  AbstractServlet ( WEBrick::HTTPServlet )
has properties
constant: Ruby #20
constant: CGIRunner #23
method: initialize / 2 #25
method: do_GET / 2 #32
alias: do_POST do_GET #104

Class Hierarchy

Code

   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?('location')
  89              # RFC 3875 6.2.3, 6.2.4
  90              res.status = 302 unless (300...400) === res.status
  91            end
  92            if header.has_key?('set-cookie')
  93              header['set-cookie'].each{|k|
  94                res.cookies << Cookie.parse_set_cookie(k)
  95              }
  96              header.delete('set-cookie')
  97            end
  98            header.each{|key, val| res[key] = val.join(", ") }
  99          rescue => ex
 100            raise HTTPStatus::InternalServerError, ex.message
 101          end
 102          res.body = body
 103        end
 104        alias do_POST do_GET
 105      end
 106 
 107    end
 108  end