class 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 和 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_length
和 server_port
是整数;其余的是字符串。
参数¶ ↑
方法 params() 返回请求中所有参数的哈希,形式为名称/值列表对,其中值列表是包含一个或多个值的 Array
。CGI
对象本身也表现为参数名称到值的哈希,但每个参数名称仅返回单个值(作为 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
并且值具有 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
实例的接受字符集。
公共类方法
来源
# File lib/cgi/core.rb, line 759 def self.accept_charset @@accept_charset end
返回所有新的 CGI
实例的接受字符集。
来源
来源
# 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
创建一个新的 CGI
实例。
tag_maker
-
这与使用
options_hash
形式且值为{ :tag_maker => tag_maker }
相同。请注意,建议使用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
-
字符串
,指定要使用的 HTML 生成方法的版本。如果未指定,则不会加载任何 HTML 生成方法。支持以下值
- “html3”
-
HTML 3.x
- “html4”
-
HTML 4.0
- “html4Tr”
-
HTML 4.0 Transitional
- “html4Fr”
-
具有框架集的 HTML 4.0
- “html5”
-
HTML 5
:max_multipart_length
-
指定多部分数据的最大长度。可以是
整数
标量或 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 和其他参数会自动从标准的 CGI
位置解析,这会根据 REQUEST_METHOD 而变化。
来源
# 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 查询字符串解析为键=>值对的哈希。
params = CGI.parse("query_string") # {"name1" => ["value1", "value2", ...], # "name2" => ["value1", "value2", ...], ... }
公共实例方法
来源
# 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
将 HTTP 标头和正文打印到 $DEFAULT_OUTPUT ($>)
content_type_string
-
如果传递字符串,则假定为内容类型。
headers_hash
-
这是一个标头的
Hash
,类似于http_header
使用的标头。 block
-
需要一个块,并且应该计算为响应的正文。
Content-Length
会自动从内容块返回的 字符串
的大小计算得出。
如果 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 383 def print(*options) stdoutput.print(*options) end
将一个或多个参数打印到默认输出流
cgi = CGI.new cgi.print # default: cgi.print == $DEFAULT_OUTPUT.print
私有实例方法
来源
# 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