Russian Translation: Dmitry the Zuryanovich
Copyright © 2002, 2003 Apache Software Foundation
Содержание
Этот документ в переводах на другие языки: English, Italian
This document is based on version 1.34 of the original English version.
Apache Rivet - это система для генерации динамических веб страниц, встроенная модулем в http сервер Apache. Она задумывалась как система быстрая, мощная, расширяемая и достаточно простая для внедрения. Стоит заметить что с Apache Rivet вы получаете надежную платформу которая не только может интегрироваться в web, но и может быть использована вне его. GUI, инструментарий администратора, XML, манипуляции с БД, консольные приложения могут использовать тот же код, который используется при разработках web-приложений. Это достигается применением языка TCL - вне и внутри Apache сервера.
В этом документе мы постараемся помочь вам быстро разобраться как можно создавать web- приложения, и показать вам дальнейшие пути для разработки приложений используя rivet для самых разнообразных применений.
Эта документация - как и весь rivet, и тем более ее перевод на русский - это работа, которая не заврешена, и будем надеяться будет продолжаться еще очень долго. Если вы видите что что-то где-то почему-то не так - то пишите об этом, мы сами за всем не углядим без вашей помощи. Это Свободное программное обеспечение!
Check Dependencies/Проверка связей между программным обеспечением
Для того чтобы установить rivet, вам в первую очередь понадобится сам Tcl, версии 8.4 или выше и веб сервер Apache версий 1.3.x. Известно что все должно работать на Linux, FreeBSD,OpenBSD, Solaris и HPUX. Возможно что можно заставить работать даже на Windows NT - в дистрибутиве написано как это делать.
Скачайте себе Rivet
Возьмите исходники отсюда http://tcl.apache.org/rivet/download. На данный момент это единственный способ получить rivet. Возможно в дальнейшем появится FreeBSD port, Debian package, RPM и бинарники под Windows.
Скачайте и соберите Apache
Rivety нужны заголовки (.h) от Apache. Самый простой способ - это скачать исходники Apache, хотя во многих системах (Debian, например) позволяют поставить отдельно заголовки и прочие вещи, необходимые для разработчиков. Если вы хотите собрать rivet в статике (вместо того чтобы грузить его как .so), то вам придется скачать все исходники apache отсюда http://httpd.apache.org/. Мы рекомендуем собирать rivet как динамическую библиотеку (shared object), и соответственно собирать его отдельно от Apache.
Исходный код apache берут тут:http://httpd.apache.org/
Разархивация исходников
Сейчас мы будем считать что apache вами был каким-то образом установлен. Теперь вы должны разархивировать исходники rivet там где вы хотите их собирать.
gunzip tcl-rivet-X.X.X.tar.gz tar -xvf tcl-rivet-X.X.X.tar.gz
Компиляция Rivet
Rivet использует некую свою уникальную систему компиляции которую мы специально придумали именно для него. Она использует информацию из инсталяций Apache (через apxs)и Tcl, для того чтобы собрать rivet через набор Tcl скриптов, которые находятся buildscripts/ тут.
Запустите ./configure.tcl
По смыслу это практчески то же что и configure, скрипт который встречается в большинстве систем. Он, конечно же, написан на Tcl. У него есть несколько полезных аргументов:
cd src/ ./configure.tcl Configuring .........done.
Запустите make.tcl
Сейчас нужно скомпилировать Rivet:
./make.tcl option
где option может быть shared или static.
Установка
Сейчас самое время запустить ./make.tcl install чтобы все установить. Эта команда должна скопировать получившийся .so файл (типа mod_rivet.so), если он конечно скомпилируется, в директорию Apache libexec, а так же установит некоторое количество полезных скриптов и прочего кода.
Конфигурация Apache
Конфигурировать Rivet достаточно просто - начнем с того что добавим сам модуль:
LoadModule rivet_module /usr/lib/apache/1.3/mod_rivet.so
После этого Apache должен знать что ему надо загрузить Rivet как shared object, чтобы иметь возможность его использовать. Далее мы должны объяснить Apache какие файлы надо обрабатывать Rivetом и как это делать:
AddType application/x-httpd-rivet .rvt AddType application/x-rivet-tcl .tcl
Эти директивы объяснят Apache что файлы с расширением .rvt и .tcl надо обрабатывать Rivetом.
Все остальные директивы описаны тут «Конфигурационные параметры Rivet Apache».
Это - разнообразный набор установок которые могут быть сделаны в конфигурационнном файле Apache с целью изменения поведения Rivet. Их формат такой: RivetDirConf, RivetUserConf, RivetServerConf, что означает что DirConf имеет более высокий приоритет и перебивает установки в UserConf, что в свою очередь перебивает ServerConf.
RivetServerConf GlobalInitScript "source /var/www/foobar.tcl"
![]() | Замечание |
---|---|
Этот код исполняется на глобальном уровне, а не в том namespace в котором исполняются страницы |
Команда var предназначена для доступа к переменным которые были переданы методами GET или POST, не делая между ними никакой разницы. Стоит заметить что есть еще две формы команды var: var_qs и var_post. Эти команды рассматривают только переменные переданные GETом и POSTом, соответственно.
См. так же Пример 3, «Доступ к переменным».
Команда upload предназначена для обработки закачанных (uploaded) файлов. Обратите внимание что поведение этой команды зависит от конфигурации Apache и Rivet.
См. так же Пример 4, «Закачка файлов (Upload)».
Загружает в указанный массив переменные окружения. По умолчанию делает это в массив ::request::env
Так как страницы выполняются в пространстве имен ::request, то нет необходимости обращатся к этому массиву по полному имени - вполне можно ограничиться просто env (примечание переводчика: щааааз!).
Загужает клиентские HTTP заголовки в указанный массив, или в headers если имя массива не указано.
Загужает переданные клиентом Cookie в указанный массив, или в headers если имя массива не указано.
Подгружает файл без обратки тэгов <? и ?>. Это лучший способ включить HTML файл или другой статический контент.
Почти то же что и команда Tcl source, но только с учетом тегов <? и ?>, используемых Rivetом. Этой командой можно вызывать один .rvt файл из другого.
Команда headers предназначена для работы с заголовками http.
Создает URL который ссылается сам на себя исходя из имени файла. Например,
makeurl /tclp.gif
вернет http://[hostname]:[port]/tclp.gif. взяв информацию о hostname и порте из достоверного источника
Эта команда преденазаначена для установки или считывания переданных Cookies. Когда вам передают cookie, эта команда вам передает значение, или же пустую строку, если вам такую cookie не передали.
Конвертирует unix-time (количество секунд с 1970 года) в формат RFC850, который требует чтобы оно было GMT.
Выводит текст с возможностию передачи HTML тэгов, переданных как аргументы. Пример:
html "Test" b i
produces: <b><i>Test</i></b>
Далее - примеры использования Rivet. Подразумевается что читатель имеет некоторые знания Tcl. Если же вы его не знаете - не волнуйтесь, это простой язык, и множество как минимум англоязычной документации и учебников доступно в сети. Посмотрите например сюда .
Пример 1. Hello World
Естественно, первым примером будет "Hello World".
Мы предполагаем что к этому моменту Apache сконфигурирован и понимает .rvt файлы, создадим файл hello.rvt в месте где Apache сможет его найдти со следующим содержимым:
<? puts "Hello World" ?>
Если вы обратитесь к этому файлу через броузер, вы должны увидеть практически чистую страницу с надписью "Helo World" (без кавычек).
Пример 2. Создание таблицы
В следующем, тоже простом примере мы покажем как создать таблицы:
<? puts "<table>\n" for {set i 1} { $i <= 8 } {incr i} { puts "<tr>\n" for {set j 1} {$j <= 8} {incr j} { set num [ expr $i * $j * 4 - 1] puts [ format "<td bgcolor=\"%02x%02x%02x\" > $num $num $num </td>\n" \ $num $num $num ] } puts "</tr>\n" } puts "</table>\n" ?>
Если вы вчитаетесь в код, то убедитесь что это чистейший Tcl. Мы можем запустить этот код и вне Rivet - и он будет генерировать такой же HTML!
Результат должен быть похож на:
Пример 3. Доступ к переменным
А тут мы продемонстрируем как обращаться с переменными переданными вам методом POST или GET.
Из такой HTML формы:
<form action="vars.rvt"> <table> <tbody> <tr> <td><b>Title:</b></td> <td><input name="title"></td> </tr> <tr> <td><b>Salary:</b></td> <td><input name="salary"></td> </tr> <tr> <td><b>Boss:</b></td> <td><input name="boss"></td></tr> <tr> <td><b>Skills:</b></td> <td> <select name="skills" multiple="multiple"> <option>c</option> <option>java</option> <option>Tcl</option> <option>Perl</option> </select> </td> </tr> <tr> <td><input type="submit"></td> </tr> </tbody> </table> </form>
Мы можем использовать rivet скрипт чтобы получить доступ к этим переменным:
<? set errlist {} if { [var exists title] } { set title [var get title] } else { set errlist "You need to enter a title" } if { [var exists salary] } { set salary [var get salary] if { ! [string is digit $salary] } { lappend errlist "Salary must be a number" } } else { lappend errlist "You need to enter a salary" } if { [var exists boss] } { set boss [var get boss] } else { set boss "Mr. Burns" } if { [var exists skills] } { set skills [var list skills] } else { lappend errlist "You need to enter some skills" } if { [llength $errlist] != 0 } { foreach err $errlist { puts "<b> $err </b>" } } else { puts "Thanks for the information!" ?> <table> <tbody> <tr> <td><b>Title:</b></td> <td><? puts $title ?></td> </tr> <tr> <td><b>Boss:</b></td> <td><? puts $boss ?></td> </tr> <tr> <td><b>Salary:</b></td> <td><? puts $salary ?></td> </tr> <tr> <td><b>Skills:</b></td> <td><? puts $skills ?></td> </tr> </tbody> </table> <? } ?>
Первый оператор проверяет что переменная boss была переданна скрипту, и потом что-то делает с этой информацией. Если же такой нет - то в список ошибок добавляется сообщение об этом прискорбном факте.
Во втором куске кода, переменная salary обрабатывается примерно таким же образом, и к тому же еще и проверяется на то является ли она числом.
Если переменная boss не введена - то она заменяется на "Mr. Burns".
А последний кусок кода немножко хитрее, потому что переменная skills - это listbox, и в принципе может иметь несколько значений, и тут мы покажем как с ними поступать.
Скрипт далее проверяет что errlist пустой (а если нет - то информирует вас об ошибках) и говорит что спасибо и все такое.
Пример 4. Закачка файлов (Upload)
Пусть есть такой HTML код upload.html
<form action="foo.rvt" enctype="multipart/form-data" method="post"> <input type="file" name="MyUpload"></input> <input type="submit" value="Send File"></input> </form>
Из такого Tcl кода, например, (под названием upload.rvt) мы получаем доступ к загруженному файлу.
<? upload save MyUpload /tmp/uploadfiles/file1 puts "Saved file [upload filename MyUpload] \ ([upload size MyUpload] bytes) to server" ?>
Кроме всего прочего, Rivet - это еще и набор полезных packageй.
Mailing List (список рассылка) - это первейшее место куда надо обращаться за помощью, если, конечно, вы не нашли ответа в документации. Пишите на <rivet-user@tcl.apache.org>. Если у вас есть мысли, идеи, или просто соображения о Rivet и его коде, то пишите на <rivet-dev@tcl.apache.org>. Чтобы подписаться на оба листа, пишите email на <rivet-list-subscribe@tcl.apache.org>.
Архивы списка рассылки доступны тут http://nagoya.apache.org/eyebrowse/SummarizeList?listId=118
Новостная группа news:comp.lang.tcl - это хорошее место для вопросов по Tcl вообще. Но и разработчики Rivet туда тоже заглядывают, можно и туда писать, но лучше в список рассылки.
Есть некоторое количество полезных веб сайтов про Apache и Tcl.
Apache Rivet использует ВсеАпачную Систему Отлова Ошибок (ВАСОО) http://nagoya.apache.org/bugzilla/. Всякие проблемы пишите сюда, или - что тоже полезно - вы можете выяснить опыт ее решения, если кто-то уже с ней сталкивался.
Эта секция давно устарела, поскольку новый код добавляется, а старый убирается. Так что лучше читайте исходники - они рулез!. А если вам интересны изменения, то пользуйтесь cvs
Когда apavhe запускается (или когда запускается использующий TCL дочерний процесс Apache если Tcl собран с поддержкой threads), вызывается Rivet_InitTclStuff, который создает новый интерпретатор, по одному на каждый виртуальный хост, в зависимости от конфигурации. Также инициализируются всякие вещи типа RivetChan канальная система (channel system), создаются специфичные для Rivet Tcl команды и исполняется Rivetовский channel system, creates the Rivet-specific Tcl commands, and init.tcl. Система кеширования, опять же, и если есть GlobalInitScript, то и он запускается.
Система RivetChan была создана для того чтобы перенаправлять стандартный поток вывода (stdout). По этой причине вы можете использовать стандартную команду puts в страницах .rvt. (примечание переводчика: и fconfigure тоже, что полезно). Она также создает канал который буферизует output, и перенаправляет его в систему ввода-вывода Apache.
Rivet сделан так, что должен запускать Tcl код с минимальным количеством неожиданностей, Но иногда приходится идти на компромиссы - в этом случае вам и пригодится команда global. Проблема в том что эта команда создаст вам действительно глобальную переменную, и если пользователь просто задействует старый код без изменений, скорее всего он захочет получить доступ к переменным из других програм, не желая заботиться проверкой того как передается эта переменная из страницы в страницу. По этому поводу мы и создали процедурку ::request::global которая и выполняет роль команды global в Rivet страницах. Если вам на самом деле нужны настоящие глобальные переменные, используйте команду ::global или добавьте :: namespace к переменным которые вы хотите сделать глобальными
Когда выполняется Rivet страница, она превращается в обычный Tcl скрипт, опираясь на символы <? ?>. Все что вне их рассматривается как большой большой аргумент для puts, а все что внутри - рассматривается как Tcl код.
Каждый .rvt файл выполняется в простанстве имен ::request, по этому нет необходимости каждый раз создавать по новому интерпретатору. По этой же причине глобальные переменные (примечание преводчика: звиняйте, не понял) 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.
![]() | Замечание |
---|---|
Одна из существующих ныне проблем подобного подхода - это отсутсвие механизма сборщика мусора, например, если вы не закрыли хэндл файла - то это плохо. Поэтому будьте добры, закрывайте все что наоткрывали. |
После того как скрипт загружен и преобразован в "чистый Tcl", он опять же кешируется, и по этой причине может быть использован в следующий раз без лишних преобразований и обращений к диску. Количество кешируемых скриптов можно изменить в конфиге. Таким образом можно значительно поднять производительность системы.
Обратная совместимость не была никогда особой целью разработчиков, но мы ее все равно предоставляем по историческим причинам и с учетом пожеланий тех кто переключается на Rivet с mod_dtcl и NeoWebScript (NWS).
Rivet базируется на коде mod_dtcl, но достаточно хорошо переработан. Основная идея осталась та же, но большое количетво команд изменилось.