6: Применение методов доступа HTTP в рамках программирования CGI-скриптов. Настройка HTTP-сервера для работы с CGI-скриптами

Bash CGI

6: Применение методов доступа HTTP в рамках программирования CGI-скриптов. Настройка HTTP-сервера для работы с CGI-скриптами

Метод доступа GET

Метод доступа GET долгое время был основным методом доступа из форм к CGI-скриптам. Это происходило по причине отсутствия при вводе большого количества данных и из-за прямого обращения к скриптам по их URL. В настоящее время ситуация меняется, но тем не менее данный метод занимает едва ли не главное место в программировании обработки данных из HTML-форм.

Условно использование GET можно разбить на два способа:

  • запросы типа isindex ;
  • запросы типа form-urlencoded .

В первом случае имитируется или реально происходит передача запроса, который появляется при вводе данных в строке приглашения контейнера ISINDEX. Во втором случае происходит передача пар "имя_поля=значение". И в том, и в другом случае данные, не входящие в кодировку Latin1, преобразуются в пары шестнадцатеричных символов, предваряемых символом "%" (%20 — пробел).

Кроме вызова скрипта непосредственно из гипертекстовой ссылки, скрипт можно запустить и через Server Side Includes. В этом случае данные из формы будут приписываться к URL документа, а не скрипта. Скрипт при этом будет вызываться сервером при разборе текста HTML-страницы перед отправкой ее клиенту.

Кроме собственно запроса, который в методе GET появляется в URL после символа "?", скрипту еще можно передать информацию в HTTP-пути. Это переменная окружения PATH_INFO . Обработка данных из этой переменной требует особого подхода к их получению и использованию в скрипте и гипертекстовых ссылках.

Запрос isindex

Запрос типа isindex является исторически первым способом передачи данных от браузера серверу . Он был разработан для передачи списка ключевых слов для поисковой машины. Запрос данного типа появляется либо в случае использования контейнера ISINDEX, либо при прямом обращении к скрипту через гипертекстовую ссылку. Данный тип запроса имеет ряд особенностей, которые отличают его от запроса типа form-urlencoded.

При использовании контейнера ISINDEX в начале документа появляется шаблон ввода ключевых слов. После ввода списка слов, разделенных пробелом, вызывается скрипт, который принимает список, разбирает его на отдельные слова и выполняет необходимую обработку. Первоначально isindex был ориентирован на модуль, подключавший поисковую систему WAIS к серверу CERN. После появления спецификации CGI стало возможным передавать списки слов любому CGI-скрипту. Запрос типа isindex определен только для метода доступа GET .

Согласно спецификации CGI для метода GET запрос присоединяется к URL документа или скрипта (указан атрибут ACTION в контейнере ISINDEX) после символа "?"(getis2.htm):

 http://localhost/htdocs/isindex.htm?search+
       engine+world+wide+web
   

или

http://localhost/htdocs/isindex.cgi?search+
       engine+world+wide+web
   

Как видно из этого примера, в запросе пробел заменяется на символ "+". Причем буквы русского алфавита в таком запросе перекодировать не надо, они передаются как есть. Если пользователь работает с локализованной версией операционной среды, то все будет отображаться так, как положено. В случае нелокализованной версии операционной среды, например, Windows NT, буквы будут отображаться абракадаброй, но в скрипт будут передаваться правильные коды.

Традиционно в GET данные запроса выбираются из переменной окружения QUERY_STRING. Например, это можно сделать на Perl следующим образом:

   #!/usr/local/bin/perl
   print "Content-type: text/plain\n\n";
   print "Запрос: $ENV{QUERY_STRING}.\n";
   

В данном примере первый оператор печати формирует заголовок HTTP-сообщения в соответствии со спецификацией CGI. Второй оператор печати распечатывает содержание переменной окружения QUERY_STRING. Главное при этом — разделить запрос на отдельные слова, чтобы можно было использовать их в качестве ключей поиска. В Perl для этого существует функция split:

   #!/usr/local/bin/perl
   print "Content-type: text/plain\n\n";
   print "Запрос: $ENV{QUERY_STRING}.\n";
   @words = split('+',$ENV{QUERY_STRING});
   foreach $word (@words)
   {
   print $word,"\n";
   }
   

В данном случае следует обратить внимание на то, что в запросе нет никаких имен полей — только введенные слова и их разделители. Естественно, если среди введенных символов встретится разделитель, он будет заменен шестнадцатеричным.

У запроса isindex есть еще одно замечательное свойство — это передача данных в командной строке CGI-скрипта. Очевидно, что ввести аргументы пользователь не в состоянии (у него нет удаленного терминала), но вот принять данные из командной строки скрипт может:

   #!/usr/local/bin/perl
   print "Content-type: text/plain\n\n";
   print "Запрос: $ENV{QUERY_STRING}.\n";
   $n = @ARGV;
   for($i=0;$i<$n;++$i)
   {
   print $ARGV[$i],"\n";
   }
   

Внешне результаты работы данного скрипта и скрипта разбора QUERY_STRING ничем не отличаются. Но данные они получают из разных источников (getis6.htm).

Запрос типа isindex не порождается событием onSubmit, как это происходит в запросах form-urlencoded . Он является одной из разновидностей схемы http универсального локатора ресурсов (URL). При использовании обычной контекстной гипертекстовой ссылки (контейнер A (anchor)) запрос просто дописывается вслед за символом "?".

При программировании на JavaScript обратиться к скрипту через запрос isindex можно либо путем изменения значения атрибута HREF в одном из элементов массива гипертекстовых ссылок документа, либо путем вызова метода replace() объекта Location.

Запрос form-urlencoded

В методе GET запрос типа form-urlencoded является основной формой запроса. От запроса типа isindex он отличается форматом и способом передачи, точнее, кодировкой данных в теле HTTP-сообщения. Данные формы попадают в запрос, который расширяет URL скрипта в виде пар "имя_поля=значение&имя_поля=значение&...". Например, для формы вида:

   <FORM ACTION=test.cgi METHOD=get>
   Поле1:<INPUT NAME=f1 VALUE=value1>
   Поле2:<INPUT NAME=f2 VALUE=value2>
   <INPUT TYPE=submit VALUE="Послать">
   </FORM>
   

запрос в сообщении HTTP-протокола будет выглядеть следующим образом:

   GET /test.cgi?f1=value1&f2=value2 HTTP/1.0
   

Несмотря на то, что в форме имеется три поля, переданы будут значения только двух полей. Это связано с тем, что у третьего поля в форме нет имени. Если у поля нет имени, то его значение не передается серверу . Это правило общее для всех полей. Чаще всего оно применяется для полей подтипов submit и reset типа text.

Применение неименованных полей позволяет передавать в скрипт только ту информацию, которая реально требуется для выполнения обработки данных. Иногда неименованные поля применяют и при программировании на JavaScript.

Кроме формата в запросе типа form-urlencoded , данные, введенные в форму, подвергаются дополнительной обработке — кодированию.

Кодирование, собственно, и дало название методу (urlencoded). Согласно спецификации, текстовое сообщение не может содержать символы, не входящие в набор Latin1. Это означает, что вторая половина таблицы ASCII и первые 20 символов должны быть закодированы. В CGI символ кодируется как две шестнадцатеричные цифры, следующие за знаком "%". Для российских Web-узлов это означает, что скрипт, который принимает запрос, должен предварительно перекодировать все шестнадцатеричные эквиваленты в символы (getform2.htm). На Perl это можно реализовать в одну строку:

   query =~ s/%(.{2})/pack('c',hex($1))/ge;
   

В данном случае мы осуществляем глобальную подстановку (оператор "=~ s///"), который употреблен с модификаторами "ge". Первый модификатор обозначает глобальную замену по всей строке query, а второй требует выполнения перед заменой выражения "pack('c',hex($1))". Более подробно о программировании на Perl см. раздел "Введение в программирование на Perl".

Передача параметров через PATH_INFO

Передача данных в скрипты возможна не только при помощи переменной окружения QUERY_STRING или аргументов командной строки скрипта. Передать параметры в скрипт можно через переменную окружения PATH_INFO. Данная переменная принимает свое значение после преобразования URL скрипта. Рассмотрим следующий URL:

   http://localhost/cgi-bin/test/arg1/arg2/arg3?param1+param2
   

Согласно спецификации URI адрес ресурса делится на две части: название схемы адресации и путь к ресурсу:

схема разделитель путь к ресурсу
http : //localhost/cgi-bin/test/arg1/arg2/arg3?param1+param2

схема адресации задается протоколом обмена данными. Обращение к скрипту осуществляется по схеме http. В свою очередь, в схеме http путь снова делится на две части: адрес ресурса и параметры. Эти части разделены символом "?". Параметры могут быть записаны либо в форме isindex, либо в формате form-urlencoded:

адрес ресурса разделитель параметры
//localhost/cgi-bin/test/arg1/arg2/arg3 ? param1+param2

Адрес ресурса в случае обращения к скрипту снова можно разделить на две части — адрес скрипта и путевой параметр PATH_INFO:

адрес скрипта PATH_INFO
//localhost/cgi-bin/test /arg1/arg2/arg3

В данном случае явного разделителя между адресом скрипта и PATH_INFO нет. Деление определяется настройками сервера . У большинства серверов стандартным каталогом CGI-скриптов является каталог cgi-bin. При этом подразумевается, что все файлы этого каталога — скрипты. Можно даже указать файл с расширением html, который в данном случае будет интерпретироваться как скрипт (getpath1.htm). Значение путевого параметра сервер помещает в переменную окружения PATH_INFO. При этом в нее попадает и лидирующий символ "/".

Управление работой скрипта через путевой параметр довольно популярно. Например, при выполнении перенаправления, когда нужно собирать статистику обращений к ресурсам, расположенным вне Web-узла:

   http://localhost/cgi-bin/banner/
     	http://otherhost/page.html
   

Вообще говоря, при таких перенаправлениях возникает опасность Web-спуффинга. Существует очень большая вероятность, что администратор не заметит подмены одной из частей такого URL.

PATH_INFO применяется не только в совокупности с каталогами скриптов, но и с любым скриптом, определенным пользователем. Часто в качестве такого скрипта определяются файлы с расширением *.cgi:

   http://www.intuit.ru/~user/script.cgi/path_param/test?arg1+arg2
   

В этом примере в переменную PATH_INFO попадет /path_param/test.

Метод доступа POST и другие методы доступа

Метод POST — это второй основной метод доступа к информационным ресурсам Web-узла. Он является альтернативой методу GET . Вообще, при HTTP-обмене используются три основных метода: GET , POST и HEAD. Первые два предназначены для получения страниц. Страницы при этом передаются в виде тела HTTP-отклика. При методе GET от клиента к серверу отправляется запрос, состоящий только из заголовка HTTP-сообщения. Все введенные пользователем данные размещаются в URL документа. При методе POST от клиента к серверу уходит запрос, который состоит из заголовка и тела HTTP-сообщения. При этом данные, введенные пользователем, размещаются в теле запроса. Метод HEAD применяется только для управления обменом и отображением. В рамках данного метода тело HTTP-сообщения не передается как клиентом в запросе, так и сервером в отклике.

Основное назначение метода POST — передача сравнительно больших объемов данных от клиента к серверу . Применение этого метода оправдано при передаче сложных состоящих из множества полей форм. В спецификации CGI от NCSA рекомендуется использовать метод POST при передаче данных из форм, содержащих поля textarea.

Современное использование Web в качестве альтернативы FTP-архивам расширило свойства метода POST . Так, большинство архивов научной периодики построено по принципу их обновления авторами статей. Для этой цели используются страницы с формами, содержащими поля типа File-upload. Этот механизм позволяет передать на сервер файл любого размера и любого типа. При этом сами пользователи не получают Web-account на сервере архива, они пользуются стандартным скриптом публикации.

Из перечисленных выше методов только POST формирует тело сообщения. В спецификации CGI речь при этом идет только об HTTP-сообщениях. Но современные браузеры — это мультипротокольные программы. При этом в качестве гипертекстовых ссылок можно использовать различные схемы. Во многих протоколах, на которые эти схемы указывают, нет понятия метода доступа. Тем не менее в контейнере FORM такой метод можно использовать, например, со схемой mailto. В данном случае ни по какому методу POST , который не определен в протоколе SMTP, ничего не передается. POST просто заставляет браузер создать тело, в данном случае, почтового сообщения.

Чтение данных из стандартного потока ввода

При передаче запроса по методу POST от клиента к серверу передается HTTP-сообщение, которое состоит из заголовка и тела. Данные, введенные в HTML-форму, как раз и составляют тело сообщения. При обработке такого запроса CGI-скриптом данные следует выбирать из стандартного потока ввода скрипта, а не из переменной окружения QUERY_STRING. Эта переменная будет иметь пустое значение.

Для того, чтобы принять данные, нужно прочитать стандартный поток ввода. При этом из стандартного потока ввода нужно считать строго определенное количество байтов. Число байтов определяется переменной окружения CONTENT_LENGTH. В Perl прием данных в скрипт можно организовать следующим образом:

   #!/usr/local/bin/perl
   read STDIN,$query,$ENV(CONTENT_LENGTH);
   

Здесь из стандартного потока ввода STDIN считывается $ENV(CONTENT_LENGTH) данных и помещается в переменную $query. После этого можно уже что-то делать с запросом, например, распечатать его в виде HTML-таблицы.

Аналогично можно принять запрос из стандартного ввода и в С. Для этого следует воспользоваться в простейшем случае функцией getchar():

   #include <stdlib.h>
   #include <malloc.h>
   void main()
   {
   int n,i;
   char *buff;
   n = atoi(getenv("CONTENT_LENGTH");
   buff = (char *) malloc(n+1);
   memset(buff,'\000',n+1);
   for(i=0;i<n;i++)
   {
   buff[i] = getchar();
   }
   printf("Content-type: text/plain\n\n");
   printf("Length of data into STDIN:%d\n",n);
   printf("STDIN data: %s\n",buff);
   free(buff);
   }
   

Посимвольное чтение в этом примере можно заменить чтением по функции fread(). При этом не следует ожидать существенного уменьшения времени чтения данных. Во-первых, данные при вводе буферизуются. Во-вторых, в С применяется потоковая модель работы с внешними наборами данных.

Передача присоединенных файлов

Метод POST позволяет реализовать передачу файлов с компьютера пользователя в архив на HTTP- сервере . Для этой цели разработана специальная форма кодирования тела документа: multipart/form-data. Она указывается в контейнере FORM в атрибуте ENCTYPE совместно с методом POST :

   <FORM ENCTYPE=multipart/form-data 
        METHOD=post>
   

Скрипт, который принимает такие данные, должен определить метод доступа, затем определить тип тела документа и только после этого начать разбирать тело. В теле может быть как минимум две части: значения различных полей, которые доставляются скрипту в первой части сообщения, и тело передаваемого файла, которое передается как вторая часть сообщения.

Поля разбираются по традиционной схеме. Это обычные ASCII-символы. С ними никаких проблем не возникает. Тело документа передается как есть, т.е. без преобразований. Это значит, что применять для его выделения текстовые функции С нельзя, т.к. внутри документа могут попадаться любые символы, в том числе и символы конца символьного массива (строки).

Чтобы убедиться в этом, достаточно просто распечатать данные, посланные браузером. Для приема данных и их разбора нужно либо написать собственную программу, либо воспользоваться готовыми программами и библиотеками языка Perl, например.

Очевидно, что метод POST с полями file-upload используется для опубликования данных на стороне сервера . При этом файл, который передается по сети, должен быть размещен в файловой системе либо сервера , либо другого удаленного компьютера. Для этого пользователь, от имени которого запускается скрипт, должен иметь соответствующие права на доступ к каталогу файловой системы компьютера, в который записывается файл. Довольно часто модули стандартных библиотек, например, CGI_Lite или CGI.pm, используют для временного хранения каталог /tmp. Иногда данный каталог закрывают на запись, из-за чего могут возникнуть проблемы с приемом данных скриптом, составленным из модулей стандартной библиотеки.

Стандартные библиотеки разбора данных

Разбор запроса по методу POST CGI-скриптом — это рутинная процедура. При запросе типа urlencoded нужно просто выделить имена полей и их значения, а при запросе типа multipart/form-data — выделить части составного тела запроса и преобразовать их в имена полей, их значения и файлы.

С 1995 года было написано достаточно много заготовок для такого разбора, которые оформлены в виде свободно распространяемых библиотек. Наиболее популярными являются библиотеки модулей Perl — CGI.pm и CGI_Lite.

CGI.pm — полный набор функций для генерации HTML-файлов с формами и разбора запросов CGI-скриптами.

CGI_Lite — это средство работы с составными (multipart/form-data) запросами. При работе с функциями данного модуля следует иметь в виду, что временные файлы эти функции размещают в каталоге /tmp.

Метод доступа PUT и другие способы использования CGI-скриптов

Кроме стандартных способов использования CGI-скриптов, т.е. приема запросов от браузеров по методам GET и POST , скрипты применяются и для решения ряда других задач. К таким задачам можно отнести обслуживание расширенного набора методов доступа, например, PUT и DELETE.

Кроме того, для исполнения скриптов сам HTTP- сервер должен быть настроен соответствующим образом. В конфигурации по умолчанию сервера Apache предполагается, что все стандартные скрипты будут размещаться в каталоге ~server_root/cgi-bin, а скрипты пользователя будут иметь расширение *.cgi.

Если эксплуатируется только один Web-узел, этих настроек вполне достаточно. Если же на одной вычислительной установке эксплуатируется несколько виртуальных Web-узлов, то для каждого из них следует дополнительно определять и каталоги стандартного размещения, и расширения по умолчанию, и методы обработки нестандартных методов доступа.

Нередко CGI-скрипты применяются в качестве подстановок SSI на стороне сервера . Схема проста: HTML-документ используется как шаблон, в котором HTML-комментарии задают команды подстановок. В зависимости от различных условий сервер , который обрабатывает эти документы перед отправкой клиенту (браузеру), вставляет в шаблон результаты выполнения команд подстановок, в частности CGI-скриптов.

Преимущество CGI-скриптов в данном случае заключается в том, что они работают с переменными окружения , порожденными сервером для скрипта, а не с системными переменными окружения . Это позволяет включить механизмы анализа IP-адреса клиента, его доменного имени или cookie, чего нельзя сделать при работе с обычным набором переменных окружения , который порождается операционной системой.

Настройки сервера для работы с CGI-скриптами

Для исполнения CGI-скриптов сервер Apache должен быть соответствующим образом настроен. Во-первых, он должен быть собран с модулем исполнения CGI-скриптов (обычно включен по умолчанию), во-вторых, в файлах настройки сервера следует указать опции управления исполнением CGI-скриптов.

В данном разделе мы будем подразумевать, что сервер собран с модулем исполнения CGI-скриптов, поэтому обратимся сразу к настройкам сервера .

В версиях Apache, начиная с 1.2.6 можно все директивы настроек сервера включать в один файл httpd.conf. Однако традиционный способ настройки , который унаследован от NCSA- сервера , предполагает использование трех файлов настройки , которые отвечают за:

  • настройку самого сервера (httpd.conf);
  • настройку ресурсов Web-узла (srm.conf);
  • настройку управления доступом к ресурсам (access.conf).

Для виртуальных хостов все директивы размещаются в файле httpd.conf в разделах описания каждого из виртуальных хостов.

httpd.conf

В этом файле определяются скрипты обработки нестандартных методов доступа (PUT или DELETE), а также описания работы с CGI-скриптами для виртуальных хостов.

Для указания скрипта обработки нестандартного метода используют директиву Script:

   Script PUT put_script.cgi
   

Вместо PUT здесь можно указать DELETEили другой метод доступа. При обращении по данному методу доступа будет вызван скрипт, который указан в качестве второго аргумента.

Директивы для описания работы со скриптами для виртуальных хостов размещают внутри контейнера VirtualHost:

   <VirtualHost>
   ...
   </VirtualHost>
   

Внутрь этого контейнера можно помещать все директивы, которые размещают для основного сервера в файлах httpd.conf, srm.conf, access.conf.

srm.conf

В этом файле определяется конфигурация ресурсов, которыми управляет сервер . Скрипты входят в состав этих ресурсов. Каталог скриптов по умолчанию определяет директива ScriptAlias:

   ScriptAlias cgi-bin 
        /usr/local/etc/httpd/cgi-bin
   

В данном каталоге определяется синоним части URL (первый параметр директивы), которому ставится в соответствие реальный путь в каталоге файловой системы вычислительной установки, где эксплуатируется сервер (второй аргумент). Например:

   http://server.intuit.ru/cgi-bin/test.cgi
   

обращается к файлу

   /usr/local/etc/httpd/cgi-bin/test.cgi
   

Кроме стандартного места размещения скриптов, которое определяется через ScriptAlias, скрипты можно хранить в произвольном каталоге, внутри дерева каталогов сервера .

Дерево каталогов сервера определяется директивой DocumentRoot:

   DocumentRoot /www/host.ru/htdocs
   

или

   DocumentRoot htdocs
   

В первом случае указан полный путь, от корня файловой системы, а во втором — относительный путь, т.е. путь от домашнего каталога сервера .

Для того, чтобы можно было запускать скрипты, нужно добавить handler (обработчик) для запуска скриптов из заданного каталога:

   SetHandler cgi-script
   

Кроме того, с расширением файла можно связать MIME-тип, по которому сервер распознает скрипт:

   AddType application/x-www-form-urlencoded .pl
   

В данном случае мы назначаем расширение *.pl для CGI-скриптов. Традиционным расширением скриптов по умолчанию является расширение *.cgi.

access.conf

Наиболее важной директивой в этом файле с точки зрения исполнения скриптов является Options. Она используется внутри контейнера Directory:

   <Directory /usr/local/etc/httpd/htdocs>
   Options ExecCGI
   </Directory>
   

В данном случае для каталога /usr/local/etc/httpd/htdocs будет разрешено исполнение CGI-скриптов.

Скрипты для обработки нестандартных методов доступа

Для того, чтобы обработать метод доступа, отличный от GET или POST , необходимо выполнить несколько условий: подготовить скрипт для обработки данного метода, настроить сервер и определить соответствующие права доступа к каталогам, с которыми этот скрипт будет работать. Рассмотрим как это делается на примере обработки запроса по методу PUT.

Некоторые серверы , например IIS компании Microsoft, имеют встроенные модули для работы с методом PUT. Сервер Apache такого модуля в стандартной комплектации не имеет, но позволяет подключить скрипт для обработки запросов по методу PUT.

Сама программа обработки таких запросов может выглядеть следующим образом:

   #!/usr/local/bin/perl
   if($ENV{REQUEST_METHOD} ne "PUT")
   {
   die "Content-type: text/plain\n\nМетод доступа не PUT";
   }
   $fname=$ENV{PATH_TRANSLATED};
   if(!$fname)
   {
   die "Content-type: text/plain\n\nНе указана мишень вывода";
   }
   $length=$ENV{CONTENT_LENGTH};
   if(!$length)
   {
   die "Content-type: text/plain\n\nСтраница имеет нулевой размер";
   }
   read(STDIN,$page,$length);
   open(OUT,">$fname");
   print OUT $page;
   close(OUT);
   print "Content-type: text/plain\n\nДанные получены.";
   
Листинг 24.1. (html, txt)

Первый оператор if проверяет метод доступа, второй — адрес страницы, которую следует разместить, третий — наличие самих данных для размещения по адресу страницы. Проверок для полной уверенности в передаче данных на самом деле нужно выполнить несколько больше. Кроме того, требуется сгенерировать код возврата и запись в журнал посещений, чтобы этот пример стал реально действующей программой. Теперь нужно настроить сервер . Для этого в файле конфигурации сервера httpd.conf следует указать:

   Script PUT cgi-сценарий
   

Здесь cgi-сценарий — это имя нашего скрипта.

После этого для нашего сценария, а, точнее, для пользователя, от которого он запускается, нужно разрешить запись данных в каталог размещения страниц и, если это необходимо, внести изменения в файлы настройки процедуры аутентификации.

Скрипты и Server Side Includes

Стандартный модуль подстановок (includes) сервера Apache позволяет задействовать CGI-скрипты для генерации подстановок. Скрипт, в отличие от обычной программы, наследует переменные окружения , которые генерирует сервер для CGI-скриптов, а не стандартный набор переменных окружения оболочки (shell).

   <!--#exec cgi="/cgi-bin/include.cgi" -->
   

В данном случае мы вставили в документ результат работы скрипта include.cgi.

Вставку можно использовать и не для генерации части текста документа, а для анализа данных, передаваемых в страницу или для анализа переменных окружения CGI-скрипта, т.е. условий обращения к странице. Например, для анализа IP-адреса пользователя и условного перенаправления запроса.

Для того, чтобы сервер выполнил подстановки в файл srm.conf, нужно внести строку определения типа документов, подлежащих разбору (server parsed documents):

   AddType text/x-server-parsed-html .shtml
   

Расширение файла *.shtml обычно используется для документов, требующих анализа их содержания на предмет выполнения подстановок. Если администратор желает распространить предварительный анализ содержания документов на все документы, то вместо или в дополнение к .shtml можно указать и .html.

Кроме того, для каталога (файл access.conf — общий файл конфигурации доступа или .htaccess — файл конфигурации доступа, расположенный в данном каталоге и переопределяющий правила доступа), в котором расположены документы в директиве Options, должны быть разрешены и подстановки, и исполнение CGI-скриптов:

   <Directory /usr/local/etc/httpd/htdocs>
   AllowOverride
   Options Includes ExecCGI
   </Directory>
   

В данном случае для домашнего каталога документов сервера Apache, который используется в настройках по умолчанию, разрешено переопределять опции доступа в подкаталогах (AllowOverride) и исполнять подстановки и скрипты (Options Includes ExecCGI). По умолчанию обычно используют вместо последних двух опций одну — All. Она тоже разрешает подстановки и выполнение скриптов, а также ряд других действий:

   <Directory /usr/local/etc/httpd/htdocs>
   AllowOverride
   Options All
   </Directory>
   

Вообще говоря, существует возможность разрешить подстановки, но запретить выполнение скриптов:

   <Directory /usr/local/etc/httpd/htdocs>
   AllowOverride
   Options IncludesNoExec
   </Directory>
   

В этом случае отключаются не только скрипты, но и обычные команды, выполняемые из стандартной оболочки (shell). При этом можно разрешить исполнение скриптов самих по себе, но не в качестве вставок.

   <Directory /usr/local/etc/httpd/htdocs>
   AllowOverride
   Options IncludesNoExec ExecCGI
   </Directory>
   

В данной конфигурации исполнение скриптов разрешено, а выполнение подстановки по команде exec запрещено.