Библиотека сайта rus-linux.net
Р.Сузи. Спецкурс "Язык Python и его приложения"
Лекция 8. CGI-программирование
CGI (Common Gateway Interface, общий интерфейс шлюза) -- протокол для запуска внешних по отношению к web-серверу приложений (CGI-скриптов), регулирует коммуникацию между HTTP-сервером и CGI-скриптами.
При поступлении запроса на URL, который Web-сервер настроен считать CGI-скриптом, сервер вызывает скрипт, передавая ему информацию через стандартный ввод, переменные окружения и (для ISINDEX) -- через аргументы командной строки.
Примечание: кроме того, для передачи ISINDEX
могут использоваться аргументы командной строки. В Python
они доступны в списке sys.argv
.
Два основных метода передачи данных из заполненной в браузере формы
Web-серверу (и CGI-скрипту) -- method="GET"
и
method="POST"
. В зависимости от метода данные передаются
по-разному. В первом случае они кодируются и помещаются прямо
в URL, типа: http://host/cgi-bin/a.cgi?a=1&b=3
.
Скрипт получает их в переменной окружения QUERY_STRING.
Во втором случае они передаются на стандартный ввод.
Следющий простейший скрипт выводит значения из словаря os.environ:
#!/usr/bin/python import os print """Content-Type: text/plain %s""" % os.environ
С помощью него можно увидеть установленные Web-сервером переменные окружения.
Основные переменные окружения следующие:
- QUERY_STRING
- Строка запроса
- REMOTE_ADDR
- IP-адрес клиента
- REMOTE_USER
- Имя клиента (если он был авторизован)
- SCRIPT_NAME
- Имя скрипта
- SCRIPT_FILENAME
- Имя файла со скриптом
- SERVER_NAME
- Имя сервера
- HTTP_USER_AGENT
- Название браузера клиента
- REQUEST_URI
- Строка запроса (URI)
- HTTP_USER_AGENT
- Имя сервера
- HTTP_ACCEPT_LANGUAGE
- Желательный язык документа
Пример:
В Python имеется поддержка CGI в виде модуля cgi
.
пример:
#!/usr/bin/python import cgi, os # анализ запроса f = cgi.FieldStorage() if f.has_key("a"): a = f["a"].value else: a = "0" # обработка запроса b = str(int(a)+1) mytext = open(os.environ["SCRIPT_FILENAME"]).read() mytext_html = cgi.escape(mytext) # формированиве ответа print """Content-Type: text/html <html><head><title>Решение примера: %(b)s = %(a)s + 1</title></head> <body> %(b)s <table width="80%%"><tr><td> <form action="me.cgi" method="GET"> <input type="text" name="a" value="0" size="6"> <input type="submit" name="b" value="Обработать"> </form></td></tr></table> <pre> %(mytext_html)s </pre> </body></html>""" % vars()
В этом примере к заданному в форме числу прибавляется 1.
Кроме того, выводится исходный код самого скрипта.
Заметьте, что для экранирования символов >, <, &
применена функция cgi.escape()
. И еще.
Для формирования Web-страницы использована операция форматирования.
В качестве словаря -- словарь vars()
со всеми
локальными переменными. Знаки процента пришлось удвоить
(для задания ширины таблицы).
При обработке входных значений CGI-скриптов будьте очень внимательны. Строго проверяйте допустимые значения. Считайте, что клиент может передать на вход все, что угодно.
Например, не подставляйте полученные от пользователя данные в путь к файлу. Не вставляйте их напрямую в формируемые страницы, если эти страницы увидит не только клиент, заказавший URL (например, web-чаты, форумы, гостевые книги и т.п.).
Даже если CGI-скрипт используется исключительно другими скриптами через запрос на URL, проверяйте входные значения столь же тщательно, как если бы данные вводил пользователь. (Так как недоброжелатель может подать на вход CGI любые значения).
В примере выше проверка на допустимость произведена при
вызове функции int(): если бы было задано нечисло,
скрипт бы аварийно завершился, а пользователь
увидел бы Internal Server Error
После анализа входных данных можно выделить фазу их обработки. В этой части CGI-скрипта вычисляются переменные для дальнейшего вывода. Здесь необходимо учитывать не только значения переданных переменных, но и факт их присутствия или отсутствия, так как это тоже может влиять на логику скрипта.
И наконец, фаза вывода готового объекта (текста, HTML-документа, изображения, мультимедиа-объекта и т.п.).
Следующий пример выдает черный квадрат:
#!/usr/bin/python import sys print """Content-Type: image/jpeg """ import Image i = Image.new("RGB", (10,10)) i.im.draw_rectangle((0,0,10,10), 1) i.save(sys.stdout, "jpeg")
Проще всего поступить как в примере 2: заранее подготовить шаблон страницы, а потом просто заполнить содержимым из переменных.
Для формирования HTML-документа можно использовать и специальные средства, обсуждение которых можно найти на http://www.python.org/topics/web/HTML.html
Обычно при создании Web-приложений стараются отделить Форму (внешний вид, стиль), Содержание и Логику обработки данных. В приведенном выше примере Логика отделена от Формы и Содержания. (Последние в силу простоты примера не отделены.)
Для создания Web-приложений применяются и более сложные средства, например, Zope (Z Object Publishing Environment, среда публикации объектов). Zope имеет встроенный web-сервер, но может работать и с другими Web-серверами, например, Apache.
Для ускорения работы CGI (для Apache) используется различные схемы, например, FastCGI или PCGI (Persistent CGI).