Class: WEBrick::CGI

Inherits:
Object
  • Object
show all
Defined in:
lib/webrick/cgi.rb

Overview

A CGI library using WEBrick requests and responses.

Example:

class MyCGI < WEBrick::CGI
  def do_GET req, res
    res.body = 'it worked!'
    res.status = 200
  end
end

MyCGI.new.start

Defined Under Namespace

Classes: Socket

Constant Summary collapse

CGIError =

The CGI error exception class

Class.new(StandardError)

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ CGI

Creates a new CGI interface.

The first argument in args is a configuration hash which would update WEBrick::Config::HTTP.

Any remaining arguments are stored in the @options instance variable for use by a subclass.



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/webrick/cgi.rb', line 56

def initialize(*args)
  if defined?(MOD_RUBY)
    unless ENV.has_key?("GATEWAY_INTERFACE")
      Apache.request.setup_cgi_env
    end
  end
  if %r{HTTP/(\d+\.\d+)} =~ ENV["SERVER_PROTOCOL"]
    httpv = $1
  end
  @config = WEBrick::Config::HTTP.dup.update(
    :ServerSoftware => ENV["SERVER_SOFTWARE"] || "null",
    :HTTPVersion    => HTTPVersion.new(httpv || "1.0"),
    :RunOnCGI       => true,   # to detect if it runs on CGI.
    :NPH            => false   # set true to run as NPH script.
  )
  if config = args.shift
    @config.update(config)
  end
  @config[:Logger] ||= WEBrick::BasicLog.new($stderr)
  @logger = @config[:Logger]
  @options = args
end

Instance Attribute Details

#configObject (readonly)

The CGI configuration. This is based on WEBrick::Config::HTTP



40
41
42
# File 'lib/webrick/cgi.rb', line 40

def config
  @config
end

#loggerObject (readonly)

The CGI logger



45
46
47
# File 'lib/webrick/cgi.rb', line 45

def logger
  @logger
end

Instance Method Details

#[](key) ⇒ Object

Reads key from the configuration



82
83
84
# File 'lib/webrick/cgi.rb', line 82

def [](key)
  @config[key]
end

#service(req, res) ⇒ Object

Services the request req which will fill in the response res. See WEBrick::HTTPServlet::AbstractServlet#service for details.



157
158
159
160
161
162
163
164
165
# File 'lib/webrick/cgi.rb', line 157

def service(req, res)
  method_name = "do_" + req.request_method.gsub(/-/, "_")
  if respond_to?(method_name)
    __send__(method_name, req, res)
  else
    raise HTTPStatus::MethodNotAllowed,
          "unsupported method `#{req.request_method}'."
  end
end

#start(env = ENV, stdin = $stdin, stdout = $stdout) ⇒ Object

Starts the CGI process with the given environment env and standard input and output stdin and stdout.



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/webrick/cgi.rb', line 90

def start(env=ENV, stdin=$stdin, stdout=$stdout)
  sock = WEBrick::CGI::Socket.new(@config, env, stdin, stdout)
  req = HTTPRequest.new(@config)
  res = HTTPResponse.new(@config)
  unless @config[:NPH] or defined?(MOD_RUBY)
    def res.setup_header
      unless @header["status"]
        phrase = HTTPStatus::reason_phrase(@status)
        @header["status"] = "#{@status} #{phrase}"
      end
      super
    end
    def res.status_line
      ""
    end
  end

  begin
    req.parse(sock)
    req.script_name = (env["SCRIPT_NAME"] || File.expand_path($0)).dup
    req.path_info = (env["PATH_INFO"] || "").dup
    req.query_string = env["QUERY_STRING"]
    req.user = env["REMOTE_USER"]
    res.request_method = req.request_method
    res.request_uri = req.request_uri
    res.request_http_version = req.http_version
    res.keep_alive = req.keep_alive?
    self.service(req, res)
  rescue HTTPStatus::Error => ex
    res.set_error(ex)
  rescue HTTPStatus::Status => ex
    res.status = ex.code
  rescue Exception => ex
    @logger.error(ex)
    res.set_error(ex, true)
  ensure
    req.fixup
    if defined?(MOD_RUBY)
      res.setup_header
      Apache.request.status_line = "#{res.status} #{res.reason_phrase}"
      Apache.request.status = res.status
      table = Apache.request.headers_out
      res.header.each{|key, val|
        case key
        when /^content-encoding$/i
          Apache::request.content_encoding = val
        when /^content-type$/i
          Apache::request.content_type = val
        else
          table[key] = val.to_s
        end
      }
      res.cookies.each{|cookie|
        table.add("Set-Cookie", cookie.to_s)
      }
      Apache.request.send_http_header
      res.send_body(sock)
    else
      res.send_response(sock)
    end
  end
end