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, а также работу с условными операторами. В случае, если потребуется изменить внешний вид этих страниц, достаточно поменять всего три файла. Тут же весь раздел приобретет новый вид. Или можно, отредактировав один единственный файл отключить показ всех картинок в разделе.
Оставить комментарий
Комментарии
точнее, символы угловых скобок заменяет на комбинации > и <
сервер не обрабатывает содержимое переменных, т.к для это нужно выполнить 2 прохода.
Пример 1 (необходимо поместить несколько строк или таблиц в середину
first.shtml):
Создаю 3 файла: index.shtml, first.shtml, second.inc
index.shtml
<!--#set var="TEXT" value="<!--#include virtual=\"/second.inc\"-->"-->
<b>Главная страница</b><br>
<!--#include virtual="/first.shtml"-->
first.shtml
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
</head>
<body>
<!--#echo var="TEXT"-->
</body>
</html>
second.shtml
Вложение.
Результат: На экране вижу:
Главная страница
<!--#include virtual="/second.inc"-->
Хочу видеть:
Главная страница
Вложение.
Пример 2.
Создаю 1 файл: index.shtml
<!--#set var="TEXT" value="<b>Строка1</b><br>Строка2<br><b>Строка3</b>"-->
<b>Главная страница</b><br>
<!--#include virtual="/first.shtml"-->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
</head>
<body>
<!--#echo var="TEXT"-->
</body>
</html>
Результат:
Главная страница
<b>Строка1</b><br>Строка2<br><b>Строка3</b>
Хочу видеть:
Главная страница
Строка1
Строка2
Строка3
Т.е. не могу корректно сделать вложение в директиве.
Возможно это не поддерживается. Если так, то посымаю голову пеплом.
Я понимаю что есть много методов рещения таких простых задачь, но мне интересно именно это.
Заранее спасибо за ответ.
Только что можно еще делать.Ведь мой хостер только сие средство дозволяет применить вн своем ресурсе. А мен хотелось бы и что-нибуть посерьезнее,вроде доставки файла на сервер методами,альтернатывными FTP через веб-сраницу.
И вообще,надо учебник писать по этой теме.А то,у ког не спрошу-не дожусь ничего путного по этой теме.