end
end
Здесь создается кук 'kabhi'
, ключ которого 'lastaccess'
содержит текущее время. Если у браузера уже был такой кук, то выводится его значение. Куки хранятся в хэше, который является переменной экземпляра в классе CGI. Каждый кук может содержать несколько пар ключ- значение, поэтому при доступе к куку по имени вы получаете массив.
19.1.4. Сеансы пользователей
Куки — это хорошо, если вам нужно сохранить простые данные и вы не прочь возложить на браузер заботу об их хранении. Но часто предъявляются более жесткие требования. Что если нужно сохранить много данных и вы не хотите гонять их «взад-вперед» при каждом запросе? К тому же данные могут быть секретными, так что доверять их хранение браузеру нежелательно.
В таких случаях можно воспользоваться классом CGI::Session
. Он аналогичен классу CGI::Cookie
в том смысле, что значения хранятся в структуре, напоминающей хэш.
require 'cgi'
require 'cgi/session'
cgi = CGI.new('html4')
sess = CGI::Session.new(cgi, 'session_key' => 'a_test',
'prefix' => 'rubysess.')
lastaccess = sess['lastaccess'].to_s
sess['lastaccess'] = Time.now
if cgi['bgcolor'][0] =~ /[a-z]/
sess['bgcolor'] = cgi['bgcolor']
end
cgi.out do
cgi.html do
cgi.body ('bgcolor' => sess['bgcolor']) do
'Фон этой страницы' +
'изменяется в зависимости от значения 'bgcolor',' +
'хранящегося в сеансе каждого пользователя.' +
'Время последнего доступа: #{lastaccess}'
end
end
end
Если обратиться к URL /thatscript.cgi?bgcolor=red
, то фоновый цвет страницы у данного пользователя станет красным и останется таким до тех пор, пока он не обратится к такому же URL, но с другим значением параметра 'bgcolor'
. При создании объекта CGI::Session
указываются объект CGI
и набор параметров в хэше. Необязательный параметр session_key
определяет ключ, с помощью которого браузер будет идентифицировать себя при каждом запросе. Сеансовые данные хранятся во временном файле, своем для каждого сеанса, а параметр prefix
задает строку, с которой должно начинаться имя файла, чтобы проще было опознать все такие файлы в файловой системе сервера.
Классу CGI::Session
пока недостает многих возможностей, в частности умения хранить объекты, отличные от String
, организации общего хранилища сеансовых данных для нескольких серверов и пр. К счастью, уже готов подключаемый механизм database_manager
, так что некоторые из этих функций нетрудно добавить. Если вы придумаете что-нибудь интересное в отношении класса CGI::Session
, не забудьте поделиться с сообществом.
19.2. FastCGI
Чаще всего CGI критикуют за то, что при каждом запросе создается новый процесс, и это заметно снижает производительность. Невозможность сохранять в памяти объекты между последовательными запросами также не украшает дизайн системы. Для разрешения этих проблем была создана технология FastCGI.
По сути дела,
Серверы, адаптированные для работы с FastCGI, реализованы на многих языках, в том числе на Ruby. Эли Грин (Eli Green) написал целиком на Ruby модуль (он есть в архиве RAA), который реализует протокол FastCGI и упрощает разработку FastCGI-программ.
Не вдаваясь в детали реализации, мы представили в листинге 19.1 пример приложения. Как видите, он повторяет функциональность предыдущего примера.
require 'fastcgi'
require 'cgi'
last_time = ''
def get_ramblings(instream)
# He слишком красивый способ извлечь значение из первой пары
# имя-значение. CGI сделал бы это за нас.
data = ''
if instream != nil
data = instream.split('&')[0].split(' = ')[1] || ''
end
return CGI.unescape(data)
end
def reverse_ramblings(ramblings)
if ramblings == nil then return '' end
chunks = ramblings.split(/s+/)
chunks.reverse.join(' ')
end
server = FastCGI::TCP.new('localhost', 9000)
begin
server.each_request do |request|