# 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(options='text/html')

This method is an alias for `http_header`, when `HTML5` tag maker is inactive.

NOTE: use `http_header` to create HTTP header blocks, this alias is only provided for backwards compatibility.

Using `header` with the `HTML5` tag maker will create a <header> element.

Alias for: http_header
http_header(headers_hash) click to toggle source

Create an HTTP header block as a string.

Includes the empty line that ends the header block.

`content_type_string`

  If this form is used, this string is the `Content-Type`

`headers_hash`

  A `Hash` of header values. The following header keys are recognized:

  type

    The Content-Type header. Defaults to “text/html”

  charset

    The charset of the body, appended to the Content-Type header.

  nph

    A boolean value. If true, prepend protocol string and status code, and date; and sets default values for “server” and “connection” if not explicitly set.

  status

    The HTTP status code as a `String`, returned as the Status header. The values are:

    OK

      200 OK

    PARTIAL_CONTENT

      206 Partial Content

    MULTIPLE_CHOICES

      300 Multiple Choices

    MOVED

      301 Moved Permanently

    REDIRECT

      302 Found

    NOT_MODIFIED

      304 Not Modified

    BAD_REQUEST

      400 Bad Request

    AUTH_REQUIRED

      401 Authorization Required

    FORBIDDEN

      403 Forbidden

    NOT_FOUND

      404 Not Found

    METHOD_NOT_ALLOWED

      405 `Method` Not Allowed

    NOT_ACCEPTABLE

      406 Not Acceptable

    LENGTH_REQUIRED

      411 Length Required

    PRECONDITION_FAILED

      412 Precondition Failed

    SERVER_ERROR

      500 Internal Server Error

    NOT_IMPLEMENTED

      501 `Method` Not Implemented

    BAD_GATEWAY

      502 Bad Gateway

    VARIANT_ALSO_VARIES

      506 Variant Also Negotiates

  server

    The server software, returned as the Server header.

  connection

    The connection type, returned as the Connection header (for instance, “close”.

  length

    The length of the content that will be sent, returned as the Content-Length header.

  language

    The language of the content, returned as the Content-Language header.

  expires

    The time on which the current content expires, as a `Time` object, returned as the Expires header.

  cookie

    A cookie or cookies, returned as one or more Set-Cookie headers. The value can be the literal string of the cookie; a `CGI::Cookie` object; an `Array` of literal cookie strings or `Cookie` objects; or a hash all of whose values are literal cookie strings or `Cookie` objects.

    These cookies are in addition to the cookies held in the @output_cookies field.

  Other headers can also be set; they are appended as key: value.

Examples:

    http_header
      # Content-Type: text/html

    http_header("text/plain")
      # Content-Type: text/plain

    http_header("nph"        => true,
                "status"     => "OK",  # == "200 OK"
                  # "status"     => "200 GOOD",
                "server"     => ENV['SERVER_SOFTWARE'],
                "connection" => "close",
                "type"       => "text/html",
                "charset"    => "iso-2022-jp",
                  # Content-Type: text/html; charset=iso-2022-jp
                "length"     => 103,
                "language"   => "ja",
                "expires"    => Time.now + 30,
                "cookie"     => [cookie1, cookie2],
                "my_header1" => "my_value",
                "my_header2" => "my_value")

This method does not perform charset conversion.

    # File lib/cgi/core.rb, line 160
    def http_header(options='text/html')
      if options.is_a?(String)
        content_type = options
        buf = _header_for_string(content_type)
      elsif options.is_a?(Hash)
        if options.size == 1 && options.has_key?('type')
          content_type = options['type']
          buf = _header_for_string(content_type)
        else
          buf = _header_for_hash(options.dup)
        end
      else
        raise ArgumentError.new("expected String or Hash but got #{options.class}")
      end
      if defined?(MOD_RUBY)
        _header_for_modruby(buf)
        return ''
      else
        buf << EOL    # empty line of separator
        return buf
      end
    end

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