# Web::Interface::FastCGI
# Copyright(c) 2002 MoonWolf <moonwolf@moonwolf.com>
require 'web/interface/basic'

module Web
  module Interface
    class FastCGI < Basic
      EOL = "\r\n"
      def initialize(opt={})
        require "fcgi"
        @sigterm = false
        trap('SIGTERM') { @sigterm = true }
      end
      
      # 標準入力からRequestを組み立てる
      def request(arg={})
        super
        req = Web::Request.new
        r = FCGI.accept
        return nil if @sigterm
        return nil unless r
        
        env    = r.env
        input  = r.in
        output = r.out
        req.env['fcgi_request'] = r
        #
        req.request_id       = env['UNIQUE_ID']       || Web::Common::unique_id
        req.method           = env['REQUEST_METHOD']  || 'GET'
        req.query_string     = env['QUERY_STRING']    || ''
        req.script_name      = env['SCRIPT_NAME']
        req.path_info        = env['PATH_INFO']
        req.path_translated  = env['PATH_TRANSLATED']
        req.server_name      = env['SERVER_NAME']
        req.server_port      = env['SERVER_PORT']
        req.server_protocol  = env['SERVER_PROTOCOL']
        req.host             = env['HTTP_HOST']
        req.remote_addr      = env['REMOTE_ADDR']     || ''
        req.remote_host      = env['REMOTE_HOST']     || req.remote_addr
        req.auth_type        = env['AUTH_TYPE']       || ''
        req.remote_ident     = env['REMOTE_IDENT']    || ''
        req.remote_user      = env['REMOTE_USER']
        req.https            = env['HTTPS'] ? true : false
        
        # header
        if len = env['CONTENT_LENGTH']
          req.header['CONTENT-LENGTH'] = len
        end
        type = env['CONTENT_TYPE']
        req.header['CONTENT-TYPE'] = type if type
        env.each {|key,value|
          if key=~/^HTTP_([0-9a-zA-Z_]+)/
            field = $1.upcase.tr("_","-")
            req.header[field] = value
          end
        }
        
        # cookie
        if cookie = req.header['COOKIE']
          req.cookies.parse(cookie, req)
        end
        
        
        ## param
        # QUERY_STRING
        parse_query(req.query_string || '', req.query)
        
        ## body
        case req.method
        when 'GET'
          # body
          req.body = nil
        when 'POST'
          ## form
          case req.header['CONTENT-TYPE']
          when /^multipart\/form-data\s*;\s*boundary="?(.*)"?/
            boundary=$1
            parse_multipart(input, boundary, req.form)
          when /^application\/x-www-form-urlencoded/
            parse_query(input.read.to_s, req.form)
          else
            req.body = input.read
          end
        end
        get_session_id req
        req
      end # FastCGI#request

      def response(req, rsp)
        exit if @sigterm
        super
        begin
          r = req.env['fcgi_request']
          out = r.out
          # ヘッダ出力
          out << 'Status: ' << rsp.status << EOL
          rsp.header.each {|key,value|
            field = key.split('-').collect! {|i| i.capitalize }.join('-') << ': '
            value.each {|v|
              out << (field + v + EOL)
            }
          }
          rsp.cookies.each {|key,cookie_ary|
            cookie_ary.each {|cookie|
              out << 'Set-Cookie: ' << cookie.to_response_header << EOL
            }
          }
          out << EOL
          
          #
          out << rsp.body
          req.cleanup
          r.finish
        rescue Errno::EPIPE
        end
      end # FastCGI#response
    end # FastCGI
  end # Interface
end # Web
