CGI
CGI类
Parent:Object
概观
通用网关接口(CGI)是一种简单的协议,用于将来自Web服务器的HTTP请求传递给独立程序,并将输出返回到Web浏览器。基本上,在环境(GET)或通过$ stdin(POST)传递的请求参数中调用CGI程序,并且打印到$ 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对象本身也表现为参数名称到值的哈希值,但仅为每个参数名称返回单个值(作为字符串)。
例如,假设请求包含带有多个值“blue”和“green”的参数“favourite_colours”。以下行为会发生:
cgi.params["favourite_colours"] # => ["blue", "green"]
cgi["favourite_colours"] # => "blue"
如果参数不存在,则前一个方法将返回一个空数组,后一个空字符串。测试参数存在的最简单方法是使用has_key?方法。
Cookies
HTTP Cookies将自动从请求中解析出来。它们可以从cookies()访问器获得,该访问器从cookie名称返回一个哈希到CGI :: Cookie对象。
多部分请求
如果请求的方法是POST并且其内容类型是multipart / form-data,那么它可能包含上传的文件。这些由QueryExtension模块存储在请求的参数中。像往常一样,参数名称是文件输入字段的名称属性。但是,该值不是一个字符串,而是一个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使用旧的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
常量
CR
用于回车的字符串
EOL
标准的互联网新行顺序
HTTP_STATUS
HTTP status codes.
LF
换行的字符串
MAX_MULTIPART_COUNT
multipart时请求参数的最大数目
NEEDS_BINMODE
在二进制文本中是否需要处理
PATH_SEPARATOR
路径分隔符在不同的环境中。
属性
accept_charsetR
返回此CGI实例的接受字符集。
公共类方法
accept_charset()显示源文件
返回所有新CGI实例的接受字符集。
# File lib/cgi/core.rb, line 739
def self.accept_charset
@@accept_charset
end
accept_charset =(accept_charset)显示源文件
为所有新的CGI实例设置接受字符集。
# File lib/cgi/core.rb, line 744
def self.accept_charset=(accept_charset)
@@accept_charset=accept_charset
end
new(tag_maker) { block } 显示源文件
new(options_hash = {}) { block }
创建一个新的CGI实例。
tag_maker
这与使用options_hash具有值的表单相同。{ :tag_maker => tag_maker }请注意,建议使用options_hash表单,因为它还允许指定您将接受的字符集。
options_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),那么它将以“脱机”模式运行。在此模式下,它从命令行读取参数或从标准输入读取(失败)参数。否则,cookies和其他参数将从标准CGI位置自动分析,这取决于REQUEST_METHOD。
# File lib/cgi/core.rb, line 830
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 'cgi/html'
extend Html3
extend HtmlExtension
when "html4"
require 'cgi/html'
extend Html4
extend HtmlExtension
when "html4Tr"
require 'cgi/html'
extend Html4Tr
extend HtmlExtension
when "html4Fr"
require 'cgi/html'
extend Html4Tr
extend Html4Fr
extend HtmlExtension
when "html5"
require 'cgi/html'
extend Html5
extend HtmlExtension
end
end
parse(query) Show source
将HTTP查询字符串解析为key =>值对的散列。
params = CGI::parse("query_string")
# {"name1" => ["value1", "value2", ...],
# "name2" => ["value1", "value2", ...], ... }
# File lib/cgi/core.rb, line 374
def CGI::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
公共实例方法
header(options='text/html')
当HTML5标记制作器处于非活动状态时,此方法是http_header的别名。
注:使用http_header创建HTTP头块,此别名仅用于向后兼容。
使用标头与HTML5标签制造商将创建一个<header>元素。
别名为:http_header
http_header(content_type_string="text/html") Show source
http_header(headers_hash)
创建一个HTTP标头块作为一个字符串。
包含结束标题块的空行。
content_type_string
如果使用这种形式,这个字符串就是 Content-Type
headers_hash
标头值的哈希值。以下标题键被识别:
type
Content-Type标头。默认为“text / html”
charset
附加到Content-Type标题的正文的字符集。
nph
一个布尔值。如果为true,则预先输入协议字符串和状态代码以及日期; 如果未明确设置,则为“服务器”和“连接”设置默认值。
status
HTTP状态码作为字符串返回,作为状态头。这些值是:
OK
200 OK
PARTIAL_CONTENT
206部分内容
MULTIPLE_CHOICES
300多种选择
MOVED
301永久移动
REDIRECT
302 Found
NOT_MODIFIED
304未修改
BAD_REQUEST
400错误请求
AUTH_REQUIRED
401需要授权
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
作为一个或多个Set-Cookie标题返回的Cookie或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 lib/cgi/core.rb, line 152
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
另外别名为:标题
out(content_type_string='text/html') Show source
out(headers_hash)
将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 lib/cgi/core.rb, line 348
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) Show source
将参数或参数列表打印到默认输出流
cgi = CGI.new
cgi.print # default: cgi.print == $DEFAULT_OUTPUT.print
# File lib/cgi/core.rb, line 364
def print(*options)
stdoutput.print(*options)
end
私有实例方法
env_table() Show source
ENV的同义词。
# File lib/cgi/core.rb, line 51
def env_table
ENV
end
stdinput() Show source
$ stdin的同义词。
# File lib/cgi/core.rb, line 56
def stdinput
$stdin
end
stdoutput() Show source
$ stdout的同义词。
# File lib/cgi/core.rb, line 61
def stdoutput
$stdout
end