class CGI

概述

通用网关接口(CGI)是一个简单的协议,用于将 HTTP 请求从 Web 服务器传递到独立的程序,并将输出返回到 Web 浏览器。基本上,CGI 程序被调用时,请求的参数要么通过环境变量(GET)传递,要么通过 $stdin (POST) 传递,并且它打印到 $stdout 的所有内容都将返回给客户端。

此文件包含 CGI 类。此类提供检索 HTTP 请求参数、管理 cookie 和生成 HTML 输出的功能。

文件 CGI::Session 提供会话管理功能;有关更多详细信息,请参阅该类。

有关 CGI 协议的更多信息,请参阅 www.w3.org/CGI/。

简介

CGI 是一个大型类,提供多种类别的方法,其中许多方法是从其他模块混合而来的。一些文档在此类中,一些文档在模块 CGI::QueryExtensionCGI::HtmlExtension 中。有关处理 cookie 的具体信息,请参阅 CGI::Cookie,有关会话的信息,请参阅 cgi/session.rb (CGI::Session)。

对于查询,CGI 提供了获取环境变量、参数、cookie 和 multipart 请求数据的方法。对于响应,CGI 提供了用于写入输出和生成 HTML 的方法。

请继续阅读以了解更多详细信息。示例在底部提供。

查询

CGI 类动态地混合了参数和 cookie 解析功能、环境变量访问以及对来自 CGI::QueryExtension 模块的 multipart 请求(包括上传的文件)进行解析的支持。

环境变量

标准的 CGI 环境变量可作为 CGI 对象的只读属性使用。以下是这些变量的列表

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

对于这些变量中的每一个,都有一个对应的属性,名称相同,只是全部小写,并且没有前缀 HTTP_。content_lengthserver_port 是整数;其余的是字符串。

参数

方法 params() 返回请求中所有参数的哈希,形式为名称/值列表对,其中值列表是包含一个或多个值的 ArrayCGI 对象本身也表现为参数名称到值的哈希,但每个参数名称仅返回单个值(作为 String)。

例如,假设请求包含参数 “favourite_colours”,其多个值为 “blue” 和 “green”。将发生以下行为

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

如果参数不存在,前一种方法将返回一个空数组,后一种方法将返回一个空字符串。测试参数是否存在的最简单方法是使用 has_key? 方法。

Cookies

HTTP Cookies 会自动从请求中解析。它们可以从 cookies() 访问器获得,该访问器返回从 cookie 名称到 CGI::Cookie 对象的哈希。

Multipart 请求

如果请求的方法是 POST,并且其内容类型是 multipart/form-data,则它可能包含上传的文件。这些文件由 QueryExtension 模块存储在请求的参数中。参数名称是文件输入字段的 name 属性,和往常一样。但是,该值不是字符串,而是 IO 对象,对于小文件是 IOString,对于大文件是 Tempfile。此对象还具有以下额外的单例方法

local_path()

本地文件系统上上传文件的路径

original_filename()

客户端计算机上的文件名

content_type()

文件的内容类型

响应

CGI 类提供用于将头部和内容输出发送到 HTTP 客户端的方法,并混合了来自 CGI::HtmlExtension 和 CGI::TagMaker 模块的用于以编程方式生成 HTML 的方法。用于 HTML 生成的 HTML 的精确版本是在对象创建时指定的。

写入输出

将输出发送到 HTTP 客户端的最简单方法是使用 out() 方法。这会将 HTTP 头部作为哈希参数,并通过代码块获取正文内容。可以使用 http_header() 方法将头部生成为字符串。可以使用 print() 方法直接写入输出流。

生成 HTML

每个 HTML 元素都有一个对应的方法,用于将该元素生成为 String。此方法的名称与该元素的名称相同,全部小写。元素的属性作为哈希传递,正文作为求值为 String 的无参数代码块传递。HTML 生成模块知道哪些元素始终为空,并静默删除任何传入的正文。它还知道哪些元素需要匹配的结束标记,哪些不需要。但是,它不知道哪些属性对于哪些元素是合法的。

还有一些来自 CGI::HtmlExtension 模块的额外的 HTML 生成方法混合进来。其中包括用于不同类型的表单输入的各个方法,以及用于通常需要特定属性的元素的方法,其中属性可以直接指定为参数,而不是通过哈希指定。

实用 HTML 转义和其他类似函数的方法。

在 cgi/util.rb 中定义了一些实用工具。当包含时,可以使用类似函数的实用方法。

使用示例

获取表单值

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')

注意!旧的 cgi.rb(包含在 Ruby 1.6 中)返回一个 Array

以哈希形式获取表单值

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

cgi.params 是一个哈希。

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

将表单值保存到文件

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

从文件恢复表单值

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

获取 multipart 表单值

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

并且值具有 StringIOTempfile 类方法。

获取 cookie 值

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

并且 cgi.cookies 是一个哈希。

获取 cookie 对象

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"}

将 HTTP 头部和 HTML 字符串打印到 $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

一些实用方法

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

一些类似函数的实用方法

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