Опубликован: 22.12.2005 | Уровень: для всех | Доступ: платный
Лекция 8:

Разработка Web-приложений

< Лекция 7 || Лекция 8: 1234 || Лекция 9 >

Что после CGI?

К сожалению, строительство интерактивного и посещаемого сайта на основе CGI имеет свои ограничения, главным образом, связанные с производительностью. Ведь для каждого запроса нужно вызвать как минимум один сценарий (а значит - запустить интерпретатор Python), из него, возможно, сделать соединение с базой данных и т.д. Время запуска интерпретатора Python достаточно невелико, тем не менее, на занятом сервере оно может оказывать сильное влияние на загрузку процессора.

Желательно, чтобы интерпретатор уже находился в оперативной памяти, и были доступны соединения с базой данных.

Такие технологии существуют и обычно опираются на модули, встраиваемые в web-сервер.

Для ускорения работы CGI используются различные схемы, например, FastCGI или PCGI (Persistent CGI). В данной лекции предлагается к рассмотрению специальный модуль для web-сервера Apache, называемый mod_python.

Пусть модуль установлен на web-сервере в соответствии с инструкциями, данными в его документации.

Модуль mod_python позволяет сценарию-обработчику вклиниваться в процесс обработки HTTP-запроса сервером Apache на любом этапе, для чего сценарий должен иметь определенным образом названные функции.

Сначала нужно выделить каталог, в котором будет работать сценарий-обработчик. Пусть это каталог /var/www/html/mywebdir. Для того чтобы web-сервер знал, что в этом каталоге необходимо применять mod_python, следует добавить в файл конфигурации Apache следующие строки:

<Directory "/var/www/html/mywebdir">
  AddHandler python-program .py
  PythonHandler mprocess
</Directory>

После этого необходимо перезапустить web-сервер и, если все прошло без ошибок, можно приступать к написанию обработчика mprocess.py. Этот сценарий будет реагировать на любой запрос вида http://localhost/*.py.

Следующий сценарий mprocess.py выведет в браузере страницу со словами Hello, world!:

from mod_python import apache

def handler(req):
  req.content_type = "text/html"
  req.send_http_header()
  req.write("""<HTML><HEAD><TITLE>Hello, world!</TITLE></HEAD>
  <BODY>Hello, world!</BODY></HTML>""")
  return apache.OK

Отличия сценария-обработчика от CGI-сценария:

  1. Сценарий-обработчик не запускается при каждом HTTP-запросе: он уже находится в памяти, и из него вызываются необходимые функции-обработчики (в приведенном примере такая функция всего одна - handler() ). Каждый процесс-потомок web-сервера может иметь свою копию сценария и интерпретатора Python.
  2. Как следствие п.1 различные HTTP-запросы делят одни и те же глобальные переменные. Например, таким образом можно инициализировать соединение с базой данных и применять его во всех запросах (хотя в некоторых случаях потребуются блокировки, исключающие одновременное использование соединения разными потоками (нитями) управления).
  3. Обработчик задействуется при обращении к любому "файлу" с расширением py, тогда как CGI-сценарий обычно запускается при обращении по конкретному имени.
  4. В сценарии-обработчике нельзя рассчитывать на то, что он увидит модули, расположенные в том же каталоге. Возможно, придется добавить некоторые каталоги в sys.path.
  5. Текущий рабочий каталог (его можно узнать с помощью функции os.getcwd() ) также не находится в одном каталоге с обработчиком.
  6. #!-строка в первой строке сценария не определяет версию интерпретатора Python. Работает версия, для которой был скомпилирован mod_python.
  7. Все необходимые параметры передаются в обработчик в виде Request-объекта. Возвращаемые значения также передаются через этот объект.
  8. Web-сервер замечает, что сценарий-обработчик изменился, но не заметит изменений в импортируемых в него модулях. Команда touch mprocess.py обновит дату изменения файла сценария.
  9. Отображение os.environ в обработчике может быть обрезанным. Кроме того, вызываемые из сценария-обработчика другие программы его не наследуют, как это происходит при работе с CGI-сценариями. Переменные можно получить другим путем: req.add_common_vars(); params = req.subprocess_env.
  10. Так как сценарий-обработчик не является "одноразовым", как CGI-сценарий, из-за ошибок программирования (как самого сценария, так и других компонентов) могут возникать утечки памяти (программа не освобождает ставшую ненужной память). Следует установить значение параметра MaxRequestsPerChild (максимальное число запросов, обрабатываемое одним процессом-потомком) больше нуля.

Другой возможный обработчик - сценарий идентификации:

def authenhandler(req):
  password = req.get_basic_auth_pw()
  user = req.connection.user
  if user == "user1" and password == "secret":
      return apache.OK
  else:
      return apache.HTTP_UNAUTHORIZED

Эту функцию следует добавить в модуль mprocess.py, который был рассмотрен ранее. Кроме того, нужно дополнить конфигурацию, назначив обработчик для запросов идентификации ( PythonAuthenHandler ), а также обычные для Apache директивы AuthType, AuthName, require, определяющие способ авторизации:

<Directory "/var/www/html/mywebdir">
  AddHandler python-program .py
  PythonHandler mprocess
  PythonAuthenHandler mprocess
  AuthType Basic
  AuthName "My page"
  require valid-user
</Directory>

Разумеется, это - всего лишь пример. В реальности идентификация может быть устроена намного сложнее.

Другие возможные обработчики (по документации к mod_python можно уточнить, в какие моменты обработки запроса они вызываются):

PythonPostReadRequestHandler

Обработка полученного запроса сразу после его получения.

PythonTransHandler

Позволяет изменить URI запроса (в том числе имя виртуального сервера).

PythonHeaderParserHandler

Обработка полей запроса.

PythonAccessHandler

Обработка ограничений доступа (например, по IP-адресу).

PythonAuthenHandler

Идентификация пользователя.

PythonTypeHandler

Определение и/или настройка типа документа, языка и т.д.

PythonFixupHandler

Изменение полей непосредственно перед вызовом обработчиков содержимого.

PythonHandler

Основной обработчик запроса.

PythonInitHandler

PythonPostReadRequestHandler или PythonHeaderParserHandler в зависимости от нахождения в конфигурации web-сервера.

PythonLogHandler

Управление записью в логи.

PythonCleanupHandler

Обработчик, вызываемый непосредственно перед уничтожением Request-объекта.

Некоторые из этих обработчиков работают только глобально, так как при вызове даже каталог их приложения может быть неизвестен (таков, например, PythonPostReadRequestHandler ).

С помощью mod_python можно строить web-сайты с динамическим содержимым и контролировать некоторые аспекты работы web-сервера Apache через Python-сценарии.

< Лекция 7 || Лекция 8: 1234 || Лекция 9 >
Сергей Крупко
Сергей Крупко

Добрый день.

Я сейчас прохожу курс  повышения квалификации  - "Профессиональное веб-программирование". Мне нужно получить диплом по этому курсу. Я так полагаю нужно его оплатить чтобы получить диплом о повышении квалификации. Как мне оплатить этот курс?

 

Павел Ялганов
Павел Ялганов

Скажите экзамен тоже будет ввиде теста? или там будет какое то практическое интересное задание?

Максим Чиндясов
Максим Чиндясов
Россия, Нижний Новгород
Ольга Коваль
Ольга Коваль
Беларусь, Минск