CGI 类
概述¶ ↑
通用网关接口 (CGI
) 是一个简单的协议,用于将 HTTP 请求从 Web 服务器传递到独立程序,并将输出返回到 Web 浏览器。基本上,CGI
程序使用在环境 (GET) 或通过 $stdin (POST) 中传递的请求参数进行调用,并且它打印到 $stdout 的所有内容都会返回给客户端。
此文件包含 CGI
类。此类提供用于检索 HTTP 请求参数、管理 Cookie 和生成 HTML 输出的功能。
文件 CGI::Session
提供会话管理功能;有关更多详细信息,请参阅该类。
有关 CGI
协议的更多信息,请参阅 www.w3.org/CGI/。
简介¶ ↑
CGI
是一个大型类,提供几类方法,其中很多都从其他模块混合而来。一些文档位于此类中,一些位于模块 CGI::QueryExtension
和 CGI::HtmlExtension
中。有关处理 cookie 的具体信息,请参阅 CGI::Cookie
,有关会话的信息,请参阅 cgi/session.rb (CGI::Session
)。
对于查询,CGI
提供方法来获取环境变量、参数、cookie 和多部分请求数据。对于响应,CGI
提供用于编写输出和生成 HTML 的方法。
请继续阅读以了解详细信息。示例在底部提供。
查询¶ ↑
CGI
类动态混合了参数和 cookie 解析功能、环境变量访问以及对从 CGI::QueryExtension
模块解析多部分请求(包括上传的文件)的支持。
环境变量¶ ↑
标准 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_length
和 server_port
是整数;其余是字符串。
参数¶ ↑
方法 params() 返回请求中所有参数的哈希,作为名称/值列表对,其中值列表是包含一个或多个值的 Array
。CGI
对象本身也表现为参数名称到值的哈希,但每个参数名称只返回一个值(作为 String
)。
例如,假设请求包含参数“favourite_colours”,其值有多个“blue”和“green”。将出现以下行为
cgi.params["favourite_colours"] # => ["blue", "green"] cgi["favourite_colours"] # => "blue"
如果参数不存在,前一种方法将返回一个空数组,后一种方法将返回一个空字符串。测试参数是否存在的最简单方法是 has_key? 方法。
Cookie¶ ↑
HTTP Cookie 会自动从请求中进行解析。它们可通过 cookies() 访问器获得,该访问器会返回一个哈希,其中包含 cookie 名称到 CGI::Cookie
对象的映射。
多部分请求¶ ↑
如果请求的方法为 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 生成模块知道哪些元素始终为空,并会自动丢弃任何传入的正文。它还知道哪些元素需要匹配的结束标签,哪些不需要。但是,它不知道哪些属性对哪些元素是合法的。
还有一些其他 HTML 生成方法,它们混合自 CGI::HtmlExtension
模块。其中包括用于不同类型表单输入的各个方法,以及用于通常采用特定属性的元素的方法,其中属性可以直接指定为参数,而不是通过哈希。
实用程序 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['field_name']
返回一个 Array
,其中包含旧的 cgi.rb(包含在 Ruby 1.6 中)
以哈希形式获取表单值¶ ↑
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
获取多部分表单值¶ ↑
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
并且值具有 StringIO
或 Tempfile
类方法。
获取 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
常量
属性
返回此 CGI
实例的接受字符集。
公共类方法
返回所有新 CGI
实例的接受字符集。
# File lib/cgi/core.rb, line 759 def self.accept_charset @@accept_charset end
创建一个新的 CGI
实例。
tag_maker
-
这与使用带有值
{ :tag_maker => tag_maker }
的options_hash
表单相同。请注意,建议使用options_hash
表单,因为它还允许您指定您将接受的字符集。 options_hash
-
识别三个选项的
Hash
:accept_charset
-
指定接收到的查询字符串的编码。如果省略,则使用
@@accept_charset
。如果编码无效,则会引发CGI::InvalidEncoding
。示例。假设
@@accept_charset
为“UTF-8”未指定时
cgi=CGI.new # @accept_charset # => "UTF-8"
指定为“EUC-JP”时
cgi=CGI.new(:accept_charset => "EUC-JP") # => "EUC-JP"
:tag_maker
-
String
,指定要使用的 HTML 生成方法的版本。如果未指定,则不会加载任何 HTML 生成方法。支持以下值
- “html3”
-
HTML 3.x
- “html4”
-
HTML 4.0
- “html4Tr”
-
过渡性 HTML 4.0
- “html4Fr”
-
带框架的 HTML 4.0
- “html5”
-
HTML 5
:max_multipart_length
-
指定多部分数据的最大长度。可以是
Integer
标量或 lambda,将在解析请求时对其进行评估。这允许在确定是否接受多部分数据时设置更复杂的逻辑(例如,咨询已注册用户的上传配额)默认值为 128 * 1024 * 1024 字节
cgi=CGI.new(:max_multipart_length => 268435456) # simple scalar cgi=CGI.new(:max_multipart_length => -> {check_filesystem}) # lambda
block
-
如果提供,则在遇到无效编码时调用此块。例如
encoding_errors={} cgi=CGI.new(:accept_charset=>"EUC-JP") do |name,value| encoding_errors[name] = value end
最后,如果 CGI
对象不是在标准 CGI
调用环境中创建的(即,它无法在其环境中找到 REQUEST_METHOD),那么它将在“脱机”模式下运行。在此模式下,它从命令行或(如果失败)从标准输入读取其参数。否则,cookie 和其他参数会根据 REQUEST_METHOD 从标准 CGI
位置自动解析,该位置因 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
将 HTTP 查询字符串解析为 key=>value 对的哈希。
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
公共实例方法
将 HTTP 头和正文打印到 $DEFAULT_OUTPUT ($>)
content_type_string
-
如果传递字符串,则假定它是内容类型。
headers_hash
-
这是一个
Hash
头,类似于http_header
使用的头。 block
-
需要一个块,并应评估为响应的主体。
Content-Length
会根据内容块返回的 String
的大小自动计算。
如果 ENV['REQUEST_METHOD'] == "HEAD"
,则只输出标题(仍然需要内容块,但会忽略它)。
如果字符集是“iso-2022-jp”或“euc-jp”或“shift_jis”,则内容会转换为此字符集,并且语言设置为“ja”。
示例
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
将参数或参数列表打印到默认输出流
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
私有实例方法
# 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
的同义词。
# File lib/cgi/core.rb, line 59 def env_table ENV end
$stdin 的同义词。
# File lib/cgi/core.rb, line 64 def stdinput $stdin end
$stdout 的同义词。
# File lib/cgi/core.rb, line 69 def stdoutput $stdout end