класс CGI
Обзор
Интерфейс общего шлюза (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 предоставляет методы для доступа к переменным окружения, параметрам, кукам и данным запроса multipart. Для ответов CGI предоставляет методы для записи вывода и генерации HTML.
Для получения более подробной информации см. примеры в конце.
Запросы
Класс CGI динамически включает в себя функциональность разбора параметров и куков, доступ к переменным среды и поддержку разбора 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?.
Куки
HTTP-куки автоматически парсятся из запроса. Они доступны через аксессор cookies(), который возвращает хэш, где ключ — имя куки, а значение — объект 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['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
Получение значений 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.
Получение значений куки
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
-
Разделители пути в разных средах.
- VERSION
Атрибуты
Возвращает набор символов, принятый для этого экземпляра CGI.
Методы публичного класса
# File lib/cgi/core.rb, line 759 def self.accept_charset @@accept_charset end
Возвращает набор символов, принятый для всех новых экземпляров CGI.
# File lib/cgi/core.rb, line 764 def self.accept_charset=(accept_charset) @@accept_charset=accept_charset end
Устанавливает набор символов, принятый для всех новых экземпляров CGI.
# 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 Создает новый экземпляр 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 -
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 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 в хеш пар ключевых => значение.
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
-
Булевое значение. Если 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 или несколько cookies, возвращаемые в одном или нескольких заголовках Set-Cookie. Значение может быть строкой cookie; объектом
CGI::Cookie; массивомArrayстроковых значений cookie или объектовCookie; или хэш, все значения которого являются строками cookie или объектамиCookie.Эти cookies дополняют cookies в поле @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 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 Печать 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 383 def print(*options) stdoutput.print(*options) end
Вывод аргумента или списка аргументов в стандартный поток вывода
cgi = CGI.new cgi.print # default: cgi.print == $DEFAULT_OUTPUT.print
Приватные методы экземпляра
# 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 # 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–2022 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.