Часто задаваемые вопросы, собранные в конференции RU.CGI.PERL.CHAINIK
Что такое CGI? Это общий интерфейс шлюзов, связывающий программу,
работющую под управлением вебсервера и клиента в виде HTTP-браузера.
Иными словами, это средство, которое позволяет генерить HTML-документы
"на лету", в зависимости от условий и пожеланий программиста.
Как и любое клиент-серверное средство, CGI-программа состоит из
двух частей - одной, которая работает на клиенте, в среде браузера, и
другой, работающей на сервере, в среде вебсервера. Клиентская часть
пишется на HTML (возможно, с употреблением раздичных дополнительных
средств, расширяющих его возможности), серверная часть может быть на-
писана на любом языке программирования, способном создавать выполняе-
мые программы на платформе, на которой установлен вебсервер. Мы будем
использовать для этих целей Перл, потому что он удобен для обработки
текстовых строк - а HTML документ представляет собой именно текст.
Принцип работы интерфейса очень прост - вебсервер, если ему это
разрешено, может запустить выполняемую программу; в отличие от запуска
этой же программы пользователем потоки вода, вывода и ошибок запущен-
ной программы будут перенаправлены: ввода и вывода в протокол HTTP, а
ошибок - в файл лога ошибок вебсервера. Таким образом, мы можем созда-
вать HTML-документ "на лету", просто выводя в поток вывода его теги с
помощию команды print или ее аналога.
Впрочем, лучше один раз увидеть, чем сто раз услышать. Для того,
чтобы работать с клиент-серверными пограммами, нужно сначала устано-
вить клиент и сервер. В качестве клиента может быть использован любой
браузер, поддерживающий протокол HTTP (рекомендуется Netscape, потому
что он достаточно строго реагирует на ошибки; можно быть увереным, что
то, что работает в нем будет работать где угодно - а обратное выполня-
ется редко), в качестве сервера рекомендуется вебсервер Apache. Это
один из самых распространенных вебсерверов, он может быть скомпилиро-
ван полд все мыслимые платформы и ситемы, и отладженные под него прог-
раммы скорее всего сможет установить любой провайдер.
Вебсервер Apache для Windows лучше всего получить по адресу ftp://cdl.bmstu.ru/soft/cgi . Установите его, однако не в директорию,
которую он предлагает для установки, а в c:apache . Вебсервер может
работать и в том случае, если он установлен в руть по-умолчанию, одна-
ко при его настройке возникнут некоторые разночтения с предлагаемым
здесь вариантом - если Вы хотите избегнуть нежелательных осложнений,
измените путь по-умолчанию.
Запустите вебсервер (на экране появится пустое черное окно - это
нормальный результат успешного запуска; ни в коем случае не закрывайте
это окно принудительно - для финиширования вебсервер создал Вам специ-
альную иконку). Обратитесь к нему из браузера через URL http://localhost и убедитесь, что демонстрационная веб-страница, кото-
рая находится в директори htdocs успешно запускается.
Если вебсервер не удалось запустить, прочитайте выводимое им со-
общение об ошибке. Чаще всего вебсервер не может запуститься из-за то-
го, что не указано имя. Откройте на редактирование основной файл кон-
фигурации вебсервера (httpd.conf) и снимите ремарку с пересенной
Servername, присвоив серверу любое имя - например localhost.
Теперь имеет смысл попробовать выполнить первую CGI-программу.
Для того, чтобы иметь возможность писать CGI-программы на Перле,
следует установить Перл. Взять его можно там же, где и вебсервер, ус-
тановка этой программы не содержит особых подводных камней. Вам будет
предложено скомпиллировать Перл из текста на Си, если Вы откажетесь от
этого (что рекомендуется), будет развернута уже скомпилированная би-
нарная версия. После установки не забудьте проложить в файле
Autoexec.bat путь в директорию c:perlbin - туда, где содержится файл
perl.exe.
Проверьте правильность установки Перла, написав простейшую прог-
рамму, состоящую из одной строки:
print "Hello";
Запустите эту программу из любой директории, набрав "perl
filename", где filename - имя файла, в который Вы вписали приведенную
выше строчку. Если на экране появилось слово Hello, это ззначит что Вы
все сделали правильно.
В отличие от многих других вебсерверов, Апач сам вызывет интерп-
ретатор Перла, таким образом в каждой программе нужно указывать, где
он находиться. Таким образом, первой строчкой нашего CGI-скрипта дол-
жен быть путь к интерпретатору:
#!perl
после того, как путь к интерпретатору указан, нужно выставить
серверный http-заголовок, указывающий тип отдаваемых данных:
print "Content-type: text/htmlnn";
Обратите внимание, что поле http-заголовков завершается двойным
переводом строки. Сами заголовки, если их несколько, отделяются друг
от друга одинарным переводом строки.
Третья строчка нашей программы будет содержать необходимую для
создания html-документов обвеску:
Обратите внимание, что при использовании внутри команды print,
двойные кавычки необходимо отчеркивать - иначе интерпретатор примет
кавычки за окончание команды, а то, чт о идет после них - за незавер-
шенную строку, и ответит ошибкой выполнения.
Теперь необходимо вести строчку вывода, и закрыть html-докумнт.
print "Hello";
print "</body></html>";
Таким образом, вся наша первая программа будет выглядеть так:
Проверьте правильность ее выполнения, запустив программу локаль-
но. Для этого наберите в командной строке: perl filename, где filename
- это имя Вашей программы. Если все в порядке, программа должна напи-
сать на экране http-заголовок, а затем теги html-документа, который
программа создает.
После локальной проверки нужно запустить программу как кли-
ент-серверное приложение. Для этого нужно дать программе права на вы-
полнение (для операционых систем, где это актуально), и расположить в
директории, в которой вебсервер распознает програмы как CGI-приложе-
ния. По умолчанию, это директория cgi-bin, в которой и надо разместить
нашу программу.
Для запуска программы нужно набрать в окне location ее URL: http://localhost/cgi-bin/filename
Как передавать данные между клиентом и сервером?
Как передать данные с сервера на клиент мы уже рассмотрели. Сле-
дующим шагом представляется передача данных с клиента на сервер и фор-
мирование клиента с учетом переданной на сервер информации.
Существуют несколько МЕТОДОВ, с помощью которых можно передать
информацию на сервер; самые распространенные из них - это метод GET,
передающий данные в URL и метод POST, передающий данные в теле запро-
са. Недостатком первого является ограниченный объем передоваемой ин-
формации (до 127 байт), недостатком виторого - сложность в формирова-
нии запроса.
В самом деле, чтобы сформировать запрос методом GET вполне доста-
точно написать знак вопроса после URL вызова, и перечислять через ам-
персанд пары "имя=значение": http://localhost/cgi-bin/test2.cgi?v1=vasya&v2=petya и так далее.
Теперь нужно получить эти данные на сервере, для чего достаточно полу-
чить содержимое переменной окружения вебсервера QWERY-STRING. Эта пе-
ременная содержит то, что в URL располагалось после знака вопроса.
Есть, однако, одна особенность, которая делает затруднительной
использование этой переменнй. Дело в том, что русские буквы, как и
специальные символы, в URL заперщены - поэтому их придется заменить на
специальный код, который не содержит запретных символов, а просле при-
ема на сервере потребуется произвести обратную перекодировку. Такая
перекодировка является вполне стандартной для CGI-программирования, и
в комплекте любого Перла предусмотрен модуль, который умеет читать со-
ответствующую переменую, перекодировать ее содержимое и раскладывать
приняные данные по переменным. Модуль, в котором содержася эти подп-
рограммы называется CGI. Подключите его к своей программе, написав:
use CGI qw(param);
после чего Вы сможете захватывать из входного потока любую переменную,
написав, к примеру:
$v1=param("v1");
теперь, если Вы вызвали скрипт с помощью приведенной выше URL-и, то
модуль будет искать в принятых данных переменную потока "v1", а найдя,
присвоит ее значение скаляру $v1, который будет теперь равняться
"vasya". Чтобы подтвердить правильность наших построений, давайте вы-
полним программу, которая иллюстрирует такую передачу данных:
Метод POST передает данные в теле запроса, а получать их следует
через входной поток программы (напомню, при запуске программы вебсер-
вером он направлен в протокол HTTP). Для отсылки данных этим методом в
HTML служат формы. Например, выполнив на клиенте приведенную ниже фор-
му мы получим точно такой же результат, как и в предыдущем примере:
Модуль CGI, обрабатывающий входные данные работает совершенно
одинаково как при применении метода GET, так и при использовании мето-
да POST.
Часто задаваемые вопросы (часть вторая)
Используются некоторые материалы из "Perl FAQ created by SLY Golovanov,
2:5020/794.13"
Где взять документацию по Perl?
Во-первых, Perl при установке добавляет в Вашу систему команду perldoc.
Выполните ее с ключем perldoc (т.е. perldoc perldoc), и она напишет как ею
пользоваться. Для модулей выполняйте perldoc <имя_модуля> а для внутенних фун-
кций perldoc -f <имя_функции>
Во-вторых, есть кое-какие книги по Perl на русском языке:
Что делать, если Ваш скрипт постоянно выдает код завершения номер 500 (внут-
ренняя ошибка сервера)?
1. Попробуйте запустить программу локально, для чего наберите в коман-
дной строке:
perl filename
(где filename это сами понимаете что).
Обратите внимание, что если вы работаете в Юникс-системе, где кроме уста-
новленного Вами пятого перла наверное есть еще и встроенный четвертый, и не
факт что он расположен позже на путях, имеет смысл набирать
perl5 filename
потому что пятый perl как правило имеет такой псевдоним. Попытка выполнить
программы с объектными модулями (к коим относится и модуль CGI) на четвертом
Perl приведет к печальным последствиям.
Если программу удалось запустить, посмотрите на сообщения от ошибках, ко-
торые она выдает. Обратите внимание, что исправлять можно ТОЛЬКО первую из
продиагностированных ошибок (остальные могут оказаться наведенными).
2. Если программа выполняется локально но не запускается сервером, про-
верьте, правильно ли программа выставляет HTTP-заголовок, устанавливающий тип
вывода. Для генерации HTML-документов он долже быть таким:
print "Content-type: text/htmlnn";
Убедитесь, что такая строка присутствует в Вашей программе до вывода любого
символа в HTTP поток. Говоря упрощенно, эта команда print должна быть выполне-
на раньше любой другой команды print.
3. Если это не принесло результата, проверьте тот ли Perl Вы вызываете.
Во многих UNIX-системах четвертый Perl расположен по пути:
/usr/local/perl
а пятый по пути:
/usr/local/bin/perl
На всякий случай убедитесь, что пятый Perl в системе вообще установлен.
4. Если и это не помогает, постарайтесь вспомнить, не проходил ли файл с
Вашим скриптом правки в текстовых редакторах из Windows. Разумеется, это ак-
туально только в том случае, если Вы запускаете скрипт на Unix-системе.
Дело в том, что у Windows и Unix различные символы конца строки. Любой
встроенный в Windows редактор оперирует с концами строк стандарта Windows, при
этом Unix не может выполнить такой файл. Для борьбы с таким эффектом рекомен-
дуется либо создавать и редактировать файлы только в Unix-системах, либо соз-
давать и редактировать их в Windows только встроенным редактором менеджера
FAR, который позволяет выбирать тип создаваемого файла через нажатие shift-F2.
По умолчанию этот редактор использует те символы окончания строк, которые уже
есть в файле (то есть созданный в UNIX файл можно сохранять "как есть", не за-
думываясь о его типе).
Если Ваш скрипт уже создан в стандарте Windows, а Вы хотите запустить его
на Unix, воспользуйтесь, например, вот такой программой:
$v1 = "x0d";
open A, "f1";
while ($line=<A>)
{
$line =~ s/$v1//g;
$itog .= $line;
}
close A;
open B, ">f1";
print B "$itog";
close B;
Эта программа открывает на чтение файл с именем f1, расположенный по мес-
ту запуска, читает оттуда по очереди все строки, заменяя окончание каждой из
них. После чтения программа открывает тот же файл как новый на запись и запи-
сывает в него полученый результат.
5. Как последний шанс - проверьте, имеет ли скрипт права на чтение и вы-
полнение со стороны того пользователя, от которого работает вебсервер. Нет, вы
все-таки это проверьте.
Если Вам и это не поможет, пишите в конференцию.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Как посмотреть все переменные окружения вебсервера, активные на данный
момент?
for (keys %ENV) { print "$_ = ${ENV{$_}}n" }
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Что такое ключи (cookies), и для чего они нужны?
Ключи - это способ открыть файл на диске клиента. Поскольку такой файл -
это потенциальный вирус, эта процедура должна быть как следует защищена на
уровне браузера. Ключ можно установить на время существования запущеного брау-
зера или на определенный срок. Для первого типа ключей можно не указывать вре-
мя, когда ключ будет удален, для второго типа нужно указать это время, причем
в доступном для браузера формате. Если браузер не сможет установить в своем
календаре даты, когда ключ должен быть удален, он сотрет его при первом же
закрытии программы. Для того, чтобы автоматизировать процесс составления даты,
применяется процедура, устанавливающая дату на месяц вперед от настоящего мо-
мента:
Не забудьте положить в какой-либо скаляр путь к Вашей программе от корня
соответсвующей области сервера. Имя программы указывать не надо, оно будет пе-
редано отдельно. Например:
$path = "/cgi-bin";
Теперь Вы всегда можете установить ключ, выполнив в своей программе вот
такой фрагмент кода:
Для того, чтобы считать ключ также предусмотрена специальная процедура:
sub get_cookie{
my (%cook, @temp, $i, $count, $key, $value);
(@temp)=split(/;/, $ENV{'HTTP_COOKIE'});
$count=@temp;
for ($i=0; $i<$count; $i++){
$temp[$i]=~s/ //;
($key, $value)=split(/=/, $temp[$i]);
$cook{$key}=$value;
}
return %cook;
}
После этого получить значение ключа можно, например, так:
if ($ENV{HTTP_COOKIE}){$cookies=1; %cookies=get_cookie();}
else {$cookies=0;}
if ($cookies==1)
{
$login=$cookies{'login'};
$pass=$cookies{'password'};
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Как скопировать из сети какой-либо файл?
Проще всего проинсталлировать на Вашу систему модуль libwww, который поз-
воляет делать это. Вот пример его использования:
#!/usr/local/bin/perl
use LWP::UserAgent;
use CGI qw(header);
my $URL = "http://www.rbc.ru/kpc/topnews/news_inc.html";
my $res = LWP::UserAgent->new->request(new HTTP::Request GET => $URL);
binmode(STDOUT);
print $res->content;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Как скопировать какой-либо файл на сервер?
Для этого нужно применить кодировку Multipart метода post, она позволяет
передавать на сервер даже бинарные файлы, причем размер их не ограничен. К со-
жалению, не все браузеры поддердживают эту кодировку. Netscape держит ее со
второй версии, MSIE- с версии 3.02. Вот пример использования этого способа:
#!/usr/local/bin/perl
use CGI qw(param);
$mode=param('mode');
$file=param('file');
# директория, в которые записывается принимаемый файл.
$fup = "/huge/httpd/htdocs/ufo/up";
if ($mode eq "upload")
{
print "Content-type: text/htmlnn";
@name= split(/\/, $file);
@name= reverse (@name);
($file1) = @name;
$file_new="$fup/"."$file1";
open A, "+>$file_new";
binmode A;
binmode $file;
while ($bytesread = read($file, $buf, 1024))
{
print A $buf;
}
close A;
print "<html>";
print "<body>";
print "Файл успешно перенесен на сервер.<br>";
print "<FORM method="post" action="/cgi-bin/upload.cgi">";
print "<input type="hidden" name="mode" value="">";
print "<input type="hidden" name="file" value="$file1">";
print "<input type="hidden" name="up_mode" value="mail">";
print "<DT><INPUT type="submit" value="back">";
print "</form>";
print "</body>";
print "</html>";
}
elsif ($mode eq "")
{
print "Content-type: text/htmlnn";
print "<html>";
print "<body>";
print "<p> Предупреждение. Программа пересылки файлов не работает с браузера-
ми Internet Explorer версии ниже 3.2"; print "<FORM method="post"
action="/cgi-bin/upload.cgi" enctype="multipart/form-data"
name="upload">";
print "<dt><b>Upload file: </b></dt>";
print "<input type="hidden" name="mode" value="upload">";
print "<dt><INPUT type="File" name="file" size=50></dt>";
print "<DT><INPUT type="submit" name="send" value="Send_file">";
print "<INPUT type="reset" name=clear></DT>";
print "</form>";
print "</body>";
print "</html>";
}
Часто задаваемые вопросы (часть третья)
Как послать письмо (в UNIX-системе).
Для работы с почтой в UNIX-системах традиционно используется программа
Sendmail. Обращаться к ней можно непосредственно, а можно через команду mail.
В любом случае, нужно сначала подготовить адреса, заменив в них символ "@" на
"@" - в противном случае программа не может быть выполнена.
$as1="@";
$as2="@";
$mails =~ s/$as1/$as2/g;
где $mails - это адрес или серия адресов, разделенных пробелами.
Письма традиционно отправляются в кодировке koi-8, в которую надо пере-
вести наш текст. Сделать это можно, записав тело письма, допустим, в скаляр
$as4 а затем выполнив над ними следующую операцию (для перевода из кодировки
1251 в кодировку koi-8):
$as4 =~
tr/АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяЁё/бвчздецъй
клмнопртуфхжигюыэящшьасБВЧЗДЕЦЪЙКЛМНОПРТУФХЖИГЮЫЭЯЩШЬАСi?/;
open MAILL, "|mail -s "Subject" $mails";
# В скаляре $mails через пробел перечисляются все адреса
print MAILL "$as4"; # это тело письма
close MAILL;
Используя программу Sendmail можно посылать письмо следующим образом:
open(MAIL, "|/usr/lib/sendmail -f $from_addr $mails");
print MAIL "Subject: subject_textn";
print MAIL "content-type: text/html; charset=koi8-rnn";
print MAIL "To: $user <$to_addr>n"; # На какой адрес отвечать.
print MAIL "$as4";
close MAIL;
LWP FAQ by Paul Kulchenko (paulclinger@yahoo.com), updated 03/04/2000
Это описание модуля LWP (иногда называемого LibWWW), содержащего множество
весьма полезных функций.
1.1. How to get text file (http, ftp)?
1.2. How to get jpeg/gif/bmp file and return it?
1.3. How to access password protected file?
1.4. How to set up REFERER and other HTTP header parameters?
1.5. How to get specified part of file (first MAXSIZE bytes)?
1.6. How to get and set up cookies?
1.7. How to specify proxy servers?
1.8. How to check for redirect?
1.9. How to create parameters for POST method?
my $ua = new LWP::UserAgent;
my $res = $ua->request(new HTTP::Request GET => $URL);
my $cookie_jar = new HTTP::Cookies;
$cookie_jar->extract_cookies($res);
print header;
if ($res->is_success) {
my $req = new HTTP::Request GET => $URL;
$cookie_jar->add_cookie_header($req);
$res = $ua->request($req);
print $res->is_success ? $res->as_string : $res->status_line;
} else {
print $res->status_line;
}
Emanual.ru – это сайт, посвящённый всем значимым событиям в IT-индустрии: новейшие разработки, уникальные методы и горячие новости! Тонны информации, полезной как для обычных пользователей, так и для самых продвинутых программистов! Интересные обсуждения на актуальные темы и огромная аудитория, которая может быть интересна широкому кругу рекламодателей. У нас вы узнаете всё о компьютерах, базах данных, операционных системах, сетях, инфраструктурах, связях и программированию на популярных языках!