класс CGI
Обзор
Интерфейс общего шлюза (CGI) — это простой протокол для передачи запроса HTTP от веб-сервера к автономной программе и возврата результата в веб-браузер. В основном, программа 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, доступ к переменным среды и поддержку анализа запросов multipart (включая загруженные файлы) из модуля 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» со значениями «blue» и «green». Будет наблюдаться следующее поведение:
cgi.params["favourite_colours"] # => ["blue", "green"] cgi["favourite_colours"] # => "blue"
Если параметр не существует, первый метод вернёт пустой массив, второй — пустую строку. Самый простой способ проверить существование параметра — использовать метод has_key?.
Cookie
HTTP Cookie автоматически анализируются из запроса. Они доступны через аксессор cookies(), который возвращает хеш, где ключами являются имена cookie, а значениями — объекты CGI::Cookie.
Запросы multipart
Если метод запроса POST, а тип контента — multipart/form-data, он может содержать загруженные файлы. Модуль QueryExtension сохраняет их в параметрах запроса. Имя параметра — это атрибут name поля ввода файла, как обычно. Однако значение не является строкой, а объектом IO, либо IOString для небольших файлов, либо Tempfile для больших.
- local_path()
-
путь к загруженному файлу в локальной файловой системе
- original_filename()
-
имя файла на компьютере клиента
- content_type()
-
тип контента файла
Ответы
Класс CGI предоставляет методы для отправки заголовков и контента клиенту HTTP и включает методы для программированного генерации HTML из модулей CGI::HtmlExtension и CGI::TagMaker. Конкретная версия 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 вернул 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
Получение значений 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
Константы
- CR
-
Stringдля возврата каретки - EOL
-
Стандартная последовательность новой строки в интернете
- HTTP_STATUS
-
Коды состояния HTTP.
- LF
-
Stringдля перевода строки - MAX_MULTIPART_COUNT
-
Максимальное количество параметров запроса при использовании multipart
- NEEDS_BINMODE
-
Требуется ли обработка в бинарном или текстовом режиме
- PATH_SEPARATOR
-
Разделители путей в разных средах.
- VERSION
Атрибуты
Возвращает набор символов для данного экземпляра CGI.
Методы публичного класса
# File lib/cgi/core.rb, line 748 def self.accept_charset @@accept_charset end
Возвращает набор символов для всех новых экземпляров CGI.
# File lib/cgi/core.rb, line 753 def self.accept_charset=(accept_charset) @@accept_charset=accept_charset end
Устанавливает набор символов для всех новых экземпляров CGI.
# File lib/cgi/core.rb, line 839
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 -
Stringкоторый определяет, какую версию методов генерации 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 -
Устанавливает максимальную длину данных multipart. Может быть скалярным целым числом или лямбдой, которая будет вычислена при разборе запроса. Это позволяет задать более сложную логику при определении того, следует ли принимать данные multipart (например, обращаясь к разрешению на загрузку зарегистрированных пользователей).
По умолчанию 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 в своей среде), то он работает в режиме «офлайн». В этом режиме он считывает свои параметры из командной строки или (если нет) из стандартного ввода. В противном случае куки и другие параметры анализируются автоматически из стандартных мест CGI, что зависит от REQUEST_METHOD.
# File lib/cgi/core.rb, line 382
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-запроса в хэш пар key=>value.
params = CGI.parse("query_string")
# {"name1" => ["value1", "value2", ...],
# "name2" => ["value1", "value2", ...], ... }
Публичные методы экземпляра
Этот метод является псевдонимом для http_header, когда создатель тегов HTML5 не активен.
ПРИМЕЧАНИЕ: используйте http_header для создания блоков HTTP-заголовков, этот псевдоним предоставляется только для обратной совместимости.
Использование header с создателем тегов HTML5 создаст элемент <header>.
# File lib/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-заголовков в виде строки.
Включает пустую строку, которая завершает блок заголовков.
-
content_type_string -
Если используется этот формат, эта строка является
Content-Type -
headers_hash -
A
Hashзначений заголовков. Признаются следующие ключи заголовков:- type
-
Заголовок Content-Type. По умолчанию «text/html»
- charset
-
Кодировка символов тела, добавленная к заголовку Content-Type.
- nph
-
Логическое значение. Если истинно, добавляет строку протокола и код состояния, а также дату; и устанавливает значения по умолчанию для «server» и «connection», если они не заданы явно.
- status
-
Код HTTP-состояния в виде
String, возвращаемый в качестве заголовка Status. Значения:- 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
MethodNot 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
MethodNot 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 или несколько файлов cookie, возвращаемые в виде одного или нескольких заголовков Set-Cookie. Значение может быть строкой файла cookie; объектом
CGI::Cookie; массивомArrayстроковых значений файлов cookie или объектовCookie; или хешем, все значения которого являются строками файлов cookie или объектамиCookie.Эти файлы cookie дополняют файлы cookie, хранящиеся в поле @output_cookies.
Другие заголовки также могут быть установлены; они добавляются как ключ: значение.
Примеры:
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 356
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 автоматически вычисляется из размера String, возвращаемого блоком контента.
Если ENV['REQUEST_METHOD'] == "HEAD", то выводится только заголовок (блок контента всё ещё нужен, но он игнорируется).
Если кодировка символов «iso-2022-jp» или «euc-jp» или «shift_jis», то контент преобразуется в эту кодировку, а язык устанавливается в «яп».
Пример:
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 372 def print(*options) stdoutput.print(*options) end
Выводит аргумент или список аргументов в стандартный поток вывода
cgi = CGI.new cgi.print # default: cgi.print == $DEFAULT_OUTPUT.print
Приватные методы экземпляра
# File lib/cgi/core.rb, line 59 def env_table ENV end
Синоним для ENV.
# File lib/cgi/core.rb, line 64 def stdinput $stdin end
Синоним для $stdin.
# File lib/cgi/core.rb, line 69 def stdoutput $stdout end
Синоним для $stdout.
Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.