blob: dfa7a60d2ee55b72cc160a6b85b04e5f49fa3d16 [file] [log] [blame]
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/committees/docbook/xml/4.1.2/docbookx.dtd" [
<!ENTITY hello.rvt SYSTEM "examples/hello.rvt" >
<!ENTITY table.rvt SYSTEM "examples/table.rvt" >
<!ENTITY vars.html SYSTEM "examples/vars.html" >
<!ENTITY vars.rvt SYSTEM "examples/vars.rvt" >
<!ENTITY upload.html SYSTEM "examples/upload.html" >
<!ENTITY upload.rvt SYSTEM "examples/upload.rvt" >
]>
<!--
Copyright 2002-2004 The Apache Software Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<article lang="ru">
<articleinfo>
<title>Apache Rivet</title>
<copyright>
<year>2002</year>
<year>2003</year>
<holder>Apache Software Foundation</holder>
</copyright>
<author>
<firstname>The Rivet Team</firstname>
<affiliation>
<orgname>The Apache Software Foundation</orgname>
<address>
<email>rivet-dev@tcl.apache.org</email>
</address>
</affiliation>
</author>
<othercredit>
<firstname>Dmitry</firstname>
<othername>the</othername>
<surname>Zuryanovich</surname>
<contrib>Russian Translation</contrib>
<affiliation>
<address><email>dtz@xepb.ru</email></address>
</affiliation>
</othercredit>
</articleinfo>
<para>
Этот документ в переводах на другие языки: <ulink
url="index.en.html">English</ulink>, <ulink url="index.it.html">Italian</ulink>
</para>
<!-- IMPORTANT: update the number below whenever you update this
document! -->
<para>This document is based on version 1.34 of the original English
version.</para>
<section>
<title>Введение в Apache Rivet</title>
<para>
Apache Rivet - это система для генерации динамических веб
страниц, встроенная модулем в http сервер Apache. Она задумывалась
как система быстрая, мощная, расширяемая и достаточно простая для
внедрения. Стоит заметить что с Apache Rivet вы получаете надежную
платформу которая не только может интегрироваться в web, но
и может быть использована вне его. GUI, инструментарий администратора,
XML, манипуляции с БД, консольные приложения могут использовать тот
же код, который используется при разработках web-приложений.
Это достигается применением языка TCL - вне и внутри Apache сервера.
</para>
<para>
В этом документе мы постараемся помочь вам быстро разобраться как
можно создавать web- приложения, и показать вам дальнейшие
пути для разработки приложений используя rivet для самых
разнообразных применений.
</para>
<para>
Эта документация - как и весь rivet, и тем более ее перевод на
русский - это работа, которая не заврешена, и будем надеяться
будет продолжаться еще очень долго.
Если вы видите что что-то где-то почему-то не так - то пишите
об этом, мы сами за всем не углядим без вашей помощи.
Это Свободное программное обеспечение!
</para>
</section>
<section id="installation">
<title>Установка Apache Rivet</title>
<procedure>
<step>
<title>Check Dependencies/Проверка связей между программным обеспечением</title>
<para>
Для того чтобы установить rivet, вам в первую очередь понадобится
сам Tcl, версии 8.4 или выше и веб сервер Apache версий 1.3.x. Известно
что все должно работать на Linux, FreeBSD,OpenBSD, Solaris и HPUX. Возможно что
можно заставить работать даже на Windows NT - в дистрибутиве
написано как это делать.
</para>
</step>
<step>
<title>Скачайте себе Rivet</title>
<para>
Возьмите исходники отсюда <ulink
url="http://tcl.apache.org/rivet/download"/>.
На данный момент это единственный способ получить rivet.
Возможно в дальнейшем появится FreeBSD port, Debian package,
RPM и бинарники под Windows.
</para>
</step>
<step performance="optional">
<title>Скачайте и соберите Apache</title>
<para>
Rivety нужны заголовки (.h) от Apache. Самый простой способ -
это скачать исходники Apache, хотя во многих системах (Debian,
например) позволяют поставить отдельно заголовки и прочие
вещи, необходимые для разработчиков. Если вы хотите собрать
rivet в статике (вместо того чтобы грузить его как .so), то
вам придется скачать все исходники apache отсюда
<ulink
url="http://httpd.apache.org/"/>.
Мы рекомендуем собирать rivet как динамическую библиотеку
(shared object), и соответственно собирать его отдельно от Apache.
</para>
<para>
Исходный код apache берут тут:<ulink
url="http://httpd.apache.org/"/>
</para>
</step>
<step>
<title>Разархивация исходников</title>
<para>
Сейчас мы будем считать что apache вами был каким-то образом
установлен. Теперь вы должны разархивировать исходники
rivet там где вы хотите их собирать.
<programlisting>gunzip tcl-rivet-X.X.X.tar.gz
tar -xvf tcl-rivet-X.X.X.tar.gz</programlisting>
</para>
</step>
<step>
<title>Компиляция Rivet</title>
<para>
Rivet использует некую свою уникальную систему компиляции
которую мы специально придумали именно для него. Она
использует информацию из инсталяций Apache (через
<command>apxs</command>)и Tcl, для того чтобы собрать rivet
через набор Tcl скриптов, которые находятся
<filename>buildscripts/</filename> тут.
</para>
<substeps>
<step>
<title>Запустите ./configure.tcl</title>
<para>
По смыслу это практчески то же что и
<filename>configure</filename>, скрипт который встречается
в большинстве систем. Он, конечно же, написан на Tcl.
У него есть несколько полезных аргументов:
</para>
<variablelist>
<varlistentry>
<term>-help</term>
<listitem>
<para>Показывает справку.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-enable-symbols</term>
<listitem>
<para>Компилирует Rivet c символами для дебаггера.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-prefix <replaceable>directory</replaceable></term>
<listitem>
<para>
Место в котором будет установлен Rivet.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-with-apxs <replaceable>file</replaceable></term>
<listitem>
<para> <replaceable>file</replaceable> который должен
использоваться как apxs binary для сбора информации о
инсталлированном Apache</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-with-tclconfig <replaceable>file</replaceable></term>
<listitem>
<para>
Использовать <replaceable>file</replaceable> как tclConfig.sh.
</para>
</listitem>
</varlistentry>
</variablelist>
<programlisting>cd src/
./configure.tcl
Configuring
.........done.</programlisting>
</step>
<step>
<title>Запустите make.tcl</title>
<para>
Сейчас нужно скомпилировать Rivet:
</para>
<programlisting>./make.tcl <replaceable>option</replaceable></programlisting>
<para>где <replaceable>option</replaceable> может быть
<option>shared</option> или
<option>static</option>.
</para>
</step>
<step>
<title>Установка</title>
<para>
Сейчас самое время запустить
<command>./make.tcl
install</command> чтобы все установить.
Эта команда должна скопировать получившийся .so
файл (типа
<filename>mod_rivet.so</filename>), если он конечно
скомпилируется, в директорию
Apache
<filename>libexec</filename>, а так же установит
некоторое количество полезных скриптов и прочего кода.
</para>
</step>
</substeps>
</step>
<step>
<title>Конфигурация Apache</title>
<para>
Конфигурировать Rivet достаточно просто - начнем с того что
добавим сам модуль:
</para>
<programlisting>LoadModule rivet_module <replaceable>/usr/lib/apache/1.3/mod_rivet.so</replaceable></programlisting>
<para>
После этого Apache должен знать что ему надо загрузить
Rivet как shared object, чтобы иметь возможность его использовать.
Далее мы должны объяснить Apache какие файлы надо обрабатывать
Rivetом и как это делать:
</para>
<programlisting>AddType application/x-httpd-rivet .rvt
AddType application/x-rivet-tcl .tcl</programlisting>
<para>
Эти директивы объяснят Apache что файлы с расширением
<filename>.rvt</filename> и <filename>.tcl</filename>
надо обрабатывать Rivetом.
</para>
<para>
Все остальные директивы описаны тут
<xref linkend="directives"/>.
</para>
</step>
</procedure>
</section>
<section id="directives">
<title>Конфигурационные параметры Rivet Apache</title>
<para>
Это - разнообразный набор установок которые могут быть
сделаны в конфигурационнном файле Apache с целью
изменения поведения Rivet.
Их формат такой: <command>RivetDirConf</command>,
<command>RivetUserConf</command>,
<command>RivetServerConf</command>,
что означает что DirConf имеет более высокий приоритет и перебивает
установки в UserConf, что в свою очередь перебивает ServerConf.
</para>
<variablelist>
<varlistentry>
<term>
<cmdsynopsis>
<command>RivetServerConf</command>
<group choice="req">
<arg>CacheSize</arg>
<arg>GlobalInitScript</arg>
<arg>ChildInitScript</arg>
<arg>ChildExitScript</arg>
<arg>BeforeScript</arg>
<arg>AfterScript</arg>
<arg>ErrorScript</arg>
<arg>UploadDirectory</arg>
<arg>UploadMaxSize</arg>
<arg>UploadFilesToVar</arg>
<arg>SeparateVirtualInterps</arg>
</group>
</cmdsynopsis>
</term>
<listitem>
<para><command>RivetServerConf</command>
Устанавливает глобальные опции для всего сервера
</para>
</listitem>
<listitem>
<variablelist>
<varlistentry>
<term>
<cmdsynopsis>
<arg>CacheSize</arg>
<arg><replaceable>size</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Устанавливает опции для внутреннего кеша для страниц, где
<option><replaceable>size</replaceable></option>
- количество компилированных страниц которые будут
хранится в кеше для испозьзования в будущем. По умолчанию -
<command>MaxRequestsPerChild</command> / 5, или 50,
если <command>MaxRequestsPerChild</command> установлен в 0.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<cmdsynopsis>
<arg>GlobalInitScript</arg>
<arg><replaceable>script</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Tcl скрипт который должен быть запущен для каждого
интерпретатора.<replaceable><option>script</option></replaceable>
- обычный Tcl скрипт, поэтому чтобы запустить файл -
<programlisting>RivetServerConf GlobalInitScript "source /var/www/foobar.tcl"</programlisting>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<cmdsynopsis>
<arg>ChildInitScript</arg>
<arg><replaceable>script</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Скрипт который будет запущен для каждого дочернего
процесса в Apache. Это идельное место чтобы загружать
модули, создавать глобальные переменные, соединяться
с базами данных и все такое.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<cmdsynopsis>
<arg>ChildExitScript</arg>
<arg><replaceable>script</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Скрипт который будет выполняться когда каждый
порожденный Apache процесс оканчивает работу.
Это идеальное место чтобы освобождать все ресурсы
занятые в
<option>ChildInitScript</option>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<cmdsynopsis>
<arg>BeforeScript</arg>
<arg><replaceable>script</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Скрипт который будет выполняться перед тем как сервер
запустит .rvt страницу. Может быть использован для
того, чтобы, например, создавать стандарный header
(в терминологии http, например - image/png). Также
может быть использован для того чтобы подгружать
код который будет использоваться на каждой странице,
если вы не хотите это делать в
<option>GlobalInitScript</option>
<option>ChildInitScript</option> когда вы
разрабатываете веб сайт в первый раз (примечание переводчика: не понимаю, о чем это
он? последняя строка - построчник)
<note>
Этот код исполняется на глобальном уровне, а не
в том namespace в котором исполняются страницы
</note>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<cmdsynopsis>
<arg>AfterScript</arg>
<arg><replaceable>script</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Скрипт который будет вызываться после каждой (.rvt) страницы.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<cmdsynopsis>
<arg>ErrorScript</arg>
<arg><replaceable>script</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Если внутри rivet произойдет ошибка, то он
сооружает некую html-страницу с информацией о том, что
собственно, произошло. Если же <option>ErrorScript</option>
указан, то можно создать свою страницу, которая будет
вызываться в этом случае. Это может быть полезно
когда вы не хотите показывать пользователю свой
код с ошибками.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<cmdsynopsis>
<arg>UploadDirectory</arg>
<arg><replaceable>directory</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>Директория в которую надо складывать загруженые (uploaded) пользователем файлы.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<cmdsynopsis>
<arg>UploadMaxSize</arg>
<arg><replaceable>size</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>Максимальный размер для загруженных (uploaded) файлов.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<cmdsynopsis>
<arg>UploadFilesToVar</arg>
<group choice="req"><arg>yes</arg><arg>no</arg></group>
</cmdsynopsis>
</term>
<listitem>
<para>
Эта установка регулирует возможность закачки (upload)
файлов прямо в Tcl переменную. Если у вас установлено
ограничение по размеру на закачиваемые файлы, а вам
не особенно хочется общаться со слишком большими файлами,
то эта установка позволяет вам складывать их на диск.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<cmdsynopsis>
<arg>SeparateVirtualInterps</arg>
<group choice="req">
<arg>yes</arg>
<arg>no</arg>
</group>
</cmdsynopsis>
</term>
<listitem>
<para>
Если эта опция установлена, то rivet будет создавать
отдельный интерпретатор Tcl на каждый VirtualHost
в терминологии Apache. Это полезно в ситуации когда
вы - хостер и надо чтобы для каждого клиента был свой
собственный интерпретатор, чтобы они друг с другом
не конфликтовали.
</para>
</listitem>
</varlistentry>
</variablelist>
</listitem>
</varlistentry>
<varlistentry>
<term>
<cmdsynopsis>
<command>RivetDirConf</command>
<group choice="req">
<arg>BeforeScript</arg>
<arg>AfterScript</arg>
<arg>ErrorScript</arg>
<arg>UploadDirectory</arg>
</group>
</cmdsynopsis>
</term>
<listitem>
<para>
Эта установка - тоже самое что
<command>RivetServerConf</command>,
кроме того что они касаются только той директории
в которой они указаны, и ее поддиректорий.
Можно использовать в
<command>Directory</command> разделах.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<cmdsynopsis>
<command>RivetUserConf</command>
<group choice="req">
<arg>BeforeScript</arg>
<arg>AfterScript</arg>
<arg>ErrorScript</arg>
<arg>UploadDirectory</arg>
</group>
</cmdsynopsis>
</term>
<listitem>
<para>
Эти опции - то же самое что и
<command>RivetServerConf</command>,
кроме лишь того что они действуют только для указанной
директории, и ее поддиректорий
</para>
</listitem>
</varlistentry>
</variablelist>
</section>
<section id="commands">
<title>Rivet: Tcl команды и переменные</title>
<refentry>
<refnamediv>
<refname>var</refname>
<refname>var_qs</refname>
<refname>var_post</refname>
<refpurpose>get the value of a form variable.</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>
var
</command>
<group choice="req">
<arg>get</arg>
<arg>list</arg>
<arg>exists</arg>
<arg>number</arg>
<arg>all</arg>
</group>
</cmdsynopsis>
<cmdsynopsis>
<command>
var_qs
</command>
<group choice="req">
<arg>get</arg>
<arg>list</arg>
<arg>exists</arg>
<arg>number</arg>
<arg>all</arg>
</group>
</cmdsynopsis>
<cmdsynopsis>
<command>
var_post
</command>
<group choice="req">
<arg>get</arg>
<arg>list</arg>
<arg>exists</arg>
<arg>number</arg>
<arg>all</arg>
</group>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Описание</title>
<para>
Команда <command>var</command>
предназначена для доступа к переменным которые были
переданы методами GET или POST, не делая между
ними никакой разницы. Стоит заметить что есть еще две
формы команды <command>var</command>:
<command>var_qs</command> и <command>var_post</command>.
Эти команды рассматривают только переменные переданные
GETом и POSTом, соответственно.
</para>
<variablelist>
<varlistentry>
<term>
<cmdsynopsis>
<arg>get</arg>
<arg><replaceable>varname</replaceable></arg>
<arg><replaceable><optional>default</optional></replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Возвращает значение переменной
<option><replaceable>varname</replaceable></option>
как строку, причем даже в случае когда у переменной есть
несколько значений
Если же такой переменной
не было передано - то возвращается
<option><replaceable><optional>default</optional></replaceable></option>,
а если и оно не было указано - то "" - пустая строка.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<cmdsynopsis>
<arg>list</arg>
<arg><replaceable>varname</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Возвращает значение переменной
<option><replaceable>varname</replaceable></option>
как список, если для этой переменной было много значений.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<cmdsynopsis>
<arg>exists</arg>
<arg><replaceable>varname</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Возвращает 1 если
<option><replaceable>varname</replaceable></option>
вам передана, и 0 если нет.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<cmdsynopsis>
<arg>number</arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Возвращает количество переменных.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<cmdsynopsis>
<arg>all</arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Возвращает список из имен переменных и их значений.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
См. так же <xref linkend="variable_access"/>.
</para>
</refsect1>
</refentry>
<refentry>
<refnamediv>
<refname>upload</refname>
<refpurpose>предназначена для обработки закачанных (uploaded)
файлов.</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>upload</command>
<group choice="req">
<arg>channel</arg>
<arg>save</arg>
<arg>data</arg>
<arg>exists</arg>
<arg>size</arg>
<arg>type</arg>
<arg>filename</arg>
</group>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Описание</title>
<para> Команда upload предназначена для обработки закачанных (uploaded)
файлов. Обратите внимание что поведение этой команды зависит от конфигурации Apache и Rivet.
</para>
<variablelist>
<varlistentry>
<term>
<cmdsynopsis>
<arg>channel</arg>
<arg><replaceable>uploadname</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Если передано имя закачанного файла, то
<option><replaceable>uploadname</replaceable></option>,
возвращает Tcl handle (как open (?)) для обращения
к этому файлу.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<cmdsynopsis>
<arg>save</arg>
<arg><replaceable>uploadname</replaceable></arg>
<arg><replaceable>filename</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Сохраняет
<option><replaceable>uploadname</replaceable></option> в
файле
<option><replaceable>filename</replaceable></option>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<cmdsynopsis>
<arg>data</arg>
<arg><replaceable>uploadname</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Возвращает данные загруженные на сервер. Должно
работать так же и с бинарными файлами.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<cmdsynopsis>
<arg>size</arg>
<arg><replaceable>uploadname</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Возвращает размер закачанного файла.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<cmdsynopsis>
<arg>type</arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Возвращает значение <varname>Content-type</varname>, если оно установлено,
или пустую строчку, если нет.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<cmdsynopsis>
<arg>filename</arg>
<arg><replaceable>uploadname</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Возвращает имя закачанного файла на клиентской машине.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<cmdsynopsis>
<arg>names</arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Возвращает список имен переменных для всех закачанных файлов
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
См. так же <xref linkend="upload"/>.
</para>
</refsect1>
</refentry>
<refentry>
<refnamediv>
<refname>load_response</refname>
<refpurpose>Сохряняет переданные данные в массиве.</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>load_response</command>
<arg><replaceable>arrayName</replaceable></arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Описание</title>
Сохраняет в массиве все переменные, переданные из формы
</refsect1>
</refentry>
<refentry>
<refnamediv>
<refname>load_env</refname>
<refpurpose>Загужает переменные окружения (environment).</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>load_env</command>
<arg choice="opt"><replaceable>array_name</replaceable></arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Описание</title>
<para>
Загружает в указанный массив переменные окружения. По умолчанию
делает это в массив <option>::request::env</option>
</para>
<para>
Так как страницы выполняются в пространстве имен
<option>::request</option>, то нет необходимости
обращатся к этому массиву по полному имени - вполне
можно ограничиться просто
<option>env</option> (примечание переводчика: щааааз!).
</para>
</refsect1>
</refentry>
<refentry>
<refnamediv>
<refname>load_headers</refname>
<refpurpose>Загружает заголовки (headers) из запроса (requestа).</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>load_headers</command>
<arg><replaceable>array_name</replaceable></arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Описание</title>
<para>
Загужает клиентские HTTP заголовки в указанный массив, или в
<option>headers</option> если имя массива не указано.
</para>
</refsect1>
</refentry>
<refentry>
<refnamediv>
<refname>load_cookies</refname>
<refpurpose>Загружает клиентские cookie.</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>load_cookies</command>
<arg choice="opt"><replaceable>array_name</replaceable></arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Описание</title>
</refsect1>
<para>
Загужает переданные клиентом Cookie в указанный массив, или в
<option>headers</option> если имя массива не указано.
</para>
</refentry>
<refentry>
<refnamediv>
<refname>include</refname>
<refpurpose> Считывает файл без всякой модификации.</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>include</command>
<arg><replaceable>filename_name</replaceable></arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Описание</title>
<para>
Подгружает файл без обратки тэгов
&lt;? и ?&gt;. Это лучший способ включить HTML файл
или другой статический контент.
</para>
</refsect1>
</refentry>
<refentry>
<refnamediv>
<refname>parse</refname>
<refpurpose>обрабатывает файл Rivetом.</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>parse</command>
<arg><replaceable>filename</replaceable></arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Описание</title>
<para>
Почти то же что и команда Tcl <command>source</command>, но только
с учетом тегов &lt;? и ?&gt;, используемых Rivetом. Этой командой можно
вызывать один .rvt файл из другого.
</para>
</refsect1>
</refentry>
<refentry>
<refnamediv>
<refname>headers</refname>
<refpurpose>установка и обработка заголовков HTTP.</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>headers</command>
<group choice="req">
<arg>set</arg>
<arg>redirect</arg>
<arg>add</arg>
<arg>type</arg>
<arg>numeric</arg>
</group>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Описание</title>
<para>
Команда <command>headers</command> предназначена для работы с заголовками http.
</para>
<variablelist>
<varlistentry>
<term><cmdsynopsis>
<arg>set</arg>
<arg><replaceable>headername</replaceable></arg>
<arg><replaceable>value</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Устанавливает разнообразные заголовки и значения.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<cmdsynopsis>
<arg>redirect</arg>
<arg><replaceable>uri</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Перенаправление (redirect) с текущей страницы на новый URI.
<emphasis>Обязана</emphasis> быть в самом начале кода.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<cmdsynopsis>
<arg>add</arg>
<arg><replaceable>headername</replaceable></arg>
<arg><replaceable>value</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>Добавляет текст в заголовок
<varname>headername</varname>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><cmdsynopsis>
<arg>type</arg>
<arg><replaceable>content-type</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>
Эта команда устанавливает HTTP заголовок
<constant>Content-type</constant> который возвращается
клиенту при обращении к странице. Это полезно если вы
отдаете содержимое отличное от text/html или
указываете кодировку.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<cmdsynopsis>
<arg>numeric</arg>
<arg><replaceable>response code</replaceable></arg>
</cmdsynopsis>
</term>
<listitem>
<para>Устанавливает код http-ответа, типа 200, 404 или 500.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
</refentry>
<refentry>
<refnamediv>
<refname>makeurl</refname>
<refpurpose>Формирует url'и основываясь на hostname, port.</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>makeurl</command>
<arg><replaceable>filename</replaceable></arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Описание</title>
<para>
Создает URL который ссылается сам на себя исходя из имени
файла. Например,
<programlisting>makeurl /tclp.gif</programlisting>
вернет
<computeroutput>http://[hostname]:[port]/tclp.gif</computeroutput>.
взяв информацию о hostname и порте из достоверного источника
</para>
</refsect1>
</refentry>
<refentry>
<refnamediv>
<refname>cookie</refname>
<refpurpose>работает с cookies.</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>cookie</command>
<arg>set</arg>
<arg><replaceable>cookieName</replaceable></arg>
<arg><replaceable><optional>cookiValue</optional></replaceable></arg>
<arg>-days <replaceable>expireInDays</replaceable></arg>
<arg>-hours <replaceable>expireInHours</replaceable></arg>
<arg>-minutes <replaceable>expireInMinutes</replaceable></arg>
<arg>-expires <replaceable>Wdy, DD-Mon-YYYY HH:MM:SS GMT</replaceable></arg>
<arg>-path <replaceable>uriPathCookieAppliesTo</replaceable></arg>
<arg>-secure <replaceable>1/0</replaceable></arg>
</cmdsynopsis>
<cmdsynopsis>
<command>cookie</command>
<arg>get</arg>
<arg><replaceable>cookieName</replaceable></arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Описание</title>
<para>
Эта команда преденазаначена для установки или
считывания переданных Cookies. Когда вам передают
cookie, эта команда вам передает значение, или же
пустую строку, если вам такую cookie не передали.
</para>
</refsect1>
</refentry>
<refentry>
<refnamediv>
<refname>clock_to_rfc850_gmt</refname>
<refpurpose>Возвращает время согласно rfc850 основываясь на [clock seconds].</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>clock_to_rfc850_gmt</command>
<arg><replaceable>seconds</replaceable></arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Описание</title>
<para>
Конвертирует unix-time (количество секунд с 1970 года) в
формат RFC850, который требует чтобы оно было GMT.
</para>
</refsect1>
</refentry>
<refentry>
<refnamediv>
<refname>html</refname>
<refpurpose>создает html выделения в тексте.</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>html</command>
<arg><replaceable>string</replaceable></arg>
<arg rep="repeat"><replaceable>arg</replaceable></arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Описание</title>
<para>
Выводит текст с возможностию передачи HTML тэгов, переданных
как аргументы. Пример:
<programlisting>html "Test" b i</programlisting>
produces: <computeroutput>&lt;b&gt;&lt;i&gt;Test&lt;/i&gt;&lt;/b&gt;</computeroutput>
</para>
</refsect1>
</refentry>
<refentry>
<refnamediv>
<refname>incr0</refname>
<refpurpose>увеличивает переменную на 1 или делает ее равной 1 если переменная не существовала.</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>incr0</command>
<arg><replaceable>varname</replaceable></arg>
<arg><replaceable>num</replaceable></arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Описание</title>
<para>
Прибавляет 1 к
<option><replaceable>varname</replaceable></option>
<option><replaceable>num</replaceable></option> раз.
Если такой переменной не существовало, то создает таковую
и присваивает ей 1, а не возвращает ошибку.
</para>
</refsect1>
</refentry>
<refentry>
<refnamediv>
<refname>parray</refname>
<refpurpose>команда Tcl's <command>parray</command> с html-форматированием.</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>parray</command>
<arg><replaceable>arrayName</replaceable></arg>
<arg><replaceable><optional>pattern</optional></replaceable></arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Описание</title>
<para>
Версия стандартной команды Tcl
<command>parray</command>. Делает то же самое, но с
красивым html оформлением.
</para>
</refsect1>
</refentry>
</section>
<section id="examples">
<title>Примеры использования</title>
<para>
Далее - примеры использования Rivet. Подразумевается что
читатель имеет некоторые знания Tcl. Если же вы его не знаете -
не волнуйтесь, это простой язык, и множество как минимум англоязычной
документации и учебников доступно в сети.
Посмотрите например <link
linkend="websites"> сюда </link>.
</para>
<example id="hello world">
<title>Hello World</title>
<para>
Естественно, первым примером будет "Hello World".
</para>
<para>
Мы предполагаем что к этому моменту Apache сконфигурирован и понимает
.rvt файлы, создадим файл
<filename>hello.rvt</filename> в месте где Apache сможет
его найдти со следующим содержимым:
</para>
<programlisting>&hello.rvt;</programlisting>
<para>
Если вы обратитесь к этому файлу через броузер, вы должны увидеть
практически чистую страницу с надписью "Helo World" (без кавычек).
</para>
</example>
<example id="table">
<title>Создание таблицы</title>
<para>
В следующем, тоже простом примере мы покажем как создать таблицы:
</para>
<programlisting>&table.rvt;</programlisting>
<para>
Если вы вчитаетесь в код, то убедитесь что это чистейший Tcl. Мы можем
запустить этот код и вне Rivet - и он будет генерировать такой же HTML!
</para>
<para>
Результат должен быть похож на:
</para>
<graphic fileref="table.png"/>
</example>
<example id="variable_access">
<title>Доступ к переменным</title>
<para>
А тут мы продемонстрируем как обращаться с переменными
переданными вам методом POST или GET.
</para>
<para>
Из такой HTML формы:
</para>
<programlisting>&vars.html;</programlisting>
<para>
Мы можем использовать rivet скрипт чтобы получить доступ к
этим переменным:
</para>
<programlisting>&vars.rvt;</programlisting>
<para>
Первый оператор проверяет что переменная
<varname>boss</varname> была переданна скрипту, и потом
что-то делает с этой информацией.
Если же такой нет - то в список ошибок добавляется сообщение
об этом прискорбном факте.
</para>
<para>
Во втором куске кода, переменная
<varname>salary</varname> обрабатывается примерно таким же
образом, и к тому же еще и проверяется на то является ли она
числом.
</para>
<para>
Если переменная <varname>boss</varname> не введена - то она
заменяется на "Mr. Burns".
</para>
<para>
А последний кусок кода немножко хитрее, потому что переменная
<varname>skills</varname> - это listbox, и в принципе
может иметь несколько значений, и тут мы покажем как с ними
поступать.
</para>
<para>
Скрипт далее проверяет что
<varname>errlist</varname> пустой (а если нет - то информирует
вас об ошибках) и говорит что спасибо и все такое.
</para>
</example>
<example id="upload">
<title>Закачка файлов (Upload)</title>
<para>
Пусть есть такой HTML код
<filename>upload.html</filename>
</para>
<programlisting>&upload.html;</programlisting>
<para>
Из такого Tcl кода, например,
(под названием <filename>upload.rvt</filename>)
мы получаем доступ к загруженному файлу.
</para>
<programlisting>&upload.rvt;</programlisting>
</example>
</section>
<section id="tcl_packages">
<title>Rivet Tcl packagы</title>
<para>
Кроме всего прочего, Rivet - это еще и набор полезных
packageй.
</para>
<itemizedlist>
<listitem>
<para>commserver - это package который может быть использован при
IPC. Страшно экспериментальный. Ему нужен comm из tcllib
</para>
</listitem>
<listitem>
<para>dio - абстрактный интерфейс работы с базами данных.</para>
</listitem>
<listitem>
<para>dtcl - модуль для обеспечения совместимости с mod_dtcl
</para>
</listitem>
<listitem>
<para>form - для создания forms.</para>
</listitem>
<listitem>
<para>rivet - еще куча полезных процедур.</para>
</listitem>
<listitem>
<para>tclrivet</para>
</listitem>
</itemizedlist>
</section>
<section id="help">
<title>Ресурсы и как получить помощь</title>
<section>
<title>Mailing Lists</title>
<para>
Mailing List (список рассылка) - это первейшее место куда
надо обращаться за помощью, если, конечно, вы не нашли ответа
в документации. Пишите на
<email>rivet-user@tcl.apache.org</email>. Если у вас
есть мысли, идеи, или просто соображения о Rivet и его коде, то
пишите на <email>rivet-dev@tcl.apache.org</email>.
Чтобы подписаться на оба листа, пишите email на
<email>rivet-<replaceable>list</replaceable>-subscribe@tcl.apache.org</email>.
</para>
<para>
Архивы списка рассылки доступны тут <ulink
url="http://nagoya.apache.org/eyebrowse/SummarizeList?listId=118"/>
</para>
</section>
<section>
<title>Новостная группа</title>
<para>
Новостная группа <ulink url="news:comp.lang.tcl"/> - это хорошее
место для вопросов по Tcl вообще. Но и разработчики Rivet туда
тоже заглядывают, можно и туда писать, но лучше в список рассылки.
</para>
</section>
<section id="websites">
<title>Веб сайты</title>
<para>
Есть некоторое количество полезных веб сайтов про Apache и Tcl.
</para>
<itemizedlist>
<listitem>
<para>
<ulink url="http://tcl.apache.org"/>
это домашняя страница проекта Apache Tcl. Сюда надо ходить за
свежими версиями софта.
</para>
</listitem>
<listitem>
<para>
<ulink url="http://httpd.apache.org/docs/"/>
по всем вопросам касающимся Apache
</para>
</listitem>
<listitem>
<para>
<ulink url="http://www.tcl.tk/"/>
классическое место где гнездится Tcl.
</para>
</listitem>
<listitem>
<para>
<ulink url="http://wiki.tcl.tk"/>
Tcl's Wiki, весьма полезный ресурс для задавания вопросов,
получения ответов и отвечания на них для тех кто крут.
</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>Система отлова ошибок</title>
<para>
Apache Rivet использует ВсеАпачную Систему Отлова Ошибок (ВАСОО) <ulink
url="http://nagoya.apache.org/bugzilla/"></ulink>.
Всякие проблемы пишите сюда, или - что тоже полезно - вы можете
выяснить опыт ее решения, если кто-то уже с ней сталкивался.
</para>
</section>
<section>
<title>IRC</title>
<para>
Иногда случается что кто-то из команды Rivet доступен по IRC
на irc.freenode.net, канал #tcl.
</para>
</section>
<section>
<title>Редактирование Rivet файлов</title>
<para>
Для двух популярных редакторов
<application>emacs</application> и
<application>vim</application> есть код для удобного редактирования
файлов Rivet. Идея в том что редактор, завидев теги
&lt;? and ?&gt; переключается то в режим HTML, то в Tcl.
Эти файлы
<filename>two-mode-mode.el</filename> и
<filename>rvt.vim</filename> находятся в директории
<filename>contrib/</filename>.
</para>
</section>
</section>
<section id="internals">
<title>Внутренности Rivet</title>
<para>
Эта секция давно устарела, поскольку новый код добавляется, а
старый убирается. Так что лучше читайте исходники - они рулез!.
А если вам интересны изменения, то пользуйтесь <command>cvs</command>
</para>
<section>
<title>Инициализация</title>
<para>
Когда apavhe запускается (или когда запускается использующий TCL
дочерний процесс Apache если Tcl собран с поддержкой threads), вызывается
<function>Rivet_InitTclStuff</function>,
который создает новый интерпретатор, по одному на каждый
виртуальный хост, в зависимости от конфигурации. Также инициализируются
всякие вещи типа
<structname>RivetChan</structname> канальная система (channel system),
создаются специфичные для Rivet Tcl команды и исполняется Rivetовский
channel system, creates the Rivet-specific Tcl commands, and
<filename>init.tcl</filename>. Система кеширования, опять же, и если
есть
<command>GlobalInitScript</command>, то и он запускается.
</para>
</section>
<section>
<title>RivetChan</title>
<para>
Система <structname>RivetChan</structname> была создана для того чтобы
перенаправлять стандартный поток вывода (stdout). По этой причине вы можете
использовать стандартную команду
<command>puts</command> в страницах .rvt.
(примечание переводчика: и <command>fconfigure</command> тоже, что полезно).
Она также создает канал который буферизует output, и перенаправляет его в
систему ввода-вывода Apache.
</para>
</section>
<section>
<title>Команда <command>global</command></title>
<para>
Rivet сделан так, что должен запускать Tcl код с минимальным
количеством неожиданностей, Но иногда приходится идти на
компромиссы - в этом случае вам и пригодится команда
<command>global</command>. Проблема в том что эта команда создаст
вам действительно глобальную переменную, и если пользователь
просто задействует старый код без изменений, скорее всего
он захочет получить доступ к переменным из других програм, не
желая заботиться проверкой того как передается эта переменная
из страницы в страницу. По этому поводу мы и создали процедурку
<command>::request::global</command> которая и выполняет
роль команды <command>global</command> в Rivet страницах. Если
вам на самом деле нужны настоящие глобальные переменные, используйте
команду
<command>::global</command> или добавьте :: namespace
к переменным которые вы хотите сделать глобальными
</para>
</section>
<section>
<title>Обработка страниц, выполнение и кеширование</title>
<para>
Когда выполняется Rivet страница, она превращается в обычный Tcl
скрипт, опираясь на символы &lt;? ?&gt;. Все что вне их
рассматривается как большой большой аргумент для
<command>puts</command>, а все что внутри - рассматривается
как Tcl код.
</para>
<para>
Каждый .rvt файл выполняется в простанстве имен
<constant>::request</constant>, по этому нет необходимости
каждый раз создавать по новому интерпретатору. По этой же
причине глобальные переменные
(примечание преводчика: звиняйте, не понял)
By running in its own namespace, though, each page will
not run afoul of local variables created by other scripts,
because they will be deleted automatically when the namespace
goes away after Apache finishes handling the request.
</para>
<note>
Одна из существующих ныне проблем подобного подхода - это отсутсвие
механизма сборщика мусора, например, если вы не закрыли
хэндл файла - то это плохо. Поэтому будьте добры, закрывайте все
что наоткрывали.
</note>
<para>
После того как скрипт загружен и преобразован в "чистый Tcl",
он опять же кешируется, и по этой причине может быть использован
в следующий раз без лишних преобразований и обращений к диску.
Количество кешируемых скриптов можно изменить в конфиге.
Таким образом можно значительно поднять производительность системы.
</para>
</section>
</section>
<section id="upgrading">
<title>Переход с mod_dtcl или NeoWebScript (NWS)</title>
<para>
Обратная совместимость не была никогда особой целью разработчиков,
но мы ее все равно предоставляем по историческим причинам и
с учетом пожеланий тех кто переключается на Rivet с mod_dtcl и NeoWebScript (NWS).
</para>
<section>
<title>mod_dtcl</title>
<para>
Rivet базируется на коде mod_dtcl, но достаточно хорошо переработан. Основная
идея осталась та же, но большое количетво команд изменилось.
</para>
</section>
<section>
<title>NeoWebScript</title>
<para>Потом.</para>
</section>
</section>
</article>