FCGI::Buffer — проверка, кэширование и оптимизация вывода FCGI
Версия 0.19
FCGI::Buffer проверяет созданный вами HTML, передавая его через HTML::Lint
.
FCGI::Buffer оптимизирует программы FCGI, сокращая, фильтруя и сжимая выходные данные для ускорения передачи, а также практически беспрепятственно используя кэши клиента и сервера.
Чтобы использовать клиентские кеши, то есть уменьшить количество ненужных вызовов на ваш сервер, запрашивающих одни и те же данные:
use FCGI;
use FCGI::Buffer;
# ...
my $request = FCGI::Request();
while($request->FCGI::Accept() >= 0) {
my $buffer = FCGI::Buffer->new();
$buffer->init(
optimise_content => 1,
lint_content => 0,
);
# ...
}
Чтобы также использовать серверные кеши, то есть сохранять восстанавливаемый вывод, когда разные клиенты запрашивают одни и те же данные, вам необходимо создать кеш. Но это просто:
use FCGI;
use CHI;
use FCGI::Buffer;
# ...
my $request = FCGI::Request();
while($request->FCGI::Accept() >= 0) {
my $buffer = FCGI::Buffer->new();
$buffer->init(
optimise_content => 1,
lint_content => 0,
cache => CHI->new(driver => 'File')
);
if($buffer->is_cached()) {
# Nothing has changed - use the version in the cache
$request->Finish();
next;
# ...
}
}
Чтобы временно запретить использование кэшей на стороне сервера, например, во время отладки перед публикацией изменения кода, установите для переменной среды NO_CACHE любое ненулевое значение. Это также остановит добавление ETag в заголовок. Если вы получаете ошибки о широких символах при печати, это означает, что вы забыли создать чистый HTML для символов, отличных от ASCII. См. HTML::Entities. В качестве обходного пути вы также можете удалить акценты и тому подобное, используя Text::Unidecode, который работает хорошо, но на самом деле это не то, что вам нужно.
Создайте объект FCGI::Buffer. Выполните одно из этих действий для каждого FCGI::Accept.
Установите различные параметры и отмените значения по умолчанию.
# Put this toward the top of your program before you do anything
# By default, generate_tag, generate_304 and compress_content are ON,
# optimise_content and lint_content are OFF. Set optimise_content to 2 to
# do aggressive JavaScript optimisations which may fail.
use FCGI::Buffer;
my $buffer = FCGI::Buffer->new()->init({
generate_etag => 1, # make good use of client's cache
generate_last_modified => 1, # more use of client's cache
compress_content => 1, # if gzip the output
optimise_content => 0, # optimise your program's HTML, CSS and JavaScript
cache => CHI->new(driver => 'File'), # cache requests
cache_key => 'string', # key for the cache
cache_age => '10 minutes', # how long to store responses in the cache
logger => $self->{logger},
lint_content => 0, # Pass through HTML::Lint
generate_304 => 1, # When appropriate, generate 304: Not modified
save_to => { directory => '/var/www/htdocs/save_to', ttl => 600, create_table => 1 },
info => CGI::Info->new(),
lingua => CGI::Lingua->new(),
});
Если кэш_ключ не указан, будет сгенерирован ключ, который может не быть уникальным. Cache_key должен быть уникальным значением, зависящим от значений, установленных браузером.
Объектом кэша будет объект, который понимает сообщения get_object(), set(), Remove() и Create_at(), например объект CHI. Он используется в качестве кэша на стороне сервера, чтобы уменьшить необходимость повторного доступа к базе данных.
По умолчанию элементы остаются в кэше на стороне сервера в течение 10 минут. Это можно переопределить с помощью HTTP-заголовка Cache_control в запросе, а значение по умолчанию можно изменить с помощью аргумента Cache_age на init().
Save_to — это функция, которая сохраняет выходные данные динамических страниц в вашем дереве htdocs и заменяет будущие ссылки, указывающие на эту страницу, статическими ссылками, чтобы вообще избежать использования CGI. Для Ttl установлено количество секунд, в течение которых статические страницы считаются активными, значение по умолчанию — 10 минут. Если установлено значение 0, страница активна навсегда. Чтобы включить save_to, также необходимо указать аргументы info и lingua. Лучше всего работает, когда также указан кэш. Используйте только там, где выходные данные гарантированно будут одинаковыми с заданным набором аргументов (те же критерии для включения Generate_304). Вы можете отключить его в каждом конкретном случае следующим образом:
my $params = CGI::Info->new()->params();
if($params->{'send_private_email'}) {
$buffer->init('save_to' => undef);
}
Info — это необязательный аргумент, предоставляющий информацию о среде FCGI, например объект CGI::Info.
Logger будет объектом, который понимает функцию debug(), например объектом Log::Log4perl.
Чтобы сгенерировать заголовок Last_modified, вы должны указать объект кэша.
Init позволяет передавать ссылку на параметры. Итак, оба из них работают: используйте FCGI::Buffer; #... мой $buffer = FCGI::Buffer->new(); $b->init(generate_etag => 1); $b->init({generate_etag => 1, info => CGI::Info->new() });
Вообще говоря, передача по ссылке лучше, поскольку при этом в стек копируется меньше данных.
Если вы передадите кеш для init(), а затем позже дадите кэш => undef, кеш на стороне сервера больше не будет использоваться. Это полезно, когда вы обнаруживаете ошибку при создании HTML и решаете, что больше не хотите хранить выходные данные в кеше.
Синоним init сохранен по историческим причинам.
Возвращает true, если серверу разрешено хранить результаты локально. Это значение X-Cache в возвращаемом заголовке.
Возвращает true, если выходные данные кэшируются. Если да, то это означает, что все дорогостоящие процедуры в сценарии FCGI можно обойти, поскольку результат уже хранится в кеше.
# Put this toward the top of your program before you do anything
# Example key generation - use whatever you want as something
# unique for this call, so that subsequent calls with the same
# values match something in the cache
use CGI::Info;
use CGI::Lingua;
use FCGI::Buffer;
my $i = CGI::Info->new();
my $l = CGI::Lingua->new(supported => ['en']);
# To use server side caching you must give the cache argument, however
# the cache_key argument is optional - if you don't give one then one will
# be generated for you
my $buffer = FCGI::Buffer->new();
if($buffer->can_cache()) {
$buffer->init(
cache => CHI->new(driver => 'File'),
cache_key => $i->domain_name() . '/' . $i->script_name() . '/' . $i->as_string() . '/' . $l->language()
);
if($buffer->is_cached()) {
# Output will be retrieved from the cache and sent automatically
exit;
}
}
# Not in the cache, so now do our expensive computing to generate the
# results
print "Content-type: text/htmln";
# ...
Найджел Хорн, <njh at bandsman.co.uk>
FCGI::Buffer должен быть безопасным даже в сценариях, которые выдают много разных результатов, например, в ситуациях электронной коммерции. Однако на таких страницах я настоятельно рекомендую установить дляgener_304 значение 0 и отправить HTTP-заголовок «Cache-Control: no-cache».
При использовании шаблона убедитесь, что вы не используете его для вывода в STDOUT, вместо этого вам нужно будет записать его в переменную и распечатать ее. Например:
my $output;
$template->process($input, $vars, $output) || ($output = $template->error());
print $output;
Может создавать ошибки в JavaScript, если вы используете технику <!-- HIDING. Это ошибка в JavaScript::Packer, а не в FCGI::Buffer.
Mod_deflate может запутать это при сжатии вывода. Убедитесь, что дефляция отключена для файлов .pl:
SetEnvIfNoCase Request_URI .(?:gif|jpe?g|png|pl)$ no-gzip dont-vary
Если вы запрашиваете сжатый вывод, а затем несжатый вывод (или наоборот) на входе, который производит тот же вывод, статус будет 304. Буква спецификации говорит, что это неправильно, поэтому я отмечаю это здесь, но на практике вам не следует увидеть, как это произойдет, или у вас возникнут какие-либо трудности из-за этого.
FCGI::Buffer не тестировался на FastCGI.
Я советую добавить FCGI::Buffer в качестве последнего оператора использования, чтобы он был очищен в первую очередь. В частности, его следует загружать после Log::Log4perl, если вы его используете, чтобы любые сообщения, которые он создает, печатались после того, как заголовки HTTP были отправлены FCGI::Buffer;
Save_to не понимает ссылки в JavaScript, а это означает, что если вы используете самовызываемые CGI, которые загружаются как статическая страница, они могут указывать не на то место. Обходной путь — избегать самовызова CGI в JavaScript.
Сообщайте о любых ошибках или запросах функций в bug-fcgi-buffer at rt.cpan.org
или через веб-интерфейс http://rt.cpan.org/NoAuth/ReportBug.html?Queue=FCGI-Buffer. Я буду уведомлен, а затем вы будете автоматически уведомлены о ходе работы над вашей ошибкой по мере того, как я вношу изменения.
Операция lint работает только в HTML4 из-за ограничения в HTML::Lint.
CGI::Buffer, HTML::Packer, HTML::Lint
Вы можете найти документацию для этого модуля с помощью команды perldoc.
perldoc FCGI::Buffer
Вы также можете поискать информацию по адресу:
RT: трекер запросов CPAN
http://rt.cpan.org/NoAuth/Bugs.html?Dist=FCGI-Buffer
Рейтинги CPAN
http://cpanratings.perl.org/d/FCGI-Buffer
Поиск CPAN
http://search.cpan.org/dist/FCGI-Buffer/
Вдохновением и кодом для некоторых из них является cgi_buffer Марка Ноттингема: https://www.mnot.net/blog/2003/04/24/etags.
Лицензия на cgi_buffer:
"(c) 2000 Copyright Mark Nottingham <[email protected]>
This software may be freely distributed, modified and used,
provided that this copyright notice remain intact.
This software is provided 'as is' without warranty of any kind."
Остальная часть программы защищена авторскими правами Найджела Хорна, 2015–2023 гг., и распространяется под следующей лицензией: GPL2.