Ключевые слова:perl, cgi, web, http, howto, (найти похожие документы)
Date: Mon, 23 Oct 2000 12:18:57 +0400 (MSD)
From: MailList: Perl в примерах
Subject: Базовые принцип работы CGI скриптов
CGI вывод
Николай Матковский (matkovsky@ukrpost.net)
В этой статье речь пойдет о том, что должна выдавать CGI-программа на
выходе. Посмотрим для начала на то, как броузер, сервер и
CGI-программа взаимодействуют между собой.
Процесс взаимодействия начинается с того момента, когда броузер
запрашивает у сервера некоторый файл или указывает ему выполнить
некоторый скрипт. Если это файл, сервер пытается найти этот файл, и,
если он его находит, он пытается определить что это за файл -
HTML-страница, рисунок и т.д. После этого сервер сообщает броузеру,
что файл найден, выдает ему информацию о типе этого файла и,
соответственно, сам файл.
Вот как это выглядит.
Допустим, есть страница page.html, которая содержит следующий текст:
<html> <head>
<title>Perl в примерах</title>
</head>
<body>
<h2>Perl в примерах</h2>
</body>
</html>
Допустим вы ввели в адресной строке броузера
http://perl.hotmail.ru/page.html. В этом случае сервер ищет этот файл,
находит его и выдает броузеру примерно такое:
HTTP/1.0 200 OK
Date: Tue, 04 Apr 1999 12:27:49 GMT
Server: Apache/1.3.7
Content-type: text/html
Content-length: 100
Last-modified: Thu, 04 Apr 1999 12:23:51 GMT
<html> <head>
<title>Perl в примерах</title>
</head>
<body>
<h2>Perl в примерах</h2>
</body>
</html>
Итак, видим, что полученные данные состоят из двух частей, разделенных
пустой строкой - заголовка и тела. Заголовок сгенерирован сервером при
отправлении данных и содержит информацию об этих данных, в то время
как тело содержит собственно сами данные. Еще раз стоит обратить
внимание на то, что они разделяются пустой строкой - это очень важно,
поскольку при помощи именно этой строки броузер определяет, где
заканчивается заголовочная часть и начинаются данные.
При выполнении CGI-программ все происходит почти так же. Почти, потому
что сервер не может определить всю необходимую информацию о
возвращаемых программой данных, поэтому скрипт должен самостоятельно
создавать необходимую часть заголовка, а сервер только дополнит то,
что он от него получит. Вернемся к этому попозже.
Заголовок
А сейчас рассмотрим внимательнее заголовок. Первая строка гласит:
HTTP/1.0 200 OK
Общий вид этой строки такой:
HTTP/1.0 номер сообщение
Здесь номер и сообщение - это код состояния и соответствующее этому
коду сообщение сервера. Они указывают на результат выполнения запроса
броузера. (Например, код 404 и сообщение "Not found" означают, что
запрашиваемый файл не найден, а код 200 и сообщение "ОК" означают, что
запрос выполнен успешно).
Ниже перечислены все наиболее стоящие запоминания (или хотя бы знания
об их существовании) коды и сообщения сервера:
Код Сообщение Что означает
200 OK Документ был успешно найден и отправлен
204 No Content Документ был найден, но отсутствуют данные для отправки
301 Moved Permanently Документ перемещен в место, указанное в
заголовке Location
302 Moved Temporarily Документ временно перемещен в место, указанное в
заголовке Location
401 Unauthorized Запрашиваемый документ охраняется некоторой системой
защиты
404 Not found Документ не найден
500 Internal server error Ошибка при выполнении скрипта (например)
Следующие две строки - параметры Date и Server особой пользы не несут
и являются исключительно информационными. Очевидно, их значения - это
время выполнения обработки запроса (в формате GMT) и название/версия
сервера.
Далее следует очень важный параметр - Content-type. Этот параметр
указывает на то, какие именно данные передются сервером броузеру.
Значением этого параметра является тип MIME (Multimedia Internet Mail
Extension). Например, MIME-тип для HTML-файлов - text/html (как вы уже
наверное поняли из примера), для изображений в формате GIF - image/gif
и т.д.
Ниже перечислены самые распространенные MIME-типы:
text/plain Обычный текст. По умолчанию, если сервер не может
определить тип файла (по расширению, например), он указывает этот
MIME-тип
text/html HTML-текст
text/richtext Текстовый формат Rich Text.
image/gif Изображения в формате GIF
image/jpeg Изображения в формате JPEG
image/x-xbitmap X-bitmap - простейший формат для изображений
audio/basic 8-битовое аудио, ulaw-compressed
audio/x-wav Аудио в формате Microsoft Windows Audio.
video/mpeg MPEG-компрессия видео
video/quicktime Видео в формате QuickTime
video/x-msvideo Microsoft видео. Как правило - .avi-файлы
application/postscript Postscript-файлы
Следующий параметр заголовка - Content-length - указывает количество
(размер) передаваемых данных, и последний, Last-modified, - дату и
время последней модификации этого файла.
Познакомим вас с еще одним параметром, не встреченным в примере, но
тем не менее очень важным. Это параметр Location. Этот параметр
включается в заголовок для переадрессации броузера на некоторый другой
URI, и принимает значение этого некоторого URI.
Выглядит он вот так:
Location: абсолютный_URL
О его пользе (если она не очевидна) - дальше.
Скрипт
Что же должен делать скрипт?
Как уже было сказано выше, он должен сам генерировать необходимую
часть заголовка, которую сервер позже дополнит тем, чем он посчитает
нужным дополнить. "Необходимую" означает ту, которую стоит указать для
того, чтобы сервер не указал информацию по умолчанию или вообще
пропустил.
Чаще всего этой необходимой (и достаточной) информацией является
параметр Content-type. (Правильнее будет, наверное, сказать, что этот
параметр обязателен с некоторыми исключениями). Итак, CGI-программа
должна указать на то, какого рода данные она возвращает.
Например, такая программа:
#!/usr/bin/perl
$file = '/usr/local/etc/httpd/htdocs/images/picture.gif';
print "Content-Type: image/gif\n\n";
open(GIF,"<$file") || die "Can't open GIF\n";
while (read(GIF,$buffer,16384)) {
print $buffer;
}
... возвращает GIF-изображение, поэотму она указывает
Content-Type: image/gif
А вот такая:
#!/usr/bin/perl
print "Content-Type: text/plain
This is a plain text.
Look how much of it is here.";
... - простой текст, поэтому и заголовок у нее соответствующий.
Другим возможным (и полезным) вариантом является добавление в
заголовок параметра Location. В таком случае, при выполнении скрипта
броузер будет переадресован на указанную страницу. Какая от этого
польза? Например, вы напишете скрипт, который в разных случаях будет
выдавать разный текст, но каждый раз в одном и том же случае этот
текст одинаковый (например, сообщение о правильном или неправильном
пароле). В таком случае удобней создать n страниц, и в различных
случаях отправлять пользователя на ту или иную страницу. В случае,
когда вам нужно будет что-то поменять в тексте одной из них, вам не
придется копаться в коде, давным-давно написаном и забытом, а просто
отредактировать соответствующую страницу.
#!/usr/bin/perl
require "check.pl"; # допустим, это модуль для проверки пароля
getParameters(*input);
if (check_password($input{'name'}, $input{'password'}) {
print "Location: /right.html\n\n";
} else {
print "Location: /wrong.html\n\n";
}
Обратите внимание на что, что здесь не нужно указывать Content-type -
при получении этих данных броузер выполнит еще один запрос - на
соответствующую страницу, после чего сервер сам определит тип этого
файла.
Последний параметр, который вам наверное понадобится - это Status. С
помощью этого параметра вы можете сами указать броузеру, как ему
воспринять ответ вашего скрипта. После слова Status и двоеточия должны
идти код и соответствующее сообщение - из тех кодов и сообщений
сервера, что уже были перечислены выше. Например, после получения
данных этой программы броузер скорее всего останется на той же
странице, с которой вызывал этот скрипт.
#!/usr/bin/perl
... # тут происходят важные, но никому не интересные процессы
print "Status: 204 No Content\n\n";
И самое главное, не забывайте о том, что заголовок отделяется от
данных пустой строкой, поэтому после определения заголовка обязательно
должны идти два символа новой строки (\n\n).