Руководство Apache: динамическое содержимое с помощью CGI
Введение
| Связанные модули | Связанные директивы |
|---|---|
CGI (Common Gateway Interface — общий шлюзовый интерфейс) определяет способ взаимодействия веб-сервера с внешними программами, создающими содержимое, которые часто называют программами CGI или CGI-скриптами. Это простой способ добавить динамическое содержимое на ваш веб-сайт с помощью любого знакомого вам языка программирования. В этом документе рассказывается, как настроить CGI на веб-сервере Apache и приступить к написанию программ CGI.
Настройка Apache для разрешения CGI
Чтобы ваши программы CGI работали правильно, необходимо настроить Apache для разрешения выполнения CGI. Это можно сделать несколькими способами.
httpd.conf убедитесь, что директива LoadModule не закомментирована. Правильно настроенная директива может выглядеть так: LoadModule cgid_module modules/mod_cgid.soВ Windows или при использовании многопоточной модели MPM, например prefork, правильно настроенная директива может выглядеть так:
LoadModule cgi_module modules/mod_cgi.so
ScriptAlias
Директива ScriptAlias сообщает Apache, что определенный каталог отведен для программ CGI. Apache будет считать каждый файл в этом каталоге программой CGI и попытается выполнить его, когда клиент запросит соответствующий ресурс.
Директива ScriptAlias выглядит так:
ScriptAlias "/cgi-bin/" "/usr/local/apache2/cgi-bin/"
Приведенный пример взят из конфигурационного файла httpd.conf по умолчанию, если Apache установлен в расположение по умолчанию. Директива ScriptAlias похожа на директиву Alias, которая определяет префикс URL, сопоставляемый с определенным каталогом. Alias и ScriptAlias обычно используются для каталогов, расположенных вне каталога DocumentRoot. Отличие Alias от ScriptAlias заключается в том, что ScriptAlias дополнительно указывает, что все содержимое по этому префиксу URL будет считаться программами CGI. Таким образом, приведенный выше пример сообщает Apache, что любой запрос ресурса, начинающегося с /cgi-bin/, должен обслуживаться из каталога /usr/local/apache2/cgi-bin/ и обрабатываться как программа CGI.
Например, если запрошен URL http://www.example.com/cgi-bin/test.pl, Apache попытается выполнить файл /usr/local/apache2/cgi-bin/test.pl и вернуть результат. Разумеется, файл должен существовать, быть исполняемым и возвращать результат в определенном формате, иначе Apache выдаст сообщение об ошибке.
CGI вне каталогов ScriptAlias
Из соображений безопасности программы CGI часто разрешено запускать только из каталогов, указанных в ScriptAlias. Так администраторы могут строго контролировать, кому разрешено использовать программы CGI. Однако при соблюдении надлежащих мер безопасности нет причин, по которым программы CGI нельзя запускать из произвольных каталогов. Например, вы можете разрешить пользователям размещать веб-содержимое в своих домашних каталогах с помощью директивы UserDir. Если они захотят запускать собственные программы CGI, но не будут иметь доступа к основному каталогу cgi-bin, им потребуется возможность запускать программы CGI в другом месте.
Чтобы разрешить выполнение CGI в произвольном каталоге, необходимо выполнить два шага. Сначала нужно активировать обработчик cgi-script с помощью директивы AddHandler или SetHandler. Затем в директиве Options нужно указать ExecCGI.
Явное использование Options для разрешения выполнения CGI
Можно явно использовать директиву Options в основном конфигурационном файле сервера, чтобы указать, что выполнение CGI разрешено в определенном каталоге:
<Directory "/usr/local/apache2/htdocs/somedir">
Options +ExecCGI
</Directory> Приведенная выше директива сообщает Apache, что выполнение файлов CGI разрешено. Также нужно сообщить серверу, какие файлы являются файлами CGI. Следующая директива AddHandler указывает серверу обрабатывать все файлы с расширением cgi или pl как программы CGI:
AddHandler cgi-script .cgi .pl
Файлы .htaccess
В руководстве по .htaccess показано, как активировать программы CGI, если у вас нет доступа к httpd.conf.
Пользовательские каталоги
Чтобы разрешить выполнение программ CGI для всех файлов с окончанием .cgi в пользовательских каталогах, можно использовать следующую конфигурацию.
<Directory "/home/*/public_html">
Options +ExecCGI
AddHandler cgi-script .cgi
</Directory> Если вы хотите указать подкаталог cgi-bin в пользовательском каталоге, где все файлы будут обрабатываться как программы CGI, можно использовать следующую конфигурацию.
<Directory "/home/*/public_html/cgi-bin">
Options ExecCGI
SetHandler cgi-script
</Directory> Написание программы CGI
Между «обычным» программированием и программированием CGI есть два основных различия.
Во-первых, перед всеми выходными данными программы CGI должен идти заголовок типа MIME. Это заголовок HTTP, который сообщает клиенту, какой тип содержимого он получает. Чаще всего он выглядит так:
Content-type: text/html
Во-вторых, выходные данные должны быть в формате HTML или в другом формате, который может отображать браузер. Обычно это HTML, но иногда можно написать программу CGI, которая выводит изображение GIF или другое содержимое не в формате HTML.
За исключением этих двух особенностей, написание программы CGI во многом похоже на написание любой другой программы.
Ваша первая программа CGI
Ниже приведен пример программы CGI, которая выводит одну строку в браузер. Введите следующий текст, сохраните его в файле с именем first.pl и поместите файл в каталог cgi-bin.
#!/usr/bin/perl print "Content-type: text/html\n\n"; print "Hello, World.";
Даже если вы не знакомы с Perl, вы должны понимать, что здесь происходит. Первая строка сообщает Apache (или оболочке, в которой выполняется программа), что этот файл можно выполнить, передав его интерпретатору, расположенному по адресу /usr/bin/perl. Вторая строка выводит объявление типа содержимого, о котором мы говорили, а затем две пары символов возврата каретки и перевода строки. Это добавляет пустую строку после заголовка, указывая на конец заголовков HTTP и начало тела сообщения. Третья строка выводит строку «Hello, World.». На этом всё.
Откройте любой удобный браузер и перейдите по адресу
http://www.example.com/cgi-bin/first.plили по адресу, где находится ваш файл. В окне браузера появится одна строка Hello, World.. Это не слишком впечатляет, но если вам удалось добиться такого результата, то, скорее всего, вы сможете заставить работать и почти всё остальное.
Но всё равно не работает!
При попытке открыть программу CGI в интернете вы можете увидеть в браузере один из четырех вариантов:
- Вывод программы CGI
- Отлично! Значит, всё работает. Если вывод верный, но браузер обрабатывает его неправильно, убедитесь, что в программе CGI задан правильный
Content-Type. - Исходный код программы CGI или сообщение «Метод POST не разрешен»
- Это означает, что Apache настроен на обработку программы CGI неправильно. Перечитайте раздел о настройке Apache и постарайтесь найти, что вы упустили.
- Сообщение, начинающееся со слова «Запрещено»
- Это означает, что возникла проблема с разрешениями. Проверьте журнал ошибок Apache и раздел ниже о разрешениях файлов.
- Сообщение «Внутренняя ошибка сервера»
- Если проверить журнал ошибок Apache, вы, скорее всего, увидите сообщение «Преждевременный конец заголовков скрипта», возможно, вместе с сообщением об ошибке, сформированным вашей программой CGI. В этом случае проверьте все разделы ниже, чтобы выяснить, что мешает программе CGI выводить правильные заголовки HTTP.
Разрешения файлов
Помните, что сервер работает не от вашего имени. То есть при запуске сервер работает с разрешениями непривилегированного пользователя — обычно nobody или www — и поэтому ему потребуются дополнительные разрешения для выполнения файлов, принадлежащих вам. Обычно, чтобы предоставить файлу достаточные разрешения для выполнения пользователем nobody, нужно разрешить выполнение файла всем пользователям:
chmod a+x first.pl
Кроме того, если программа читает другие файлы или записывает в них данные, этим файлам также нужны соответствующие разрешения.
Информация о путях и окружение
При запуске программы из командной строки оболочка получает от вас определенную информацию, даже если вы об этом не задумываетесь. Например, у вас есть PATH, который сообщает оболочке, где искать файлы, на которые вы ссылаетесь.
Когда программа запускается веб-сервером как программа CGI, у нее может не быть того же PATH. Полный путь необходимо указывать для всех программ, которые вы запускаете из программы CGI (например, sendmail), чтобы оболочка могла найти их при попытке выполнить вашу программу CGI.
Часто это касается пути к интерпретатору скриптов (нередко perl), указанному в первой строке программы CGI, которая выглядит примерно так:
#!/usr/bin/perl
Убедитесь, что это действительно путь к интерпретатору.
Отсутствующие переменные окружения
Если программа CGI зависит от нестандартных переменных окружения, необходимо убедиться, что Apache передает эти переменные.
Если в окружении отсутствуют заголовки HTTP, убедитесь, что они отформатированы согласно разделу 4.2 RFC 2616: имена заголовков должны начинаться с буквы, за которой могут следовать только буквы, цифры или дефис. Любой заголовок, не соответствующий этому правилу, будет молча отброшен.
Ошибки программы
Чаще всего программа CGI не работает из-за ошибки в самой программе. Это особенно верно после того, как вы освоитесь с CGI и перестанете допускать две описанные выше ошибки. Прежде всего, убедитесь, что программа запускается из командной строки, и только потом проверяйте ее через веб-сервер. Например, попробуйте выполнить:
cd /usr/local/apache2/cgi-bin ./first.pl
(Не вызывайте интерпретатор perl. Оболочка и Apache должны найти интерпретатор по информации о пути в первой строке скрипта.)
Первыми данными, выводимыми программой, должны быть заголовки HTTP, включая Content-Type, за которыми следует пустая строка. Если вы видите что-то другое, при запуске через сервер Apache вернет ошибку Premature end of script headers. Подробнее см. выше в разделе «Написание программы CGI».
Журналы ошибок
Журналы ошибок — ваши помощники. Любая проблема оставляет сообщение в журнале ошибок. Всегда сначала проверяйте его. Если хостинг-провайдер не предоставляет доступ к журналу ошибок, вероятно, вам стоит разместить сайт в другом месте. Научитесь читать журналы ошибок — и вы обнаружите, что почти все проблемы можно быстро выявить и решить.
Suexec
Вспомогательная программа suexec позволяет запускать программы CGI с разными пользовательскими разрешениями в зависимости от виртуального хоста или домашнего каталога пользователя, где они находятся. Suexec строго проверяет разрешения, и любое нарушение этих проверок приведет к сбою программ CGI с ошибкой Premature end of script headers.
Чтобы проверить, используется ли suexec, выполните apachectl -V и найдите расположение SUEXEC_BIN. Если при запуске Apache обнаружит там исполняемый файл suexec, suexec будет активирован.
Если вы не понимаете suexec полностью, не используйте его. Чтобы отключить suexec, просто удалите (или переименуйте) исполняемый файл suexec, на который указывает SUEXEC_BIN, а затем перезапустите сервер. Если после прочтения информации о suexec вы всё же хотите его использовать, выполните suexec -V, чтобы узнать расположение файла журнала suexec, и воспользуйтесь этим журналом, чтобы выяснить, какое правило вы нарушаете.
Что происходит за кулисами?
По мере того как вы будете осваивать программирование CGI, вам пригодится более подробное понимание того, что происходит за кулисами. В частности, того, как браузер и сервер взаимодействуют друг с другом. Ведь хотя написать программу, которая выводит «Hello, World.», довольно просто, сама по себе она не слишком полезна.
Переменные окружения
Переменные окружения — это значения, которые сопровождают вас при работе за компьютером. Это полезные параметры, например путь (по которому компьютер ищет файл, реализующий команду, когда вы вводите ее), имя пользователя, тип терминала и так далее. Чтобы увидеть полный список обычных переменных окружения, введите env в командной строке.
Во время транзакции CGI сервер и браузер также задают переменные окружения, чтобы обмениваться информацией. К ним относятся тип браузера (Netscape, IE, Lynx), тип сервера (Apache, IIS, WebSite), имя запускаемой программы CGI и так далее.
Эти переменные доступны разработчику CGI и составляют половину механизма взаимодействия клиента и сервера. Полный список обязательных переменных приведен в документе RFC по Common Gateway Interface.
Эта простая программа CGI на Perl отображает все передаваемые переменные окружения. Две похожие программы входят в каталог cgi-bin дистрибутива Apache. Обратите внимание: одни переменные обязательны, а другие — необязательны, поэтому вы можете увидеть переменные, которых нет в официальном списке. Кроме того, Apache предоставляет множество способов добавить собственные переменные окружения к основным переменным, заданным по умолчанию.
#!/usr/bin/perl
use strict;
use warnings;
print "Content-type: text/html\n\n";
foreach my $key (keys %ENV) {
print "$key --> $ENV{$key}<br>";
} STDIN и STDOUT
Другой обмен данными между сервером и клиентом происходит через стандартный ввод (STDIN) и стандартный вывод (STDOUT). В обычной ситуации STDIN означает клавиатуру или файл, с которым работает программа, а STDOUT обычно означает консоль или экран.
Когда вы POST веб-форму программе CGI, данные формы объединяются в специальный формат и передаются программе CGI через STDIN. Затем программа может обрабатывать эти данные так, словно они поступают с клавиатуры или из файла
«Специальный формат» очень прост. Имя поля и его значение соединяются знаком равенства (=), а пары значений — амперсандом (&). Неудобные символы, например пробелы, амперсанды и знаки равенства, преобразуются в соответствующие шестнадцатеричные значения, чтобы не мешать обработке. Вся строка данных может выглядеть примерно так:
name=Rich%20Bowen&city=Lexington&state=KY&sidekick=Squirrel%20MonkeyИногда вы также увидите строку такого типа, добавленную к URL. В этом случае сервер помещает эту строку в переменную окружения с именем QUERY_STRING. Такой запрос называется запросом GET. В HTML-форме с помощью атрибута METHOD тега FORM указывается, будет ли для передачи данных использоваться GET или POST.
Затем программа должна разделить эту строку на полезные данные. К счастью, существуют библиотеки и модули, которые помогают обрабатывать эти данные и выполнять другие задачи, связанные с вашей программой CGI.
Модули и библиотеки CGI
При написании программ CGI стоит использовать библиотеку кода или модуль, который возьмет на себя большую часть рутинной работы. Это уменьшает количество ошибок и ускоряет разработку.
Если вы пишете программы CGI на Perl, модули доступны на CPAN. Самый популярный модуль для этой цели — CGI.pm. Можно также рассмотреть CGI::Lite, который реализует минимальный набор функций, достаточный для большинства программ.
Для написания программ CGI на C можно выбрать один из нескольких вариантов. Один из них — библиотека CGIC, доступная по адресу https://web.mit.edu/wwwdev/www/cgic.html.
Дополнительная информация
Актуальная спецификация CGI доступна в документе RFC по Common Gateway Interface.
Задавая вопрос о проблеме с CGI в списке рассылки или группе новостей, обязательно предоставьте достаточно информации: что произошло, чего вы ожидали и чем фактический результат отличался от ожидаемого, какой сервер вы используете, на каком языке написана программа CGI и, если возможно, фрагмент кода, вызывающий проблему. Это значительно упростит ее поиск.
Обратите внимание: вопросы о проблемах с CGI никогда не следует публиковать в базе ошибок Apache, если только вы не уверены, что обнаружили проблему в исходном коде Apache.
© 2018 The Apache Software Foundation
Licensed under the Apache License, Version 2.0.
https://httpd.apache.org/docs/2.4/en/howto/cgi.html