Авторы: www.webclub.ru
SSI - что,
когда, как?
Андрей
Новиков - Член Всероссийского Клуба Вебмастеров
Андрей
Юрченко - Член Всероссийского Клуба Вебмастеров
Основным, простейшим,
но в то же время чрезвычайно мощным инструментом поддержки
больших наборов документов является SSI (Server-Side Includes
- включения на стороне сервера). Если кто-то из вас знает
Си, то он быстро поймет, что SSI чрезвычайно похож на макроязык.
С помощью SSI можно не только в зависимости от некоторых условий
выводить определенные части документа, не только формировать
документ из заранее определенных кусочков, но и вставлять
результат работы некоторого CGI сценария или программы прямо
в документ.
Не смотря на
порядок слов в заголовке (что, когда и как) мы сначала расскажем
"как", а потом уже перейдем к "когда".
В стандартном
дистрибутиве Apache есть модуль mod_include. Начиная
с версии 1.2 он имеет расширенное количество директив и называется
- XSSI (eXtended SSI). По умолчанию он включен в компиляцию.
Включение механизма Server-Side
Includes
Любой документ,
у которого будет установлен обработчик "server-parsed" будет
сканироваться этим модулем, если включена опция "Includes".
Если вы имеете малое количество документов с SSI, то лучше
всего в файле httpd.conf указать следующее:
AddType text/html .shtml
AddHandler server-parsed .shtml
и
устанавливать у таких файлов расширение .shtml. Если
же все или почти все документы будут иметь директивы SSI,
то лучше в файле конфигурации указать:
AddHandler server-parsed .html И
не забудьте включить в опции директории узла опцию Includes:
Options +Includes Конечно
в этой строке могут быть и другие нужные вам опции.
Базовые директивы
Директивы SSI
включаются в HTML документ в виде комментариев (это не мешает
вам использовать обычные комментарии). Синтакс команд имеет
следующий вид:
<!--#element attribute=value attribute=value ... --> Очень
часто значение помещается в двойные кавычки. Некоторые команды
позволяют иметь только одну пару атрибут-значение. Обратите
внимание, что заключительная часть комментария (-->) должна
отделяться от директивы пробелом, иначе она будет воспринята,
как ее часть.
Рассмотрим определенные
в Apache элементы SSI:
config
- контролирует различные аспекты сканирования. Его атрибутами
могут быть:
errmsg
- устанавливает сообщение, выводящееся при возникновении ошибки;
в большинстве случаев целесообразно установить в пустую строку;
sizefmt
- устанавливает формат, в котором будет выводиться размер
файла. Формат соответствует передаваемому библиотечной функции
strftime;
timefmt
- устанавливает формат, в котором будет выводиться дата.
echo -
выводит значение установленной переменной SSI. Допустимым
атрибутом является var.
fsize
- выводит размер файла в определенном с помощью sizefmt
формате. Допустимые атрибуты:
file -
определяет путь к файлу, относительно сканируемого документа;
virtual
- определяет стандартный кодированный URL, относительно сканируемого
документа, или, при наличии в начале слеша (/) - относительно
корня документов узла.
flastmod
- выводит дату последней модификации файла в определенном
с помощью timefmt формате. Атрибуты аналогичны атрибутам
fsize.
include
- включает текст другого документа или файла в сканируемый
файл. К включаемому файлу применяются все установленные правила
ограничения доступа. Если для каталога, из которого включается
файл, установлена опция IncludesNOEXEC, и включение
данного документа привело бы к запуску программы, то документ
не включается, и выводится сообщение об ошибке. CGI сценарии
вызываются, как обычно с помощью URL, который может содержать
кодированную строку запроса (query string). Положение файла
указывается с помощью атрибутов:
file -
указывает путь, относительно сканируемого документа; путь
не может содержать ../ и не может быть абсолютным путем; всегда
предпочтительнее использовать атрибут virtual;
virtual - содержит кодированный URL, относительный
или абсолютный; URL не может содержать имя протокола или имя
хоста, и может содержать строку запроса.
printenv
- выводит содержимое переменных окружения. Вызывается без
параметров.
set -
устанавливает значение переменной. Ее атрибутами являются
var, определяющий имя переменной, и value, определяющий
ее значение.
Переменные включения
В дополнение
к стандартным окружения CGI, модуль SSI делает доступными
для директив и условий, а также для вызываемых через SSI сценариев
следующие переменные:
DATE_GMT
- текущее время по Гринвичу;
DATE_LOCAL - текущее локальное (для сервера) время;
DOCUMENT_NAME - имя файла (без каталогов) документа,
запрошенного пользователем;
DOCUMENT_URI - декодированный URL запрошенного пользователем
документа;
LAST_MODIFIED - дата последней модификации документа,
запрошенного пользователем. То есть во вложенном SSI эта переменная
будет содержать имя "главного" документа, а не вложенного.
Подстановка переменных
Подстановка переменных
производится внутри заключенных в кавычки строк в большинстве
аргументов SSI директив. В этих случаях знак доллара можно
вставить, предварив его слешом:
<!--#if expr="$a = \$test" -->
Для предотвращения
двусмысленности можно заключать имя переменной в фигурные
скобки:
<!--#set var="Zed" value="${a}bc_${abc}" -->
В результате
такого присвоения переменная Zed будет иметь значение
"Xbc_Y", если переменная a равна X, а переменная
abc равна Y.
Условные операторы
Базовыми элементами
контроля являются:
<!--#if expr="test_condition" -->
<!--#elif expr="test_condition" -->
<!--#else -->
<!--#endif -->
Элементы elif
и else являются необязательными.
Элемент endif
заканчивает элемент if и является обязательным.
test_condition
может быть одним из следующих:
string
- истинно, если string не пуста;
string1 = string2
string1 != string2
string1 < string2
string1 <= string2
string1 > string2
string1 >= string2
- истинно, если выполняется условие сравнения. Если string2
имеет форму /string/, то тогда она интерпретируется,
как регулятное выражение. Их синтаксис аналогичен синтаксису
регулярных выражений в Unix команде egrep;
( test_condition ) - истинно, если test_condition истинно;
! test_condition - истинно, если test_condition ложно;
test_condition1 && test_condition2 - истинно, если
как test_condition1, так и test_condition2 истинны;
test_condition1 || test_condition2 - истинно, если
хотя бы test_condition1 или test_condition2 истинно.
"=" и "!=" имеют больший приоритет, чем "&&" и "||", а "!"
имеет наивысший приоритет.
Все, что не распознается,
как переменная, считается строкой. Если строка имеет пробелы
или символы табуляции, то ее надо заключать в кавычки.
Практическое использование SSI
Первым распространенным
применением SSI является внедрение в документ некоего динамического
куска разметки. Хрестоматийными примерами могут служить счетчики
посещений, цитаты или баннеры рекламных сетей. В любом случае,
будь то строка текста или целая таблица, вставка производится
с помощью директивы include, помещаемой в то место, куда должен
быть вставлен кусок разметки:
<html>
<body>
<p>Документ с баннером внизу страницы</p>
<!--#include virtual="/cgi-bin/ibanner.pl?webclub" -->
</body>
</html>
Программа или
сценарий CGI, вставляемая с помощью SSI, ничем не отличается
от стандартной CGI программы, за исключением того, что должен
выдаваться не целый документ, а только кусок разметки.
Вот текст упомянутого
выше сценария:
#!/usr/local/bin/perl
$login=$ENV{"QUERY_STRING"};
print "Content-type: text/html\n\n";
($IP)=($ENV{"REMOTE_ADDR"}=~s/\.//g);
srand($$+$IP+time);
$seed=int rand(10000000);
print "<a href=\"http://www.reklama.ru/cgi-bin/href/$login?$seed\">\n";
print "<img src=\"http://www.reklama.ru/cgi-bin/banner/$login?$seed\"
width=468 height=60 border=0>\n";
print "</a>\n";
Как видно из
примера даже во включаемых сценариях необходимо выводить HTTP
заголовок.
В результате
сканирования нашего простейшего документа пользователю будет
возвращен примерно (с точностью до случайной величины) следующий
документ:
<html>
<body>
<p>Документ с баннером внизу страницы</p>
<a href="http://www.reklama.ru/cgi-bin/href/webclub?348593">
<img src="http://www.reklama.ru/cgi-bin/banner/webclub?348593"
width=468 height=60 border=0>
</a>
</body>
</html>
Вторым распространенным
применением SSI является формирование страницы из шаблона.
В простейшем случае - это документ в начало и конец которого
вставляются шапка и концевик:
<html>
<head>
<title>Test Page</title>
</head>
<!--#include virtual="/ssi/header.html" -->
<h1>Тестовая страница</h1>
<p>Некий текст</p>
<!--#include virtual="/ssi/global_menu.html" -->
<!--#include virtual="/ssi/footer.html" -->
</body>
</html>
Вставляемые блоки
не обязательно должны быть законченными, например, header.html
может заканчиваться тэгом <td>, а global_menu.html
или footer.html начинаться с тэга </td>.
Таким образом, какими бы навороченными не были шапка и концевик
документа, редактируемый документ выглядит чрезвычайно просто,
и его легко редактировать.
Только используя
SSI вы можете в считанные минуты полностью изменить внешний
вид или обновить систему навигации на узле, имеющем сотни
или тысячи документов, и так, что это пройдет безболезненно
для пользователей узла, т.к. вам только потребуется заменить
несколько файлов, а остальное за вас сделает сервер.
В связи со всем
вышесказанным рождается одно правило: желательно смысловую
часть документа строить так, чтобы она никак не полагалась
на содержимое шапок и концевиков. В этом случае вы легко сможете
перейти с табличной организации страниц на последовательную
или на слоевую.
Теперь приведем
пример файла, вставляемого в начало каждого документа сервера
http://www.citforum.ru/.
Особенностью сервера является то, что каждый раздел имеет
свой базовый цвет, и все это создается этим единственным файлом:
<link rel=stylesheet type="text/css" href="/css/cf.css">
</head>
<!--#if expr="$DOCUMENT_URI=/\/internet\//" -->
<body bgcolor="#FFFFFF" link="#099771" vlink="#006741"
alink="#800000" text="#000000">
<table cellspacing=0 cellpadding=0 border=0
background="/pictures/menu/header2.jpg" width="100%">
<!--#elif expr="$DOCUMENT_URI=/\/database\//" -->
<body bgcolor="#FFFFFF" link="#719709" vlink="#416700"
alink="#800000" text="#000000">
<table cellspacing=0 cellpadding=0 border=0
background="/pictures/menu/header3.jpg" width="100%">
<!--#elif expr="$DOCUMENT_URI=/\/ofis\//" -->
<body bgcolor="#FFFFFF" link="#98650A" vlink="#683500"
alink="#800000" text="#000000">
<table cellspacing=0 cellpadding=0 border=0
background="/pictures/menu/header4.jpg" width="100%">
<!--#elif expr="$DOCUMENT_URI=/\/abtec\//" -->
<body bgcolor="#FFFFFF" link="#98340A" vlink="#680400"
alink="#800000" text="#000000">
<table cellspacing=0 cellpadding=0 border=0
background="/pictures/menu/header5.jpg" width="100%">
<!--#elif expr="$DOCUMENT_URI=/\/programming\//" -->
<body bgcolor="#FFFFFF" link="#099607" vlink="#006600"
alink="#800000" text="#000000">
<table cellspacing=0 cellpadding=0 border=0
background="/pictures/menu/header6.jpg" width="100%">
<!--#elif expr="$DOCUMENT_URI=/\/operating_systems\//" -->
<!--#elif expr="$DOCUMENT_URI=/\/abtec\//" -->
<body bgcolor="#FFFFFF" link="#98340A" vlink="#680400"
alink="#800000" text="#000000">
<table cellspacing=0 cellpadding=0 border=0
background="/pictures/menu/header5.jpg" width="100%">
<!--#elif expr="$DOCUMENT_URI=/\/ftp\//" -->
<body bgcolor="#FFFFFF" link="#970941" vlink="#670011"
alink="#800000" text="#000000">
<table cellspacing=0 cellpadding=0 border=0
background="/pictures/menu/header8.jpg" width="100%">
<!--#elif expr="$DOCUMENT_URI=/\/news\//" -->
<body bgcolor="#FFFFFF" link="#970941" vlink="#670011"
alink="#800000" text="#000000">
<table cellspacing=0 cellpadding=0 border=0
background="/pictures/menu/header8.jpg" width="100%">
<!--#elif expr="$DOCUMENT_URI=/\/finnews\//" -->
<body bgcolor="#FFFFFF" link="#970941" vlink="#670011"
alink="#800000" text="#000000">
<table cellspacing=0 cellpadding=0 border=0
background="/pictures/menu/header8.jpg" width="100%">
<!--#elif expr="$DOCUMENT_URI=/\/events\//" -->
<body bgcolor="#FFFFFF" link="#970941" vlink="#670011"
alink="#800000" text="#000000">
<table cellspacing=0 cellpadding=0 border=0
background="/pictures/menu/header8.jpg" width="100%">
<!--#elif expr="$DOCUMENT_URI=/\/lists\//" -->
<body bgcolor="#FFFFFF" link="#970941" vlink="#670011"
alink="#800000" text="#000000">
<table cellspacing=0 cellpadding=0 border=0
background="/pictures/menu/header8.jpg" width="100%">
<table cellspacing=0 cellpadding=0 border=0
background="/pictures/menu/header8.jpg" width="100%">
<!--#elif expr="$DOCUMENT_URI=/\/hardware\//" -->
<body bgcolor="#FFFFFF" link="#950995" vlink="#650065"
alink="#800000" text="#000000">
<table cellspacing=0 cellpadding=0 border=0
background="/pictures/menu/header9.jpg" width="100%">
<!--#elif expr="$DOCUMENT_URI=/\/nets\//" -->
<body bgcolor="#FFFFFF" link="#390A98" vlink="#090068"
alink="#800000" text="#000000">
<table cellspacing=0 cellpadding=0 border=0
background="/pictures/menu/header10.jpg" width="100%">
<!--#else -->
<body bgcolor="#FFFFFF" link="#006890" vlink="#003860"
alink="#800000" text="#000000">
<table cellspacing=0 cellpadding=0 border=0
background="/pictures/menu/header0.jpg" width="100%">
<!--#endif -->
<tr><td align="center">
<table cellspacing=0 cellpadding=4 border=0 width="100%" background="">
<tr><td align="left">
<img src="/pictures/menu/logo.gif" width=157 height=53
border=0 alt="Server for Information Technologies">
</td><td align="right">
<!--#include virtual="/cgi-bin/Look_new.cgi"-->
</td></tr>
</table>
<table cellspacing=0 cellpadding=4 border=0 width="100%" background="">
<tr valign=top><td align="left">
<font size="-1">Сервер содержит море(!)
аналитической информации</font></td>
<td align="right">
<font size="-1"><a href="/rubricator/index.shtml">
Рубрикатор всех документов
CIT Forum</a></font></td>
</tr>
</table>
</td></tr>
</table>
Данный пример
иллюстрирует работу с условными операторами, с шаблонами,
а также возможность использования вложенных SSI.
Следующий пример
иллюстрирует, как с помощью SSI собираются страницы
в Кладовой. Их особенность заключается в наличии повторяющихся
блоков одинаково оформленного текста. Достигается это использованием
трех шаблонов:
_head.html
<html><head>
<title>Web Club Repository. <!--#echo var="TITLE" --></title>
<meta http-equiv="Content-Type" content="text/html">
<meta http-equiv="author" content="Andrey G. Novikov
+ Andrew Yourtchenko">
<meta http-equiv="distribution" content="global">
<meta http-equiv="resource-type" content="document">
<meta name="keywords" content="WebClub,
<!--#echo var="KEYWORDS" -->">
<meta name="description" content="WebClub. Кладовая. <
!--#echo var="DESCRIPTION" -->">
<link rel="stylesheet" type="text/css" href="/webclub2.css">
</head>
<body text="#000000" bgcolor="#FFFFFF" link="#0000A8"
vlink="#000040" alink="#FF0000">
<h1 align="center"><font color="#CCCCCC"><h></font>
КЛАДОВАЯ<font color="#CCCCCC"></h></font><br>
<img src="/images/bar.gif" width=587 height=19 border=0></h1>
<h2 align="center"><!--#echo var="TITLE" --></h2>
_item.html
<table cellspacing=0 cellpadding=3 border=0 width="100%">
<tr><td bgcolor="#CCCCFF">
<b><!--#echo var="I_TITLE" --></b>
</td></tr></table>
<!--#if expr="$I_PIC" -->
<br>
<table cellspacing=1 cellpadding=3 border=1
align="right" bgcolor="#CCCCFF">
<tr><td align="center" valign="middle">
<img src="<!--#echo var="I_PIC" -->"
width="<!--#echo var="I_PIC_W" -->"
height="<!--#echo var="I_PIC_H" -->" border=0>
</td></tr></table>
<!--#endif -->
<p>
<!--#if expr="$I_SITE" -->
<b>Узел поддержки</b>:<a href="<!--#echo var="I_SITE" -->">
<!--#echo var="I_SITE" --></a><br>
<!--#endif -->
<!--#if expr="$I_PAGE" -->
<b>Домашняя страница</b>:<a href="<!--#echo var="I_PAGE" -->">
<!--#echo var="I_PAGE" --></a><br>
<!--#endif -->
<!--#if expr="$I_ARCHIVE" -->
<b>Она сама</b>:<a href="<!--#echo var="I_ARCHIVE" -->">
<!--#echo var="I_ARCHIVE" --></a><br>
<!--#endif -->
<!--#if expr="$I_LOCALARCHIVE" -->
<b>Она сама у нас</b>:
<a href="<!--#echo var="I_LOCALARCHIVE" -->">
<!--#echo var="I_LOCALARCHIVE" --></a><br>
<!--#endif -->
<!--#if expr="$I_PLATFORM" -->
<b>Платформа</b>: <!--#echo var="I_PLATFORM" --><br>
<!--#endif -->
<!--#if expr="$I_STATUS" -->
<b>Статус</b>: <!--#echo var="I_STATUS" --><br>
<!--#endif -->
</p>
<p align="justify">
<!--#if expr="$I_DESCRIPTION" -->
<!--#echo var="I_DESCRIPTION" -->
<!--#else -->
No description.
<!--#endif -->
</p>
<br clear="right"><br>
_foot.html
<!--#include virtual="/materials/banfooter.html"-->
</body>
</html>
А вот как выглядит
на самом деле файл, который вы воспринимаете, как обычный
HTML документ (он сокращен для удобства восприятия):
<!--#set var="TITLE" value="HTML редакторы и утилиты" -->
<!--#set var="KEYWORDS"
value="HTML,editor,редактор,утилита,utilities,freeware,
shareware,free" -->
<!--#set var="DESCRIPTION" value="HTML редакторы и утилиты" -->
<!--#include virtual="_head.html" -->
<!--#set var="I_TITLE" value="Prime Style 1.2" -->
<!--#set var="I_RATING" value="1" -->
<!--#set var="I_PIC" value="ps.gif" -->
<!--#set var="I_PIC_W" value="300" -->
<!--#set var="I_PIC_H" value="225" -->
<!--#set var="I_SITE" value="" -->
<!--#set var="I_PAGE" value="http://www.northnet.com.au/
~hardy/prime/" -->
<!--#set var="I_ARCHIVE" value="" -->
<!--#set var="I_LOCALARCHIVE" value="" -->
<!--#set var="I_PLATFORM" value="Windows 95/NT" -->
<!--#set var="I_STATUS" value="Free" -->
<!--#set var="I_DESCRIPTION" value="Простой и наглядный редактор
каскадных
стилей. Простой и понятный интерфейс." -->
<!--#include virtual="_item.html" -->
<!--#set var="I_TITLE" value="Web-O-Rama v.4.00" -->
<!--#set var="I_RATING" value="" -->
<!--#set var="I_PIC" value="weborama.gif" -->
<!--#set var="I_PIC_W" value="300" -->
<!--#set var="I_PIC_H" value="225" -->
<!--#set var="I_SITE" value="" -->
<!--#set var="I_PAGE" value="" -->
<!--#set var="I_ARCHIVE" value="" -->
<!--#set var="I_LOCALARCHIVE" value="" -->
<!--#set var="I_PLATFORM" value="Windows 95/NT" -->
<!--#set var="I_STATUS" value="Free" -->
<!--#set var="I_DESCRIPTION" value="Весьма удобный интерфейс,
возможность внешнего просмотра файлов через браузер,
открывает сразу много файлов. Есть встроенный индикатор контроля
системных ресурсов." -->
<!--#include virtual="_item.html" -->
<!--#set var="I_TITLE" value="HTML Font Colorizer" -->
<!--#set var="I_RATING" value="3" -->
<!--#set var="I_PIC" value="" -->
<!--#set var="I_PIC_W" value="100" -->
<!--#set var="I_PIC_H" value="100" -->
<!--#set var="I_SITE" value="" -->
<!--#set var="I_PAGE" value="http://home1.inet.tele.dk/
theill/hfc.htm" -->
<!--#set var="I_ARCHIVE" value="" -->
<!--#set var="I_LOCALARCHIVE" value="" -->
<!--#set var="I_PLATFORM" value="Windows 95/NT" -->
<!--#set var="I_STATUS" value="Freeware" -->
<!--#set var="I_DESCRIPTION" value="Эта великолепная утилита, котороя
позволит вам создать цветовое перетекание в тексте любым цветом.
Достаточно
нажать несколько кнопок." -->
<!--#include virtual="_item.html" -->
<!--#include virtual="_foot.html" -->
Данный пример
замечательно иллюстрирует передачу параметров вставляемым
файлам, возможность использования вложенного SSI, а также
работу с условными операторами. В случае, если потребуется
изменить внешний вид этих страниц, достаточно поменять всего
три файла. Тут же весь раздел приобретет новый вид. Или можно,
отредактировав один единственный файл отключить показ всех
картинок в разделе.
В заключение
хотим сказать, что нами (а точнее А.Ю.) написан пакет подпрограмм
для Perl, который позволяет включать HTML из CGI-скрипта с
обработкой директив SSI внутри этого HTML. Лежит он у нас
в Кладовой - http://www.webclub.ru/repository/archive/cgi-scripts/ssi-pl.tgz.
Только мы должны вас предупредить - работают только базовые
директивы, выражения не обрабатываются вовсе. |