Perl <

Часть Б. Перл как средство для работы с CGI


  • (5) CGI-скрипты
  • (Q 5.1) Что такое CGI и как с ним работать
  • (Q 5.2) Как заставить браузеры не кешировать выдаваемый результат?
  • (Q 5.3) Как перенаправить клиента на другой URL?
  • (Q 5.4) Как загрузить файл на сервер?
  • (Q 5.5) Как получить файл по URL?
  • (Q 5.6) ! Как использовать плюшки (cookies)?
  • (6) Web серверы
  • (Q 6.1) Как заставить WWW сервер исполнять CGI-программы?
  • (Q 6.2) Мой CGI-скрипт не работает! Как установить причину?
  • (Q 6.3) Ошибки HTTP 500 и 403. Что это значит и что с ними делать
  • (Q 6.4) ! Почему $ENV{REMOTE_HOST} пуста?
  • (Q 6.5) ! Почему $ENV{REMOTE_USER}} пуста? (5) CGI-скрипты (Q 5.1) Что такое CGI и как с ним работать (A) CGI -- Common Gateway Interface. Cтандарт интерфейса внешних программ с http-сервером. Как работать: HTTP -- клиент-серверный протокол, следовательно со стороны CGI, как серверного процесса, все взаимодействие выглядит следующим образом: 1. Получение данных от клиента 2. Обработка данных 3. Выдача ответа клиенту. Пункты 1 и 3 я в кратце опишу здесь, а 2, надеюсь, сделате сами. Начнем с п.3 как наиболее простого. 3. Выдача данных клиенту: Обычно клиенту выдают текст в формате HTML (ничто не мешает Вам отправить ему и картинку/видео/etc). Для того, чтобы сервер и клиент вас поняли, необходимо сказать, что вы выдаете, c помощью заголовка Content-Type: mime-type/mime-subtype. Обратите внимание на регистр и последовательность -- если вы скажите нечто типа Content_type, то сервер вас скорее всего не поймет. (Сообщение типа "500 Internal Server Error" будет симптомом). Пример: print "Content-Type: text/html\n"; # Мы выдаем текст в формате HTML. Также # можно: text/plain -- простой текст, в # брузере отобразится аналогично тексту, # заключённому между тегами <pre></pre>. # image/gif -- Картинка, формат gif # video/mpeg -- mpeg-видео # И целая куча других форматов, см. # файл mime.types из apache print "\n"; # <-- еще одна пустая строка, обозначает конец вывода наших # заголовков. ВАЖНО! # Теперь мы можем написать свой текст клиенту print " <html> <head> <title>Моя первая CGI программа</title> </head> <body> <h1>Моя первая CGI программа</h1> </body> </head> "; ## Все. 1. Прием данных от клиента Взаимодействие с клиентом обеспечивается так: Он заполняет форму своими значениями, нажимает на кнопку "submit", броузер кодирует данные соответствующим образом и отправляет их серверу. Определение форм Производится тегами <form> и </form>. Тег определения форм имеет следующие аттрибуты action -- скрипт на сервере, который будет запущен на сервере для обработки данных формы. method -- тип взаимодействия с сервером. Может иметь значения GET и POST. + еще некоторые специальные, которые вы можете посмотреть в учебнике Формы не могут быть вложенными. Элементы ввода Определяются тегами <input>, <textarea> и <select> тег <input>: <input type=checkbox> -- Элемен ввода "Опция" <input type=hidden> -- Элемент ввода, который не виден пользователю <input type=file> -- в Netscape Navigator позволяет загрузить файл на сервер <input type=image> -- Изображение. Если по нему шелкнуть, это вызовет submit формы и серверу будут выданы две переменные вида name.x и name.y, где name -- то, что вы пропишете в name=... тега <input> <input type=password> -- Элемент ввода Пароль. Позволяет ввести строку, которая на экране отображается звездочками. Никаких методов защиты при передаче на сервер не применяется <input type=radio> -- Радиокнопки <input type=reset> -- Кнопка сброса значений формы на начальные <input type=submit> -- Кнопка отправки формы на сервер <input type=text> -- строка ввода Все теги <input> имеют аттрибут name -- Наименование элемента. Служит для идентификации при передаче на сервер, а также другие типа value, width, etc, название и назначение которых можно опять-таки посмотреть в настоящем руководстве. Тег <textarea> -- Поле многострочного ввода. Тег <select> -- списочный выбор Пример: <form action=/cgi-bin/myscript.pl method=GET> Имя: <input type=string name=name><p> Пол: <input type=radio name=gender value=male>Мужской <input type=radio name=gender value=female>Женский <input type=submit><input type=reset> </form> Как это будет видно в моей программе? Это определяется методом формы, GET или POST В случае GET сервер установит переменную окружения QUERY_STRING в виде name1=vaue1&name2=value2&..&nameN=vauleN. В случае POST аналогичная строка будет записана на стандартный ввод. Ее длину можно получить через переменную окружения CONTENT_LENGTH. В обоих случаях данные будут закодированы по следующему алгоритму: Eсли ASCII код символа больше 32 и меньше 128, то он будет выдан без изменения. если символ - пробел, то он заменится на "+" (плюсик, без кавычек) все остальное преабразуется в вид %xx, где xx -- шестнадцатеричный код сивола. Если вам повезло и у вас "Русский apache", то он преобразует его в нормальную кодировку. Декодирование на perl tr/+/ /; s/%([0-9a-fA-F]{2})/pack("c",hex($1))/ge; (списано из CGI.pm) На самом деле, можно не возится со всем этим, а использовать модуль CGI.pm (Имеется в поставке Perl 5.004 и более поздних. Если у вас perl версии 4 или 1, нужно срочно взять на CPAN новую версию perl) Самый большой и последний пример Предположим мы делаем поисковую систему, тогда у нас должен быть HTML с формой и программа, которая будет выполнять поиск. ---- search.html <html> <head> <title>Поиск</title> </head> <body> <h1>Чего искать?</h1> <form action=/cgi-bin/search.pl method=get> Строка для поиска: <input type=text name=string width=70><p> Искать в <input type=checkbox name=searchin value=internet>Интернет <input type=checkbox name=searchin value=intranet>Интранет <input type=checkbox name=searchin value=extranet>Экстранет<p> <input type=submit value=Давай!><input type=reset value="Нет, не надо"> </form> </body> </html> ---- конец search.html Программа: ---- начало search.pl #!/usr/bin/perl -- поменяйте, как надо use CGI qw(:standard); print "Content-Type: text/html\n\n"; # Не забудьте про два "\n" $string = param("string"); @searchin = param("searchin"); # searchin это checkbox и его значения # возвращаются списком # Искать мы сегодня ничего не будем print "<html> <body> <h1>Мы сегодня ничего не ищем</h1> Но, если бы искали, то: <br> Искали бы строку <b>$string</b><br>\n"; print "В <b>" . join(" ", @searchin) . "</b>\n"; print " </body> </html> "; ---- конец search.pl Да, кстати, если вы собираетесь писать в файлы с помощью CGI-программ, не забывайте про file locking. (Q 5.2) Как заставить браузеры не кешировать выдаваемый результат? (A) Выдавайте заголовки в таком виде: print "Content-Type: type/sub-type\n"; # Подставьте Ваш тип/подтип print "Pragma: no-cache\n"; # Для HTTP/1.0 клиентов print "Cache-Control: no-cache\n"; # Для HTTP/1.1 print "Expires: Thu Jan 1 00:00:00 1970\n\n"; # Это уже любой браузер должен # понять (Q 5.3) Как перенаправить клиента на другой URL? (A) В заголовке напишите: print "Status: 302\n"; # Или 301. Разница состоит в том, что по стандарту 301 значит "перемещён # навсегда", а 302 -- "перемещён временно" print "Location: ВАШ Новый URL\n"; # URL должен быть указан абсолютный print "URI: ВАШ новый URL\n\n"; # Для http/1.0 Подробности: см. rfc1945(http/1.0), rfc2068(http/1.1) (Q 5.4) Как загрузить файл на сервер? (A) В поставку CGI.pm входит пример file_upload.cgi. Подробности CGI(3) (Q 5.5) Как получить файл по URL? (A) Возьмите на CPAN библиотеку libwww-perl и смотрите lwpcook(3), там написаны основы использования библиотеки и есть примеры. (Q 5.6) ! Как использовать плюшки (cookies)?(A) Плюшки работают следующим образом: программа CGI добавляет в свой ответ директиву Set-Cookie, а клиент (если он поддерживает плюшки), при следующих запросах возвращает их. Сами плюшки представляют из себя пары имя=значение. Ситаксис Set-Cookie: Set-Cookie: имя=значение; expires=дата; path=путь; domain=домен; secure Сервер может установить не более 20 плюшек, размер всей плюшки не может превышать 4Kb. * Имя=значение единственный обязательный параметр. И имя, и значение могут быть строками текста, не содержащими символов перевода строки, побелов, ; и табуляции. Если необходимо их использовать, можно эти символы закодировать при помощи стандартного url-кодирования. * expires=дата, устанавливается дата истечения срока действия плюшки. После этой дата плюшка клиентом не возвращается. Если дата не установлена, то плюшка действует до завершения работы браузера. * path=путь, обозначает путь на сервере, для которого возвращается эта плюшка, если не указано, то только для того, который ее создал. * domain=домен, домен, для которого возвращается эта плюшка. Может быть доменом уровня 2 и выше, т.е. .example.ru, а не .ru. Если не установлен, то плюшка возвращается только серверу, который выдал плюшку. * secure, указывает, что плющка должна возвращаться только по защищенному соединению (SSL). Синтаксис ответа клиента: Cookie: имя1=значение1; имя2=значение2;....;имяn=значениеn Программы CGI могут получить пары имя-значение через переменную окружения HTTP_COOKIE. В модуле CGI.pm значение можно получить при помощи метода cookie(). Пример: 1. Установка плюшки ---- начало setcookie.pl #!/usr/bin/perl print "Content-Type: text/html\n"; print "Set-Cookie: mycookie=some+string\n\n"; print "<html><head><title>Установка плюшки</title></head>\n"; print "<body><h1>Установка плюшки</h1>\n"; print "<a href=getcookie.pl>Щелкни здесь,</a> чтобы посмотреть, что получилось. print "</body></html>"; ---- конец setcookie.pl 2. Получение плюшки файл getcookie.pl ---- начало getcookie.pl #!/usr/bin/perl use CGI qw(:standard); print "Content-Type: text/html\n\n"; print "<html><head><title>Получение плюшки</title></head>\n"; print "<body><h1>Плюшка</h1>\n"; print "mycookie = ", getcookie('mycookie'); print "</body></html>"; ---- конец getcookie.pl * * * (6) Web серверы (Q 6.1) Как заставить WWW сервер исполнять CGI-программы? (A) Apache для Unix/Win32 Надо поправить конфигурационные файлы (я расчитываю, что у вас default конфиги apache) Способ 1 srm.conf Директива ScriptAlias ScriptAlias /cgi-bin/ /usr/local/apache/cgi-bin/ и в файле access.conf прописать <Directory /usr/local/apache/cgi-bin/> Options ExecCGI </directory> (если приглядется, там нужно только раскоментировать опции) Это позволит вам помещать программы в каталог /usr/local/apache/cgi-bin/ и они будут видны по URL http://you/cgi-bin/program_name Способ 2 Добавить в srm.conf директиву AddHandler cgi-script .cgi и вы сможете вызывать cgi-программу из любого каталога. Но она должна иметь окончание .cgi и для этого каталога должно быть разрешено исполнение CGI (Options ExecCGI в access.conf, написано выше). Оба способа можно без проблем использовать совместно. (Q 6.2) Мой CGI-скрипт не работает! Как установить причину?Прежде чем читать дальше, убедитесь в том, что: 1) Вы запустили скрипт с командной строки (не через CGI!!!) и он работает, а не говорит 'compilation stopped due to errors' 2) Скрипт не только работает, но и выдает нужный заголовок с пустой строкой после него 3) (Для многопользовательских систем) Вы сделали тоже под пользователем, под которым работает сервер (su -m имя_пользователя -c script в Unix) и он столь же благополучно работает (Q 6.3) Ошибки HTTP 500 и 403. Что это значит и что с ними делать(A) error_log для того и служит, чтобы туда смотреть :-) Основные причины: Ошибка 403 "Forbidden" Возникает, если сервер не может отдать вам содержимое по причине отсутствия полномочий. Проверьте: Может ли user (для apache под Unix это обычно nobody), под которым работает, сервер исполнять файл? В частности, может ли сервер исполнять интерпретатор (в случае скриптовых языков)? Можно ли для этого каталога исполнять CGI? (Options ExecCGI для apache) Ошибка 500 "Internal Server Error" Возникает в случае внутренней ошибки. Проверьте: Выводите ли вы строку "Content-Type:"? Правильно ли вы ее выводите? (Content-type, Content_Type -- неправильно) Заканчиваете ли вы хедеры пустой строкой? (Нельзя написать print "Content-Type: text/html\n"; print "<HTML>\n"; Надо писать: print "Content-Type: text/html\n\n"; # Два "\n" print "<HTML>\n";) Также, эта ошибка возникает, если CGI-программа завершилась с ненулевым кодом возврата, что часто встречается в случае некомпилируемости вашего скрипта perl'ом. Совет: делайте use CGI::Carp qw(fatalsToBrowser) во время отладки, тогда вам выдадут сообщение об ошибке perl. (Q 6.4) ! Почему $ENV{REMOTE_HOST} пуста?(A) apache устнавливает переменную окружения REMOTE_HOST, если ему разрешено проводить dns запросы для определения имени. Для 1.3.x по-умолчанию это выключено. Включается/выключается директивой HostNameLookups, которая может принимать 3 значения: on -- проводить запросы, off -- не запрашивать dns и double -- делать двойные запросы: запрашивать имя хоста, а затем по имени запрашивать ip адрес, для безопасности. (Q 6.5) ! Почему $ENV{REMOTE_USER}} пуста?(A) Переменная окружения REMOTE_USER устанавливается apache в случае, если скрипт защищен паролем. Как это сделать рассказано на http://www.apacheweek.com/features/userauth и http://www.apacheweek.com/features/dbmauth
    Рейтинги
    Яндекс цитирования

    GameTop - рейтинг игровых ресурсов. Портал Rolemancer (www.rolemancer.ru)