класс CGI
Обзор
Common Gateway Interface (CGI) — это простой протокол для передачи HTTP-запроса от веб-сервера к автономной программе и возвращения результата веб-браузеру. По сути, программа CGI вызывается с параметрами запроса, переданными либо в среде (GET), либо через $stdin (POST), а всё, что она выводит в $stdout, возвращается клиенту.
В этом файле находится класс CGI. Этот класс предоставляет функциональность для получения параметров HTTP-запроса, управления куки и генерации HTML-вывода.
Файл CGI::Session предоставляет функциональность управления сеансами; подробнее об этом классе см. там.
Дополнительную информацию о протоколе CGI см. на сайте www.w3.org/CGI.
Введение
CGI — это большой класс, предоставляющий несколько категорий методов, многие из которых взяты из других модулей. Некоторые из документации находятся в этом классе, а некоторые — в модулях CGI::QueryExtension и CGI::HtmlExtension. Дополнительную информацию по работе с куки см. в CGI::Cookie, а информацию по сессиям — в cgi/session.rb (CGI::Session).
Для запросов, класс CGI предоставляет методы для доступа к переменным среды, параметрам, куки и данным многочастного запроса. Для ответов, класс CGI предоставляет методы для записи вывода и генерации HTML.
Для получения подробной информации см. далее. Внизу приведены примеры.
Запросы
Класс CGI динамически подключает функциональность разбора параметров и куки, доступ к переменным среды и поддержку разбора многочастных запросов (включая загруженные файлы) из модуля 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?.
Куки
HTTP-куки автоматически разбираются из запроса. Они доступны через свойство cookies(), которое возвращает хэш с именем куки в качестве ключа и объектом CGI::Cookie в качестве значения.
Многочастные запросы
Если метод запроса — 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
Получение значений многочастной формы
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.
Получение значений куки
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 — это хэш.
Получение объектов куки
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
-
Разделители путей в различных средах.
Атрибуты
Возвращает набор символов по умолчанию для этого объекта CGI.
Публичные методы класса
# File lib/cgi/core.rb, line 747 def self.accept_charset @@accept_charset end
Возвращает набор символов по умолчанию для всех новых объектов CGI.
# File lib/cgi/core.rb, line 838
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 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 Разбирает строку 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 -
Хэш-таблица значений заголовков. Признаются следующие ключи заголовков:
- type
-
Заголовок Content-Type. По умолчанию «text/html»
- charset
-
Кодировка символов тела, добавляемая к заголовку Content-Type.
- nph
-
Логическое значение. Если true, добавляет строку протокола и код состояния, а также дату; и устанавливает значения по умолчанию для «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; массивом литеральных строк файлов 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», содержимое преобразуется в эту кодировку, а язык устанавливается на «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 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.