在线文档教程
Ruby 2.4

CGI::QueryExtension

module CGI::QueryExtension

Mixin模块提供以下功能:

  • 作为方法访问CGI环境变量。有关这些变量的列表,请参阅CGI类的文档。通过删除前导HTTP_(如果存在)并降低名称来暴露这些方法。例如,auth_type将返回环境变量AUTH_TYPEaccept并将返回值HTTP_ACCEPT

2. 访问cookie,包括cookie属性。

3. 访问参数,包括params属性,并重载[]以通过键执行参数值查找。

4. #initialize_query方法用于初始化上述机制,处理多部分表单以及允许在“脱机”模式下使用该类。

属性

cookiesRW

获取cookie作为cookie-name => Cookie对的散列。

filesR

将上传的文件作为名称=>值对的散列

paramsR

获取参数作为name => values对的散列值,其中values是一个Array。

公共实例方法

显示来源

用给定的键获取参数的值。

如果该参数具有多个值,则仅检索第一个值; 使用参数来获取值的数组。

# File lib/cgi/core.rb, line 694 def [](key) params = @params[key] return '' unless params value = params[0] if @multipart if value return value elsif defined? StringIO StringIO.new("".force_encoding(Encoding::ASCII_8BIT)) else Tempfile.new("CGI",encoding: Encoding::ASCII_8BIT) end else str = if value then value.dup else "" end str end end

has_key?(*args) Show source

如果给定的查询字符串参数存在,则返回true。

# File lib/cgi/core.rb, line 718 def has_key?(*args) @params.has_key?(*args) end

还有别名:key ?,包括?

include?(*args)

Alias for: has_key?

key?(*args)

Alias for: has_key?

keys(*args) Show source

将所有查询参数名称返回为String数组。

# File lib/cgi/core.rb, line 713 def keys(*args) @params.keys(*args) end

multipart?()显示源文件

返回表单是否包含multipart / form-data

# File lib/cgi/core.rb, line 686 def multipart? @multipart end

params=(hash) 显示源文件

设置所有参数。

# File lib/cgi/core.rb, line 455 def params=(hash) @params.clear @params.update(hash) end

raw_cookie()显示源文件

将原始cookie作为字符串获取。

# File lib/cgi/core.rb, line 435 def raw_cookie env_table["HTTP_COOKIE"] end

raw_cookie2()显示源文件

将原始RFC2965 Cookie作为字符串获取。

# File lib/cgi/core.rb, line 440 def raw_cookie2 env_table["HTTP_COOKIE2"] end

私有实例方法

initialize_query()显示源文件

一个包装类,用于将StringIO对象作为主体,并在传入阈值时切换到TempFile。初始化查询中的数据。

处理多部分表单(特别是涉及文件上传的表单)。在@params字段中读取查询参数,并将cookie写入@cookies。

# File lib/cgi/core.rb, line 641 def initialize_query() if ("POST" == env_table['REQUEST_METHOD']) and %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?|.match(env_table['CONTENT_TYPE']) current_max_multipart_length = @max_multipart_length.respond_to?(:call) ? @max_multipart_length.call : @max_multipart_length raise StandardError.new("too large multipart data.") if env_table['CONTENT_LENGTH'].to_i > current_max_multipart_length boundary = $1.dup @multipart = true @params = read_multipart(boundary, Integer(env_table['CONTENT_LENGTH'])) else @multipart = false @params = CGI::parse( case env_table['REQUEST_METHOD'] when "GET", "HEAD" if defined?(MOD_RUBY) Apache::request.args or "" else env_table['QUERY_STRING'] or "" end when "POST" stdinput.binmode if defined? stdinput.binmode stdinput.read(Integer(env_table['CONTENT_LENGTH'])) or '' else read_from_cmdline end.dup.force_encoding(@accept_charset) ) unless Encoding.find(@accept_charset) == Encoding::ASCII_8BIT @params.each do |key,values| values.each do |value| unless value.valid_encoding? if @accept_charset_error_block @accept_charset_error_block.call(key,value) else raise InvalidEncoding,"Accept-Charset encoding error" end end end end end end @cookies = CGI::Cookie::parse((env_table['HTTP_COOKIE'] or env_table['COOKIE'])) end

read_from_cmdline()显示源文件

离线模式。在标准输入上读取名称=值对。

# File lib/cgi/core.rb, line 606 def read_from_cmdline require "shellwords" string = unless ARGV.empty? ARGV.join(' ') else if STDIN.tty? STDERR.print( %Q|(offline mode: enter name=value pairs on standard input)\n| ) end array = readlines rescue nil if not array.nil? array.join(' ').gsub(/\n/n, '') else "" end end.gsub(/\=/n, '%3D').gsub(/\&/n, '%26') words = Shellwords.shellwords(string) if words.find{|x| /=/n.match(x) } words.join('&') else words.join('+') end end

read_multipart(boundary, content_length)显示源

根据分析多部分表单元素

http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.2

根据多部分表单元素是否超过10 KB,返回多部分表单参数与StringIO或Tempfile类型主体的散列

params[name => body]

# File lib/cgi/core.rb, line 469 def read_multipart(boundary, content_length) ## read first boundary stdin = stdinput first_line = "--#{boundary}#{EOL}" content_length -= first_line.bytesize status = stdin.read(first_line.bytesize) raise EOFError.new("no content body") unless status raise EOFError.new("bad content body") unless first_line == status ## parse and set params params = {} @files = {} boundary_rexp = /--#{Regexp.quote(boundary)}(#{EOL}|--)/ boundary_size = "#{EOL}--#{boundary}#{EOL}".bytesize buf = '' bufsize = 10 * 1024 max_count = MAX_MULTIPART_COUNT n = 0 tempfiles = [] while true (n += 1) < max_count or raise StandardError.new("too many parameters.") ## create body (StringIO or Tempfile) body = create_body(bufsize < content_length) tempfiles << body if defined?(Tempfile) && body.kind_of?(Tempfile) class << body if method_defined?(:path) alias local_path path else def local_path nil end end attr_reader :original_filename, :content_type end ## find head and boundary head = nil separator = EOL * 2 until head && matched = boundary_rexp.match(buf) if !head && pos = buf.index(separator) len = pos + EOL.bytesize head = buf[0, len] buf = buf[(pos+separator.bytesize)..-1] else if head && buf.size > boundary_size len = buf.size - boundary_size body.print(buf[0, len]) buf[0, len] = '' end c = stdin.read(bufsize < content_length ? bufsize : content_length) raise EOFError.new("bad content body") if c.nil? || c.empty? buf << c content_length -= c.bytesize end end ## read to end of boundary m = matched len = m.begin(0) s = buf[0, len] if s =~ /(\r?\n)\z/ s = buf[0, len - $1.bytesize] end body.print(s) buf = buf[m.end(0)..-1] boundary_end = m[1] content_length = -1 if boundary_end == '--' ## reset file cursor position body.rewind ## original filename /Content-Disposition:.* filename=(?:"(.*?)"|([^;\r\n]*))/i.match(head) filename = $1 || $2 || '' filename = CGI.unescape(filename) if unescape_filename?() body.instance_variable_set(:@original_filename, filename.taint) ## content type /Content-Type: (.*)/i.match(head) (content_type = $1 || '').chomp! body.instance_variable_set(:@content_type, content_type.taint) ## query parameter name /Content-Disposition:.* name=(?:"(.*?)"|([^;\r\n]*))/i.match(head) name = $1 || $2 || '' if body.original_filename.empty? value=body.read.dup.force_encoding(@accept_charset) body.close! if defined?(Tempfile) && body.kind_of?(Tempfile) (params[name] ||= []) << value unless value.valid_encoding? if @accept_charset_error_block @accept_charset_error_block.call(name,value) else raise InvalidEncoding,"Accept-Charset encoding error" end end class << params[name].last;self;end.class_eval do define_method(:read){self} define_method(:original_filename){""} define_method(:content_type){""} end else (params[name] ||= []) << body @files[name]=body end ## break loop break if content_length == -1 end raise EOFError, "bad boundary end of body part" unless boundary_end =~ /--/ params.default = [] params rescue Exception if tempfiles tempfiles.each {|t| if t.path t.close! end } end raise end