Наши партнеры








Книги по Linux (с отзывами читателей)

Библиотека сайта rus-linux.net

Р.Сузи. Спецкурс "Язык Python и его приложения"

Лекция 8. CGI-программирование

CGI (Common Gateway Interface, общий интерфейс шлюза) -- протокол для запуска внешних по отношению к web-серверу приложений (CGI-скриптов), регулирует коммуникацию между HTTP-сервером и CGI-скриптами.

--sys.stdin,os.environ-->[CGI-script]--sys.stdout,sys.stderr-->

При поступлении запроса на 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).