![]() | новости статьи | ||
.программирование | |||
первый сайт на Perl 6 В апреле 2004 года я создал пятистраничный сайт http://real.perl6.ru, который работал под управлением Perl 6. Сегодня особенно интересно заметить, что на сервере выполнялся байт-код, в который был предварительно скомпилирован исходный код скриптов на Perl 6. Иными словами, одна из основных идей — иметь возможность компилировать код — была успешно применена, и позволила сделать быстро работающий мини-сайт, хотя в то время сам по себе компилятор работал довольно медленно. Но даже и при быстром компиляторе идея выполнять байт-код вместо интерпретации исходного кода всегда разумна. Все, что описано в этой статье, преследует лишь исторический интерес (хотя сайт по-прежнему работает). Большинство показанного здесь кода на Perl 6 сегодня окажется синтаксически некорректным, поскольку многие конструкции языка уже изменились. О том, как писать веб-приложения, пользуясь компилятором, поддерживающим современное состояние Perl 6, рассказано в следующей статье в этом номере журнала. исполнение байт-кода Сервер настроен таким образом, что индексным файлом в каталогах является файл main.pbc. Байт код, хранящийся в файлах с расширением .pbc (Parrot Byte-code), исполняется виртуальной машиной Parrot (до сих пор работает машина версии 0.1.0, вышедшая в феврале 2004 года — в ее составе был первый компилятор Perl 6, место которого сейчас занимает Rakudo). Сам же Parrot запускался через крошечное CGI-приложение, написанное на C: int main () { char* argv[] = {"parrot", getenv ("PATH_TRANSLATED"), NULL}; execvp ("/parrot-0.1.0/parrot", argv); return 0; } чтение переменных окружения Это крайне простая и полезная операция, использующая значения, полученные в хеше %ENV, работает почти так же, как и в Perl 5. Основное отличие в том, что при обращении к элементу хеша нужно использовать сигил %, а не $: my @keys = ( 'SERVER_NAME', 'REMOTE_ADDR', 'HTTP_USER_AGENT' ); my $key; foreach $key (@keys){ print "$key=%ENV{$key}<br />\n"; } Демонстрация работы этого кода доступна на странице http://real.perl6.ru/p6/environment/. Здесь печатаются значения нескольких переменных окружения, которые перечислены в списке @keys. Вывод выглядит, примерно так: SERVER_NAME real.perl6.ru REMOTE_HOST REMOTE_ADDR 81.211.3.86 HTTP_USER_AGENT Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.2.149.27 Safari/525.13 SERVER_PROTOCOL HTTP/1.1 Как нетрудно заметить, зайдя на страницу разными браузерами или с разных компьютеров, строки, содержащие IP-адрес и версию браузера, формируется динамечески, а не извлекается из исходного кода приложения. разбор строки запроса Разбор переданных странице параметров — еще одна задача, которая обязательно присутствует в коде любого веб-проекта. Задача может быть сформулирована крайне просто: разбить строку на пары ключ=значение, разделенные символом амперсанда (экранирование символов для простоты не учитывается). Это легко осуществить с помощью регулярных выражений, однако в то время они не поддерживались в достаточной степени, поэтому функция чтения параметров выглядела так: sub read_params ($query, @params_key, @params_value){ my $pos = 0; loop (my $c = 0; 1; $c++) { my $newpos = index ($query, '&', $pos); my @keyvalue; my $pair = substr ($query, $pos, $newpos == -1 ?? length ($query) :: $newpos - $pos); split_pair ($pair, @keyvalue); @params_key[$c] = @keyvalue[0]; @params_value[$c] = @keyvalue[1]; last if $newpos == -1; $pos = $newpos + 1; } } Здесь стоит обратить на четыре особенности. Самое интересное в коде этой функции — она принимает параметры, причем два из них — массивы. Во-вторых, для создания C-подобного цикла используется ключевое слово loop. В-третьих, тернарный оператор имеет вид ?? ::. Он не был таким в Perl 5, но и в сегодняшнем Perl 6 выглядит по-иному (?? !!). И наконец, аналогично доступу к элементу хеша, упомянутому ранее, при обращении к элементу массива не нужно изменять сигил @: @params_key[$c] = @keyvalue[0]; Для каждой найденной пары функция read_params() вызывает функцию split_pair(), которая выделяет из строки ключ и его значение: sub split_pair ($pair, @keyvalue){ my $pos = index ($pair, '='); if ($pos == -1){ @keyvalue[0] = $pair; @keyvalue[1] = ''; } else{ @keyvalue[0] = substr ($pair, 0, $pos); @keyvalue[1] = substr ($pair, $pos + 1); } } Итоговый же вызов выглядит так: my @params_key; my @params_value; read_params (%ENV{'QUERY_STRING'}, @params_key, @params_value); После этого ключи и значения оказываются в двух отдельных массивах @params_key и @params_value. Для удобства их целесообразно объединить в один хеш: sub params2hash (%params, @params_key, @params_value){ for 0 .. @params_key -> $c { %params{@params_key[$c]} = @params_value[$c]; } } Здесь встречается новая конструкция Perl 6 для создания циклов. Помимо того, что скобки для списка, переданного оператору for, необязательны, переменная цикла объявлена после стрелки ->, что делает всю запись выразительнее. Кстати, весьма необычно с точки зрения Perl 6 выглядит вызов этой функции: в аргументах передаются и хеш, и списки: my %params; params2hash (%params, @params_key, @params_value); Посмотреть работу программы можно по адресу http://real.perl6.ru/p6/querystring/ (версия без хеша) или http://real.perl6.ru/p6/queryhash/ (с хешом). Чтобы убедиться в работоспособности, достаточно дописать в адресную строку любое число параметров, в том числе с повторяющимися ключами. Например: http://real.perl6.ru/p6/querystring/?one=alpha&two=beta&three=gamma∅&four=delta работа с куками Программа, работающая по адресу http://real.perl6.ru/p6/cookie/, делает попытку установить куки, а затем читает их. При второй загрузке этой страницы должно отобразиться установленное содержимое: cookie-name=test-value. Программа на Perl 6 представляет собой обычный CGI-скрипт (независимо от того, что выполняется совсем не Perl 6, а байт-код), поэтому куки устанавливаются обычным способом в заголовке HTTP-ответа: print "Content-Type: text/html\n" print "Set-Cookie: cookie-name=test-value; path=/;\n\n"; Куки, переданные браузером обратно на сервер, доступны в переменной окружения HTTP_COOKIE: print %ENV{'HTTP_COOKIE'}; счетчик посещений Разумеется, на сайт хотелось поставить и счетчик посещений. В то время в реализации Perl 6 не было механизмов работы с файлами, поэтому счетчик написан как отдельная подпрограмма на ассемблере Parrot. Чтобы поставить счетчик на страницу, нужно было сначала скомпилировать исходный код на Perl 6, получить промежуточный файл в формате IMC (прототип современного PIR), и вставить туда строку, подключающую imc-файл счетчика: .include "counter.imc" Сам же основной код счетчика выглядит так: open P0, "counter.txt" readline S0, P0 set I0, S0 inc I0 set I2, 0 seek P0, I2, I2 print P0, I0 close P0 в заключение Не стоит удивляться тому, что некоторые показанные здесь решения выглядят странными и нелогичными. Многие привычные конструкции просто невозможно применить из-за неполной реализации языка на момент создания этого первого сайта. Андрей Шитов, andy@shitov.ru обсудить статью | |||
© сетевые решения | |||
.
| .
| |