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() 返回请求中所有参数的哈希,作为名称/值列表对,其中值列表是一个或多个值的数组。 CGI
对象本身也表现为参数名称到值的哈希,但每个参数名称仅返回一个值(作为字符串)。
例如,假设请求包含多个值为“蓝色”和“绿色”的参数“favourite_colours”。将发生以下行为
cgi.params["favourite_colours"] # => ["blue", "green"] cgi["favourite_colours"] # => "blue"
如果参数不存在,则前一种方法将返回一个空数组,后一种方法返回一个空字符串。测试参数是否存在的 最简单方法是使用 has_key? 方法。
Cookies¶ ↑
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 元素都有一个对应的方法,用于将该元素生成为字符串。此方法的名称与元素的名称相同,全部小写。元素的属性作为哈希传入,正文作为不带参数的块,该块的计算结果为字符串。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']
返回一个带有旧 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
并且 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
常量
- CR
回车符的字符串
- EOL
标准 Internet 换行符序列
- HTTP_STATUS
HTTP 状态代码。
- LF
换行符的字符串
- MAX_MULTIPART_COUNT
多部分时请求参数的最大数量
- NEEDS_BINMODE
是否需要在二进制与文本中处理
- PATH_SEPARATOR
不同环境中的路径分隔符。
- VERSION
属性
返回此 CGI
实例的接受字符集。
公共类方法
返回所有新 CGI
实例的接受字符集。
# File cgi/core.rb, line 759 def self.accept_charset @@accept_charset end
设置所有新 CGI
实例的接受字符集。
# File cgi/core.rb, line 764 def self.accept_charset=(accept_charset) @@accept_charset=accept_charset 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 过渡
- “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 和其他参数将根据 REQUEST_METHOD 自动从标准 CGI
位置解析,该位置因 REQUEST_METHOD 而异。
# File 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 查询字符串解析为键=>值对的哈希。
params = CGI.parse("query_string") # {"name1" => ["value1", "value2", ...], # "name2" => ["value1", "value2", ...], ... }
# File 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
公共实例方法
当 HTML5
标签生成器处于非活动状态时,此方法是 http_header
的别名。
注意:使用 http_header
创建 HTTP 头部块,此别名仅为向后兼容而提供。
创建一个 HTTP 头部块作为字符串。
包含结束头部块的空行。
content_type_string
-
如果使用此形式,则此字符串是
Content-Type
headers_hash
-
头部值的哈希。以下头部键被识别
- type
-
Content-Type 头部。默认为 “text/html”
- charset
-
正文的字符集,附加到 Content-Type 头部。
- nph
-
一个布尔值。如果为 true,则前置协议字符串和状态码以及日期;并为 “server” 和 “connection” 设置默认值(如果未显式设置)。
- status
-
作为 Status 头部返回的 HTTP 状态码(字符串)。这些值是
- 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
-
服务器软件,作为 Server 头部返回。
- connection
-
连接类型,作为 Connection 头部返回(例如,“close”)。
- length
-
将要发送的内容长度,作为 Content-Length 头部返回。
- language
-
内容的语言,作为 Content-Language 头部返回。
- expires
-
当前内容过期的时机,作为
Time
对象,作为 Expires 头部返回。 - cookie
-
一个或多个 cookie,作为一或多个 Set-Cookie 头部返回。值可以是 cookie 的字面字符串;一个
CGI::Cookie
对象;字面 cookie 字符串或Cookie
对象的数组;或者所有值都是字面 cookie 字符串或Cookie
对象的哈希。这些 cookie 是 @output_cookies 字段中保存的 cookie 的补充。
还可以设置其他头部;它们以 key: value 的形式附加。
示例
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")
此方法不执行字符集转换。
# File 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
将 HTTP 头部和正文打印到 $DEFAULT_OUTPUT ($>)
content_type_string
-
如果传递的是字符串,则假定为内容类型。
headers_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 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 cgi/core.rb, line 383 def print(*options) stdoutput.print(*options) end
私有实例方法
# File 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 cgi/core.rb, line 59 def env_table ENV end
$stdin 的同义词。
# File cgi/core.rb, line 64 def stdinput $stdin end
$stdout 的同义词。
# File cgi/core.rb, line 69 def stdoutput $stdout end