Server Side Includes
Server Side Includes - включения на стороне сервера. SSI представляет механизм включения одних документов внутрь других. Чем-то это схоже с фреймами по функциональному назначению, но есть существенные отличия. Во-первых, включать в один HTML-документ можно любой файл с HTML-кодом, совершенно не обязательно, чтобы он(HTML-код) представлял собой законченный HTML-документ. Например, у вас часть таблицы может быть в одном файле, часть в другом, а еще часть в третьем. Во-вторых, включать можно программы, которые, в свою очередь, могут связываться с базами данных, вызывать внутри себя другие программы и выдавать какие-либо отчеты и таблицы. Естественно, что эти программы выдают на STDOUT( поток стандартного вывода, для не программистов это экран монитора с командной строкой ) HTML-код, который затем и включается внутрь нашего исходного HTML-документа. И в третьих, SSI поддерживают переменные и элементарные инструкции языка программирования: if, elif и else. Server Side Includes работают следующим образом. У вас на сервере находится html-файл с командами SSI.
<!--#include virtual="/cgi-bin/head.pl?name=О нас" --> <p align=justify> Веб-студия ITSoft состоит из молодых специалистов, работающих в области информационных технологий более пяти лет. Мы занимаемся веб-дизайном, разработкой программного обеспечения, предоставляем услуги хостинга и создания локальных сетей. <!--#include virtual="/include/footer.inc"-->
Когда броузер клиента запрашивает у веб-сервера этот документ, то веб-сервер, прежде чем отдать его броузеру проверяет его на наличие SSI-команд. Когда веб-сервер встретит <!--#include virtual="/cgi-bin/head.pl?name=О нас" --> он запустит программу /cgi-bin/head.pl и передаст ей параметр name=О нас. Программа head.pl выдаст HTML-код с заголовком для нашего HTML-документа, в котором будет содержаться меню и название раздела. О том, как писать такие программы вы узнаете в третей части книги. Когда веб-сервер натолкнется на <!--#include virtual="/include/footer.inc"-->, то он просто включит HTML-код из файла /include/footer.inc в наш HTML-документ.
Там, собственно, хранится код завершающий любую HTML-страницу нашего веб-сайта. Таким образом, SSI позволяет избежать избыточности. Общий код для всех HTML-страниц нашего сайта хранится в одном месте. Теперь, если нам захочется добавить пункт меню или поменять что-либо еще, то нам не придется бегать по всему сайту и изменять каждый файл отдельно. Достаточно будет внести изменения в один файл. Для того чтобы начать экспериментировать с SSI-командами надо внести изменения в файл httpd.conf и перезапустить веб-сервер Apache. Найдите и раскомментируйте следующие две строчки в файле httpd.conf. Они указывают веб-серверу, что файлы с расширением shtml надо обрабатывать прежде, чем выдавать пользователю.
AddType text/html .shtml AddHandler server-parsed .shtml
Если вы собираетесь повсеместно использовать SSI, то добавьте еще и такую строчку. У нас SSI-команды присутствуют в большинстве HTML-документов, поэтому на нашем веб-сервере такая строчка присутствует в файле httpd.conf
AddHandler server-parsed .html
HTML-код для включения в HTML-документы обычно хранится в файлах с расширением inc. Включите и для этих файлов обработку SSI-директив. Это позволит делать рекурсивную обработку SSI-директив. Если в файле footer.inc будет SSI-директива, то она будет обработана.
AddHandler server-parsed .inc
Еще может потребоваться добавить опцию Includes в следующий раздел.
<Directory /> Options FollowSymLinks Indexes MultiViews Includes AllowOverride All </Directory>
На нашем сервере под управлением FreeBSD такая опция стоит. У меня дома на Windows98 ее нет и SSI работают. Возможно тут дело в различных версиях Apache.
Теперь перезапустите веб-сервер. Давайте рассмотрим SSI еще на одном примере, заодно разберем одну из самых распространенных структур организации HTML-документов. На большинстве сайтов, документы состоят из трех частей: заголовок, тело и завершающая часть. Для эксперимента создайте директорию на вашем веб-сайте и назовите ее ssi. В этой директории создайте head.inc со следующим содержанием:
<html> <body>
<table bgcolor=#0000FF width=600 height=100> <tr><td> Здесь будет заголовок и главное меню нашего вебсайта </table>
<table width=600 height=200> <tr><td width=120 bgcolor=#CCCCCC> Левое меню<br> пункт1<br> пункт2<br> пункт3<br> пункт4<br> пункт5<br> <td>
Все SSI-директивы имеют следующую семантику <!--#команда параметр="значение" параметр="значение"--> Создайте index.html:
<!--#include virtual="head.inc"--> Основное содержание HTML-документа. <!--#include virtual="footer.inc"-->
И footer.inc:
</table>
<table bgcolor=#0000FF width=600> <tr><td> Здесь будет завершающая часть HTML-документа, обычно это реклама </table>
</body> </html>
В результате, при запросе этого документа, веб-сервер выдаст:
<html> <body>
<table bgcolor=#0000FF width=600 height=100> <tr><td> Здесь будет заголовок и главное меню нашего вебсайта </table>
<table width=600 height=200> <tr><td width=120 bgcolor=#CCCCCC> Левое меню<br> пункт1<br> пункт2<br> пункт3<br> пункт4<br> пункт5<br> <td>
Основное содержание HTML-документа. </table>
<table bgcolor=#0000FF width=600> <tr><td> Здесь будет завершающая часть HTML-документа, обычно это реклама </table>
</body> </html>
Это одно из самых основных применений SSI. Теперь давайте рассмотрим использование переменных и условных операторов. Команда <!--#printenv --> выводит все переменные окружения, которые доступны по умолчанию. Ниже приведен результат действия этой команды на моем домашнем компьютере.
COMSPEC=C:\WINDOWS\COMMAND.COM DOCUMENT_ROOT=c:/projects/www/web-tehnolog HTTP_ACCEPT=*/* HTTP_ACCEPT_ENCODING=gzip, deflate HTTP_ACCEPT_LANGUAGE=ru HTTP_CONNECTION=Keep-Alive HTTP_COOKIE=testparam=testvalue HTTP_HOST=web.ru HTTP_USER_AGENT=Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt) PATH=C:\Program Files\Apache Group\Apache;C:\WINDOWS;C:\WINDOWS\COMMAND; C:\ARCH;C:\JDK12\BIN;C:\PROGRA~1\ULTRAE~1 REMOTE_ADDR=127.0.0.1 REMOTE_PORT=1546 SCRIPT_FILENAME=c:/projects/www/web-tehnolog/chapter6.html SERVER_ADDR=127.0.0.1 SERVER_ADMIN=igor@itsoft.ru SERVER_NAME=web.ru SERVER_PORT=80 SERVER_SIGNATURE=Apache/1.3.12 Server at web.ru Port 80
SERVER_SOFTWARE=Apache/1.3.12 (Win32) WINDIR=C:\WINDOWS GATEWAY_INTERFACE=CGI/1.1 SERVER_PROTOCOL=HTTP/1.1 REQUEST_METHOD=GET QUERY_STRING= REQUEST_URI=/chapter6.html SCRIPT_NAME=/chapter6.html DATE_LOCAL=Monday, 26-Feb-2001 19:26:02 Московское время (зима) DATE_GMT=Monday, 26-Feb-2001 16:26:02 GMT LAST_MODIFIED=Monday, 26-Feb-2001 19:25:58 Московское время (зима) DOCUMENT_URI=/chapter6.html DOCUMENT_PATH_INFO= DOCUMENT_NAME=chapter6.html
Для того чтобы вывести значение отдельной переменной дайте команду <!--#echo var="var_name" -->. Например, <!--#echo var="LAST_MODIFIED" --> выдаст Monday, 26-Feb-2001 19:25:58 Московское время (зима).
Также вы можете определять и использовать свои собственные переменные. В файл index.html, который мы рассматривали выше, вставьте самой первой строкой <!--#set var="title" value="Заголовок нашего веб-сайта." -->. В head.inc добавьте следующую строчку <title><!--#echo var="title" --></title> после команды <html> и где идут слова "здесь будет заголовок" вставьте <h1><!--#echo var="title" --></h1>
В результате у вас должно получится для index.html
<!--#set var="title" value="Заголовок нашего веб-сайта." --> <!--#include virtual="head.inc"--> Основное содержание HTML-документа. <!--#include virtual="footer.inc"-->
и
<html> <title><!--#echo var="title" --></title> <body>
<table bgcolor=#0000FF width=600 height=100> <tr><td><h1><!--#echo var="title" --></h1> главное меню нашего веб-сайта </table>
<table width=600 height=200> <tr><td width=120 bgcolor=#CCCCCC> Левое меню<br> пункт1<br> пункт2<br> пункт3<br> пункт4<br> пункт5<br> <td>
Таким образом можно передавать параметры во включаемые куски HTML-кода.
Дурным стилем сайтостроительства считается наличие в документе гиперссылок на этот же документ. Ссылаться на самого себя неразумно - пользователь от нажатия на гиперссылку ожидает, что загрузится другая страница, а также такого рода ссылки доставляют большие неудобства пользователям каналов с низкой пропускной способностью. Такие ссылки на себя часто получаются при включении колонтитулов. Для того чтобы избежать таких ссылок, оформляйте каждый пункт меню в колонтитулах следующим образом:
Пример для графического меню с подсветкой:
<!--#if expr="$DOCUMENT_URI!=/\/about.html/" --><a href=/about.html onMouseOut="MM_swapImgRestore()" onMouseOver="MM_swapImage('about','','/about2.gif',0)" ><!--#endif --><img src=/about1.gif width=212 height=38 border=0 name=about ><!--#if expr="$DOCUMENT_URI!=/\/about.html/" --></a ><!--#endif -->
Данный SSI-код используется на сайте .
Другой не менее важный SSI-код применяется для организации версии страниц для печати. Версия страницы сайта для печати отличается от обычной страницы отсутствием колонститулов, навигации, баннеров и прочей лишней информации. Рассмотрим, как организована версия для печати на примере сайта .
===Файл /include/head.inc === <html> <head> <title><!--#echo var="title"--></title> <meta http-equiv="Content-Type" content="text/html; charset=windows-1251"> <link rel=stylesheet href=/styles.css> </head>
<body bgcolor=FFFFFF text=474C54 link=566A89 vlink=96A7C1 leftmargin=0 topmargin=0 marginwidth=0 marginheight=0> <basefont face=Arial>
<!--#if expr="$QUERY_STRING!=/for_printing/" --> ...здесь навигационный блок, графика, Flash-анимация и т.д. ...
<p > <a href=?for_printing=1&<!--#echo var="QUERY_STRING"-->> Версия для печати </a></p> <!--#endif -->
При нажатии на гиперссылку "версия для печати" страница, на которой находится пользователь, перегружается.
Но поскольку в строке запроса присутствует параметр for_printing, то лишний HTML-код не включается на страницу. Обратите внимание <!--#echo var="QUERY_STRING"-->. Это строка запроса CGI-параметров. В обычном случае, у вас никаких параметров, кроме for_printing нет, но когда появляются на сайте CGI-модули, то появляются и дополнительные параметры. Забегая вперед расскажу, как делать "Версию для печати" В CGI-программе. Пока веб-сервер Apache не может обрабатывать на SSI-директивы вывод CGI-программ. Такую возможность обещают в новых версиях Apache. У CGI-программистов есть два пути либо самим разобрать SSI-директивы в файле head.inc либо, что значительно проще, создать ручками файл phead.inc и подключать его в CGI-программах.
Условные операторы записываются следующим образом:
<!--#if expr="условие1" --> <!-- Здесь HTML-код1 --> <!--#elif expr="условие2" --> <!-- Здесь HTML-код2 --> <!--#else --> <!-- Здесь HTML-код3 --> <!--#endif -->
Для примера приведу SSI-код для вывода времени последней модификации документа в приемлемом виде. Как вы уже видели, команда <!--#echo var="LAST_MODIFIED" --> выдает совершенно не приемлемую строчку - Monday, 26-Feb-2001 19:25:58 Московское время (зима), для размещения ее на солидном веб-сайте. Нам бы хотелось получить что-нибудь, вроде 26 Февраля 2001 года. Для этого существует команда config с параметром timefmt, которая задает формат вывода даты. Например, в нашем случае нам требуется следующий вариант <!--#config timefmt="%e %B %Y"-->, тогда результат <!--#echo var="LAST_MODIFIED" --> будет 26 February 2001. Но это пока все равно не то, что бы нам хотелось. Для определения месяца мы воспользуемся условными операторами. Вот, как будет выглядеть этот код:
<!--#config timefmt="%m" --> <!--#set var="NUM_MONTH" value="$LAST_MODIFIED"--> <!--#if expr="$NUM_MONTH=01" --> <!--#set var="month" value="Января" --> <!--#elif expr="$NUM_MONTH=02" --> <!--#set var="month" value="Февраля" --> <!--#elif expr="$NUM_MONTH=03" --> <!--#set var="month" value="Марта" --> <!--#elif expr="$NUM_MONTH=04" --> <!--#set var="month" value="Апреля" --> <!--#elif expr="$NUM_MONTH=05" --> <!--#set var="month" value="Мая" --> <!--#elif expr="$NUM_MONTH=06" --> <!--#set var="month" value="Июня" --> <!--#elif expr="$NUM_MONTH=07" --> <!--#set var="month" value="Июля" --> <!--#elif expr="$NUM_MONTH=08" --> <!--#set var="month" value="Августа" --> <!--#elif expr="$NUM_MONTH=09" --> <!--#set var="month" value="Сентября" --> <!--#elif expr="$NUM_MONTH=10" --> <!--#set var="month" value="Октября" --> <!--#elif expr="$NUM_MONTH=11" --> <!--#set var="month" value="Ноября" --> <!--#else --> <!--#set var="month" value="Декабря" --> <!--#endif -->
Соответственно, чтобы получить дату в формате 26 Февраля 2001.
<!--#config timefmt="%e"--><!--#echo var="LAST_MODIFIED" --> <!--#echo var="month" --> <!--#config timefmt="%Y"--><!--#echo var="LAST_MODIFIED" -->
Вот полный список значение параметра timefmt:
Формат | Описание | Пример |
%a | Аббревиатура названия дня недели | Sun |
%A | Полное название дня недели | Sunday |
%b | Аббревиатура названия месяца | Jan |
%B | Полное название месяца | January |
%d | День месяца | 01 (не 1) |
%D | Дата в формате "%m/%d/%y" | 01/31/90 |
%e | День месяца | 1 |
%H | Часы в 24-часовом формате | 13 |
%I | Часы в 12-часовом формате | 01 |
%j | День года | 235 |
%m | Номер месяца | 01 |
%M | Минуты | 03 |
%p | AM|PM | AM |
%r | Время в формате "%I:%M:%S %p" | 11:35:46 PM |
%S | Секунды | 34 |
%s | Время в секундах с 01.01.1970 | 957228726 |
%T | Время в формате "%H:%M:%S" | 14:05:34 |
%U | Неделя года | 49 |
%w | Номер дня недели | 5 |
%y | Год в формате ГГ | 95 |
%Y | Год в формате ГГГГ | 1995 |
%Z | Временная зона | MSK |
<a href=0.gif>Прозрачный gif-файл</a><br> Дата модификации:<!--#config timefmt="%d %B %Y" --> <!--#flastmod file="0.gif" --><br> Размер:<!--#config sizefmt="bytes"--> <!--#fsize file="0.gif" --> байта<br>
Дата модификации: 12 February 2002
Размер: 43 байта
Если у вас файлы больших размеров, то информацию лучше выводить в килобайтах.
Для этого установите формат вывода размера файла следующим образом.
<!--#config sizefmt="abbrev"-->
При возникновение какой-либо ошибки, например, при попытки включить в HTML-документ файл, которого не существует веб-сервер выдаст следующее сообщение:
[an error occurred while processing this directive]
Сообщение не слишком информативно и пугает пользователя, не так ли? Давайте изменим сообщение об ошибке следующей SSI-директивой
<!--#config errmsg="<b>На сервере произошла ошибка связанная с SSI, пожалуйста, напишите </b> <a href=mailto:igor@itsoft.ru>администратору</a>."-->
Теперь сообщение об ошибке вылядит так:
На сервере произошла ошибка связанная с SSI, пожалуйста, напишите .