# class CGI

## Overview¶ ↑

The Common Gateway Interface (`CGI`) is a simple protocol for passing an HTTP request from a web server to a standalone program, and returning the output to the web browser. Basically, a `CGI` program is called with the parameters of the request passed in either in the environment (GET) or via $stdin (POST), and everything it prints to $stdout is returned to the client.

This file holds the `CGI` class. This class provides functionality for retrieving HTTP request parameters, managing cookies, and generating HTML output.

The file `CGI::Session` provides session management functionality; see that class for more details.

See www.w3.org/CGI/ for more information on the `CGI` protocol.

## Introduction¶ ↑

`CGI` is a large class, providing several categories of methods, many of which are mixed in from other modules. Some of the documentation is in this class, some in the modules `CGI::QueryExtension` and `CGI::HtmlExtension`. See `CGI::Cookie` for specific information on handling cookies, and cgi/session.rb (`CGI::Session`) for information on sessions.

For queries, `CGI` provides methods to get at environmental variables, parameters, cookies, and multipart request data. For responses, `CGI` provides methods for writing output and generating HTML.

Read on for more details. Examples are provided at the bottom.

## Queries¶ ↑

The `CGI` class dynamically mixes in parameter and cookie-parsing functionality, environmental variable access, and support for parsing multipart requests (including uploaded files) from the `CGI::QueryExtension` module.

### Environmental Variables¶ ↑

The standard `CGI` environmental variables are available as read-only attributes of a `CGI` object. The following is a list of these variables:

    AUTH_TYPE               HTTP_HOST          REMOTE_IDENT
    CONTENT_LENGTH          HTTP_NEGOTIATE     REMOTE_USER
    CONTENT_TYPE            HTTP_PRAGMA        REQUEST_METHOD
    GATEWAY_INTERFACE       HTTP_REFERER       SCRIPT_NAME
    HTTP_ACCEPT             HTTP_USER_AGENT    SERVER_NAME
    HTTP_ACCEPT_CHARSET     PATH_INFO          SERVER_PORT
    HTTP_ACCEPT_ENCODING    PATH_TRANSLATED    SERVER_PROTOCOL
    HTTP_ACCEPT_LANGUAGE    QUERY_STRING       SERVER_SOFTWARE
    HTTP_CACHE_CONTROL      REMOTE_ADDR
    HTTP_FROM               REMOTE_HOST

For each of these variables, there is a corresponding attribute with the same name, except all lower case and without a preceding HTTP_. `content_length` and `server_port` are integers; the rest are strings.

### Parameters¶ ↑

The method params() returns a hash of all parameters in the request as name/value-list pairs, where the value-list is an `Array` of one or more values. The `CGI` object itself also behaves as a hash of parameter names to values, but only returns a single value (as a `String`) for each parameter name.

For instance, suppose the request contains the parameter “favourite_colours” with the multiple values “blue” and “green”. The following behavior would occur:

    cgi.params["favourite_colours"]  # => ["blue", "green"]
    cgi["favourite_colours"]         # => "blue"

If a parameter does not exist, the former method will return an empty array, the latter an empty string. The simplest way to test for existence of a parameter is by the has_key? method.

### Cookies¶ ↑

HTTP Cookies are automatically parsed from the request. They are available from the cookies() accessor, which returns a hash from cookie name to `CGI::Cookie` object.

### Multipart requests¶ ↑

If a request’s method is POST and its content type is multipart/form-data, then it may contain uploaded files. These are stored by the `QueryExtension` module in the parameters of the request. The parameter name is the name attribute of the file input field, as usual. However, the value is not a string, but an `IO` object, either an IOString for small files, or a `Tempfile` for larger ones. This object also has the additional singleton methods:

local_path()

  the path of the uploaded file on the local filesystem

original_filename()

  the name of the file on the client computer

content_type()

  the content type of the file

## Responses¶ ↑

The `CGI` class provides methods for sending header and content output to the HTTP client, and mixes in methods for programmatic HTML generation from `CGI::HtmlExtension` and CGI::TagMaker modules. The precise version of HTML to use for HTML generation is specified at object creation time.

### Writing output¶ ↑

The simplest way to send output to the HTTP client is using the `out()` method. This takes the HTTP headers as a hash parameter, and the body content via a block. The headers can be generated as a string using the `http_header()` method. The output stream can be written directly to using the `print()` method.

### Generating HTML¶ ↑

Each HTML element has a corresponding method for generating that element as a `String`. The name of this method is the same as that of the element, all lowercase. The attributes of the element are passed in as a hash, and the body as a no-argument block that evaluates to a `String`. The HTML generation module knows which elements are always empty, and silently drops any passed-in body. It also knows which elements require matching closing tags and which don’t. However, it does not know what attributes are legal for which elements.

There are also some additional HTML generation methods mixed in from the `CGI::HtmlExtension` module. These include individual methods for the different types of form inputs, and methods for elements that commonly take particular attributes where the attributes can be directly specified as arguments, rather than via a hash.

### Utility HTML escape and other methods like a function.¶ ↑

There are some utility tool defined in cgi/util.rb . And when include, you can use utility methods like a function.

## Examples of use¶ ↑

### Get form values¶ ↑

    require "cgi"
    cgi = CGI.new
    value = cgi['field_name']   # <== value string for 'field_name'
      # if not 'field_name' included, then return "".
    fields = cgi.keys            # <== array of field names

    # returns true if form has 'field_name'
    cgi.has_key?('field_name')
    cgi.has_key?('field_name')
    cgi.include?('field_name')

CAUTION! `cgi['field_name']` returned an `Array` with the old cgi.rb(included in Ruby 1.6)

### Get form values as hash¶ ↑

    require "cgi"
    cgi = CGI.new
    params = cgi.params

cgi.params is a hash.

    cgi.params['new_field_name'] = ["value"]  # add new param
    cgi.params['field_name'] = ["new_value"]  # change value
    cgi.params.delete('field_name')           # delete param
    cgi.params.clear                          # delete all params

### Save form values to file¶ ↑

    require "pstore"
    db = PStore.new("query.db")
    db.transaction do
      db["params"] = cgi.params
    end

### Restore form values from file¶ ↑

    require "pstore"
    db = PStore.new("query.db")
    db.transaction do
      cgi.params = db["params"]
    end

### Get multipart form values¶ ↑

    require "cgi"
    cgi = CGI.new
    value = cgi['field_name']   # <== value string for 'field_name'
    value.read                  # <== body of value
    value.local_path            # <== path to local file of value
    value.original_filename     # <== original filename of value
    value.content_type          # <== content_type of value

and value has `StringIO` or `Tempfile` class methods.

### Get cookie values¶ ↑

    require "cgi"
    cgi = CGI.new
    values = cgi.cookies['name']  # <== array of 'name'
      # if not 'name' included, then return [].
    names = cgi.cookies.keys      # <== array of cookie names

and cgi.cookies is a hash.

### Get cookie objects¶ ↑

    require "cgi"
    cgi = CGI.new
    for name, cookie in cgi.cookies
      cookie.expires = Time.now + 30
    end
    cgi.out("cookie" => cgi.cookies) {"string"}

    cgi.cookies # { "name1" => cookie1, "name2" => cookie2, ... }

    require "cgi"
    cgi = CGI.new
    cgi.cookies['name'].expires = Time.now + 30
    cgi.out("cookie" => cgi.cookies['name']) {"string"}

### Print http header and html string to $DEFAULT_OUTPUT ($>)¶ ↑

    require "cgi"
    cgi = CGI.new("html4")  # add HTML generation methods
    cgi.out do
      cgi.html do
        cgi.head do
          cgi.title { "TITLE" }
        end +
        cgi.body do
          cgi.form("ACTION" => "uri") do
            cgi.p do
              cgi.textarea("get_text") +
              cgi.br +
              cgi.submit
            end
          end +
          cgi.pre do
            CGI.escapeHTML(
              "params: #{cgi.params.inspect}\n" +
              "cookies: #{cgi.cookies.inspect}\n" +
              ENV.collect do |key, value|
                "#{key} --> #{value}\n"
              end.join("")
            )
          end
        end
      end
    end

    # add HTML generation methods
    CGI.new("html3")    # html3.2
    CGI.new("html4")    # html4.01 (Strict)
    CGI.new("html4Tr")  # html4.01 Transitional
    CGI.new("html4Fr")  # html4.01 Frameset
    CGI.new("html5")    # html5

### Some utility methods¶ ↑

    require 'cgi/util'
    CGI.escapeHTML('Usage: foo "bar" <baz>')

### Some utility methods like a function¶ ↑

    require 'cgi/util'
    include CGI::Util
    escapeHTML('Usage: foo "bar" <baz>')
    h('Usage: foo "bar" <baz>') # alias

### Constants

CR

  `String` for carriage return

EOL

  Standard internet newline sequence

HTTP_STATUS

  HTTP status codes.

LF

  `String` for linefeed

MAX_MULTIPART_COUNT

  Maximum number of request parameters when multipart

NEEDS_BINMODE

  Whether processing will be required in binary vs text

PATH_SEPARATOR

  Path separators in different environments.

VERSION

### Attributes

accept_charset[R]

Return the accept character set for this `CGI` instance.

### Public Class Methods

accept_charset() click to toggle source

Return the accept character set for all new `CGI` instances.

    # File lib/cgi/core.rb, line 759
    def self.accept_charset
      @@accept_charset
    end

accept_charset=(accept_charset) click to toggle source

`Set` the accept character set for all new `CGI` instances.

    # File lib/cgi/core.rb, line 764
    def self.accept_charset=(accept_charset)
      @@accept_charset=accept_charset
    end

new(tag_maker) { block } click to toggle source
new(options_hash = {}) { block }

Create a new `CGI` instance.

`tag_maker`

  This is the same as using the `options_hash` form with the value `{ :tag_maker => tag_maker }` Note that it is recommended to use the `options_hash` form, since it also allows you specify the charset you will accept.

`options_hash`

  A `Hash` that recognizes three options:

  `:accept_charset`

    specifies encoding of received query string. If omitted, `@@accept_charset` is used. If the encoding is not valid, a `CGI::InvalidEncoding` will be raised.

    Example. Suppose `@@accept_charset` is “UTF-8”

    when not specified:

        cgi=CGI.new      # @accept_charset # => "UTF-8"

    when specified as “EUC-JP”:

        cgi=CGI.new(:accept_charset => "EUC-JP") # => "EUC-JP"

  `:tag_maker`

    `String` that specifies which version of the HTML generation methods to use. If not specified, no HTML generation methods will be loaded.

    The following values are supported:

    “html3”

      HTML 3.x

    “html4”

      HTML 4.0

    “html4Tr”

      HTML 4.0 Transitional

    “html4Fr”

      HTML 4.0 with Framesets

    “html5”

      HTML 5

  `:max_multipart_length`

    Specifies maximum length of multipart data. Can be an `Integer` scalar or a lambda, that will be evaluated when the request is parsed. This allows more complex logic to be set when determining whether to accept multipart data (e.g. consult a registered users upload allowance)

    Default is 128 * 1024 * 1024 bytes

        cgi=CGI.new(:max_multipart_length => 268435456) # simple scalar

        cgi=CGI.new(:max_multipart_length => -> {check_filesystem}) # lambda

`block`

  If provided, the block is called when an invalid encoding is encountered. For example:

      encoding_errors={}
      cgi=CGI.new(:accept_charset=>"EUC-JP") do |name,value|
        encoding_errors[name] = value
      end

Finally, if the `CGI` object is not created in a standard `CGI` call environment (that is, it can’t locate REQUEST_METHOD in its environment), then it will run in “offline” mode. In this mode, it reads its parameters from the command line or (failing that) from standard input. Otherwise, cookies and other parameters are parsed automatically from the standard `CGI` locations, which varies according to the REQUEST_METHOD.

    # File lib/cgi/core.rb, line 850
    def initialize(options = {}, &block) # :yields: name, value
      @accept_charset_error_block = block_given? ? block : nil
      @options={
        :accept_charset=>@@accept_charset,
        :max_multipart_length=>@@max_multipart_length
      }
      case options
      when Hash
        @options.merge!(options)
      when String
        @options[:tag_maker]=options
      end
      @accept_charset=@options[:accept_charset]
      @max_multipart_length=@options[:max_multipart_length]
      if defined?(MOD_RUBY) && !ENV.key?("GATEWAY_INTERFACE")
        Apache.request.setup_cgi_env
      end

      extend QueryExtension
      @multipart = false

      initialize_query()  # set @params, @cookies
      @output_cookies = nil
      @output_hidden = nil

      case @options[:tag_maker]
      when "html3"
        require_relative 'html'
        extend Html3
        extend HtmlExtension
      when "html4"
        require_relative 'html'
        extend Html4
        extend HtmlExtension
      when "html4Tr"
        require_relative 'html'
        extend Html4Tr
        extend HtmlExtension
      when "html4Fr"
        require_relative 'html'
        extend Html4Tr
        extend Html4Fr
        extend HtmlExtension
      when "html5"
        require_relative 'html'
        extend Html5
        extend HtmlExtension
      end
    end

parse(query) click to toggle source

Parse an HTTP query string into a hash of key=>value pairs.

    params = CGI.parse("query_string")
      # {"name1" => ["value1", "value2", ...],
      #  "name2" => ["value1", "value2", ...], ... }

    # File lib/cgi/core.rb, line 393
    def self.parse(query)
      params = {}
      query.split(/[&;]/).each do |pairs|
        key, value = pairs.split('=',2).collect{|v| CGI.unescape(v) }

        next unless key

        params[key] ||= []
        params[key].push(value) if value
      end

      params.default=[].freeze
      params
    end

### Public Instance Methods

header
Alias for: http_header
http_header
Also aliased as: header
out(content_type_string='text/html') click to toggle source
out(headers_hash)

Print an HTTP header and body to $DEFAULT_OUTPUT ($>)

`content_type_string`

  If a string is passed, it is assumed to be the content type.

`headers_hash`

  This is a `Hash` of headers, similar to that used by `http_header`.

`block`

  A block is required and should evaluate to the body of the response.

`Content-Length` is automatically calculated from the size of the `String` returned by the content block.

If `ENV['REQUEST_METHOD'] == "HEAD"`, then only the header is output (the content block is still required, but it is ignored).

If the charset is “iso-2022-jp” or “euc-jp” or “shift_jis” then the content is converted to this charset, and the language is set to “ja”.

Example:

    cgi = CGI.new
    cgi.out{ "string" }
      # Content-Type: text/html
      # Content-Length: 6
      #
      # string

    cgi.out("text/plain") { "string" }
      # Content-Type: text/plain
      # Content-Length: 6
      #
      # string

    cgi.out("nph"        => true,
            "status"     => "OK",  # == "200 OK"
            "server"     => ENV['SERVER_SOFTWARE'],
            "connection" => "close",
            "type"       => "text/html",
            "charset"    => "iso-2022-jp",
              # Content-Type: text/html; charset=iso-2022-jp
            "language"   => "ja",
            "expires"    => Time.now + (3600 * 24 * 30),
            "cookie"     => [cookie1, cookie2],
            "my_header1" => "my_value",
            "my_header2" => "my_value") { "string" }
       # HTTP/1.1 200 OK
       # Date: Sun, 15 May 2011 17:35:54 GMT
       # Server: Apache 2.2.0
       # Connection: close
       # Content-Type: text/html; charset=iso-2022-jp
       # Content-Length: 6
       # Content-Language: ja
       # Expires: Tue, 14 Jun 2011 17:35:54 GMT
       # Set-Cookie: foo
       # Set-Cookie: bar
       # my_header1: my_value
       # my_header2: my_value
       #
       # string

    # File lib/cgi/core.rb, line 367
    def out(options = "text/html") # :yield:

      options = { "type" => options } if options.kind_of?(String)
      content = yield
      options["length"] = content.bytesize.to_s
      output = stdoutput
      output.binmode if defined? output.binmode
      output.print http_header(options)
      output.print content unless "HEAD" == env_table['REQUEST_METHOD']
    end

print(*options) click to toggle source

Print an argument or list of arguments to the default output stream

    cgi = CGI.new
    cgi.print    # default:  cgi.print == $DEFAULT_OUTPUT.print

    # File lib/cgi/core.rb, line 383
    def print(*options)
      stdoutput.print(*options)
    end

### Private Instance Methods

_no_crlf_check(str) click to toggle source

    # File lib/cgi/core.rb, line 191
    def _no_crlf_check(str)
      if str
        str = str.to_s
        raise "A HTTP status or header field must not include CR and LF" if str =~ /[\r\n]/
        str
      else
        nil
      end
    end

env_table() click to toggle source

Synonym for `ENV`.

    # File lib/cgi/core.rb, line 59
    def env_table
      ENV
    end

stdinput() click to toggle source

Synonym for $stdin.

    # File lib/cgi/core.rb, line 64
    def stdinput
      $stdin
    end

stdoutput() click to toggle source

Synonym for $stdout.

    # File lib/cgi/core.rb, line 69
    def stdoutput
      $stdout
    end