類別 CGI
概述¶ ↑
通用閘道介面 (CGI
) 是一種簡單的協定,用於將 HTTP 要求從網路伺服器傳遞至獨立程式,並將輸出傳回至網路瀏覽器。基本上,CGI
程式會使用在環境 (GET) 或透過 $stdin (POST) 傳遞的請求參數來呼叫,而它列印至 $stdout 的所有內容都會傳回至客戶端。
這個檔案包含 CGI
類別。這個類別提供用於擷取 HTTP 請求參數、管理 Cookie 和產生 HTML 輸出的功能。
檔案 CGI::Session
提供階段管理功能;請參閱該類別以取得更多詳細資料。
請參閱 www.w3.org/CGI/ 以取得有關 CGI
協定的更多資訊。
簡介¶ ↑
CGI
是個大型類別,提供多種類別的方法,其中許多方法都混合自其他模組。有些文件說明在這個類別中,有些在 CGI::QueryExtension
和 CGI::HtmlExtension
模組中。請參閱 CGI::Cookie
以取得有關處理 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」。會發生下列行為
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
區塊
-
如果提供,則在遇到無效編碼時呼叫區塊。例如
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 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
使用的標頭。 區塊
-
需要區塊,且應評估為回應的本文。
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