Search     or:     and:
 LINUX 
 Language 
 Kernel 
 Package 
 Book 
 Test 
 OS 
 Forum 
 iakovlev.org 
 Books
  Краткое описание
 Linux
 W. R. Стивенс TCP 
 W. R. Стивенс IPC 
 A.Rubini-J.Corbet 
 K. Bauer 
 Gary V. Vaughan 
 Д Вилер 
 В. Сталлинг 
 Pramode C.E. 
 Steve Pate 
 William Gropp 
 K.A.Robbins 
 С Бекман 
 Р Стивенс 
 Ethereal 
 Cluster 
 Languages
 C
 Perl
 M.Pilgrim 
 А.Фролов 
 Mendel Cooper 
 М Перри 
 Kernel
 C.S. Rodriguez 
 Robert Love 
 Daniel Bovet 
 Д Джеф 
 Максвелл 
 G. Kroah-Hartman 
 B. Hansen 
NEWS
Последние статьи :
  Тренажёр 16.01   
  Эльбрус 05.12   
  Алгоритмы 12.04   
  Rust 07.11   
  Go 25.12   
  EXT4 10.11   
  FS benchmark 15.09   
  Сетунь 23.07   
  Trees 25.06   
  Apache 03.02   
 
TOP 20
 MINIX...3058 
 Solaris...2934 
 LD...2907 
 Linux Kernel 2.6...2488 
 William Gropp...2187 
 Rodriguez 6...2018 
 C++ Templates 3...1947 
 Trees...1941 
 Kamran Husain...1868 
 Secure Programming for Li...1795 
 Максвелл 5...1712 
 DevFS...1696 
 Part 3...1686 
 Stein-MacEachern-> Час...1635 
 Go Web ...1629 
 Ethreal 4...1620 
 Стивенс 9...1609 
 Arrays...1609 
 Максвелл 1...1598 
 FAQ...1540 
 
  01.01.2024 : 3621733 посещений 

iakovlev.org
 

Chapter 3 - Архитектура Apache Module API

Apache API написаны из условия , что Apache - это HTTP-server, который работает как демон . Поскольку он HTTP-server, он должен слушать входящие TCP/IP-пакеты,распознавть URI , парсить их в имена файлов и скриптов и возвращать контент на клиентский броузер . Модули играют активную роль во всех этих аспектах . Апач устроен так , что новый запрос может инициировать новый процесс прежде , чем закончится процесс , обслуживающий предыдущий запрос . Используется мультипроцессорная модель с наличием множества серверов , каждый из которых может обслуживать множество клиентов . На Win32-модели в большей степени используется мультитрэдинговая модель . HTTP Protocol Пример запроса , который клиент посылает на сервер : GET /very/important/document.html HTTP/1.1 Host: www.modperl.com 1-я строка состоит из 3-х компонентов : GET - метод запроса (GET,POST,PUT,HEAD,DELETE) /very/important/document.html - URI документа HTTP/1.1 - тип протокола ; 1.1 отличается от 1.0 наличием виртуальных хостов и кэшированием 2-я строка состоит из имени хоста Дальше идут серия строк , каждая из которых состоит из хидера , двоеточия и расшифровки : GET /news.html HTTP/1.1 Connection: Keep-Alive User-Agent: Mozilla/4.05 [en] (X11; I; Linux 2.0.33 i686) Host: www.modperl.com Referer: http://www.modperl.com/index.html If-Modified-Since: Tue, 24 Feb 1998 11:19:03 GMT Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */* Accept-Language: en Accept-Charset: iso-8859-1,*,utf-8 В этом примере приведены большинство HTTP-хидеров , которые нужно знать . Например , хидер Connection говорит о том , что TCP-коннект будет открытым до окончания запроса. В User-Agent указывается тип броузера . Host - имя хоста , откуда пришел запрос . Referer - URI ссылаемого документа . If-Modified-Since - дата кэширования документа на клиенте . В зависимости от него сервер может не возвращать контент . Accept - список MIME-типов , которые поддерживаются броузером . Если тип запроса POST , могут быть другие дополнительные поля .
 
 Apache Life Cycle
 
 Апачевский цикл показан на картинке .
 Он стартует , инициализирует , создает несколько копий самого себя любимого ,
 после чего запускается цикл , в котором проверяются входящие запросы .
 Модули регистрируют хэндлеры , которые вызываются в нужное время .
 Порядок вызова зависит от того , в каком порядке загружены модули . 
 
 
  Server Startup 
 
  При старте апач парсит командную строку и конфиг файлы .
 Конфиги могут включать директивы , реализованные в модулях .
 В каждом модуле есть init-процедура , которая передает от сервера информацию 
 в структуру server_rec . 
 Ее полями являются ServerName, Port,ServerAdmin.
 Модули на C имеют дополнительный указатель на область памяти "resource pool".
 В перловом модуле , на этапе инициализации , могут быть применены 
 директивы PerlRequire и PerlModule.
 Далее апач создает несколько процессов , которые будут обслуживать 
 входящие запросы .  
 Эти процессы устанавливают собственные  user и group IDs для нерутовых пользователей 
 ("nobody" или "guest"). 
 Родительский рутовый процесс обслуживает эту очередь дочерних процессов .
  Каждый дочерний процесс , обслужив положенную порцию процессов , 
  равную MaxRequestsPerChild ,
 прекращает свое существование . При этом в соответствующем модуле будет 
 вызываться хэндлер child_exit ,
 где могут комититься незавершенные транзакции , закрываться файлы и т.д.
 Перловые модули при этом могут вызвать хэндлер , который может быть прописан как
 PerlChildExitHandler в конфиге .
 
 Основной цикл
 
  Он показан на следующей картинке .
 
  Решения принимает апач , но свою лепту могут вносить модули .
 Можно выделить 8 основных моментов : 
  
 1. Что это ? (трансляция URI )
  URI может ссылаться на физический файл , на документ , генерируемый на лету внешним скриптом ,
 или на документ , генерируемый модулем . 
 2. Откуда пришел запрос ?
 3. От кого пришел запрос ?
 4. Кому разрешено выполнять этот запрос ? 
  В конфигурации могут быть перечислены файлы , доступ к которым имеют далеко не все .
 5. Тип документа ? (MIME)
 6. Кто генерирует контент для этого документа ?
       Апач может принять решение о том , что генерация контента отдается внешнему модулю .
 7. Кто и куда пишет лог ?
       Вообще-то логами занимается сам апч , но может быть принято решение о передаче внешнему
       модулю прав на специальное логирование , например в базу данных . 
 8. Кто двери закрывает ?
       После обработки запроса модули могут выполнять различные телодвижения .
 
 
 
 
 Внутренние запросы апача 
 
  Они могут быть сгенерированы апачем при обработке ошибок или в других ситуациях .
 При этом возвращаемый контент заменяется на другой . 
 С помощью функции internal_redirect() апач прекращает обработку текущего запроса и передает
 управление другому процессу . При возникновении ошибок срабатывает  ErrorDocument ,
 при этом возвращается спциальный HTML-file или CGI-script .
 В некоторых ситуациях вызываются функции lookup_file() или lookup_uri() .
 Они генерят запрос , как будто он пришел снаружи .
 
  Некоторые стандартные апач-модули используют т.н.  environment variables .
 mod_cgi устанавливает их для хранения информации о запросе .
 mod_include использует их при генерации HTML . 
 mod_log_config включает информацию о них в лог-файл .
 mod_access принимает решение о разрешении доступа на их основе.
 Их можно модифицировать с помощью PassEnv, SetEnv, UnsetEnv директив 
 которые реализованы в модуле mod_env . 
 Pass-Env может передавать их процессу .
 Эти переменные также можно выставлять в конфиге с помощью директив <Directory> и <Location> : 
 	PerlPassEnv     ORGANIZATION
 	PerlSetEnv      TMPDIR  /usr/tmp
 	<Location /stage/upload>
 	PerlSetEnv      TMPDIR /tmp/staging
 	</Location>
 
  При старте апач копирует  environment variables во внутреннюю таблицу .
 После чего загружаемые модули читают из нее эти переменные , а не из конфигов .
 Perl и C API позволяют модифицировать содержимое этой таблицы .
 
 
 
 Handler API
 
  При вызове хэндлера апач передает ему информацию о текущей транзакции и конфигурации сервера ,
 который должен быть возвращен апачу назад . 
 В Perl API определение хэндлера такое : 
 	sub  {
 	my $r = shift;
 	# do something
 	return ;
 	}
 Хэндлер может быть вызван в любой момент . Он возвращает единственный аргумент , являющийся
 ссылкой на обьект запроса . Этот обьект есть структура и называется request record,
 включающая в себя всю необходимую информацию о транзакции .
 Этот обьект хранится в перл-переменной , называемой  $r. 
 В особом случае хэндлер может вернуть и 2 аргумента ($$) , где первым аргументом будет
 имя пакета . Это позволяет перловым хэндлерам использовать возможности наследования и полиморфизма .
 Такие хэндлеры называются "method handlers" : 
 	sub  ($$) {
 	my $class = shift;
 	my $r = shift;
 	# do something
 	return ;
 	}
 
  Хэндлеры на C API декларируются так :
    static int  (request_rec* r) {
    /* do something */
    return ;
 	}
 
  В отличие от Perl API, где все хэндлеры имеют одинаковую структуру , C API handlers 
 могут иметь другую форму .Например , child_init()-handler выглядит так :
 	static void child_init (server_rec *s, pool *p) {
 	/* do something */
 	}
 
 
 
 Status Codes 
 Каждый хэндлер должен возвращать статус-код , который ассоциируется с символической констаной .
 Для перла они определены в модуле Apache::Constants и для си в httpd.h-include .
 
Code
Constant (Nickname)
Описание

2XX Codes--Success

200
HTTP_OK
(DOCUMENT_FOLLOWS)
URI был найден и контент определен.
201
HTTP_CREATED
URI создан с помощью PUT.
202
HTTP_ACCEPTED
Доступ к запросу
203
HTTP_NON_AUTHORITATIVE
Ошибка авторизации
204
HTTP_NO_CONTENT
Запрос правильный , но контент нулевой
206
HTTP_PARTIAL_CONTENT
(PARTIAL_CONTENT)
Часть контента документа

3XX Codes--Multiple Choices Available

300
HTTP_MULTIPLE_CHOICES
(MULTIPLE_CHOICES)
Несколько документов
301
HTTP_MOVED_PERMANENTLY
(MOVED)
Документ перемещен на другой URI.
302
HTTP_MOVED_TEMPORARILY
(REDIRECT)
Документ временно перемещен на другой URI.
304
HTTP_NOT_MODIFIED
(USE_LOCAL_COPY)
Документ закэширован , обновлять не надо .

4XX Codes--Client-Side Errors

400
HTTP_BAD_REQUEST
(BAD_REQUEST)
Запрос с ошибкой
401
HTTP_UNAUTHORIZED
(AUTH_REQUIRED)
Неправильно авторизованный клиент
402
HTTP_PAYMENT_REQUIRED
Деньги вперед
403
HTTP_FORBIDDEN
(FORBIDDEN)
Доступ к документу для клиента запрещен
404
HTTP_NOT_FOUND
(NOT_FOUND)
Запрашиваемый документ не существует
405
HTTP_METHOD_NOT_ALLOWED
(METHOD_NOT_ALLOWED)
Метод (e.g., PUT) не разрешен
406
HTTP_NOT_ACCEPTABLE
Запрос недоступен
407
HTTP_PROXY_AUTHENTICATION_REQUIRED
Proxy authentication.
408
HTTP_REQUEST_TIME_OUT
Клиент ждет
410
HTTP_GONE
Документа нет.
412
HTTP_PRECONDITION_FAILED
(PRECONDITION_FAILED)
Документ не найден
413
HTTP_REQUEST_ENTITY_TOO_LARGE
Слишком большой обьем данных от клиента
414
HTTP_REQUEST_URI_TOO_LARGE
Слишком длинный URI
415
HTTP_UNSUPPORTED_MEDIA_TYPE
MIME type не поддерживается

5XX Codes--Server-Side Errors

500
HTTP_INTERNAL_SERVER_ERROR
(SERVER_ERROR)
Неопределенная ошибка
501
HTTP_NOT_IMPLEMENTED
(NOT_IMPLEMENTED)
Не реализовано
502
HTTP_BAD_GATEWAY
(BAD_GATEWAY)
Ошибка proxy
503
HTTP_SERVICE_UNAVAILABLE
Сервер в дауне
504
HTTP_GATEWAY_TIME_OUT
proxy - time out
505
HTTP_VERSION_NOT_SUPPORTED
Версия HTTP не поддерживается
506
HTTP_VARIANT_ALSO_VARIES
(VARIANT_ALSO_VARIES)
Документ представлен несколькими вариантами
Модуль Apache::Constants экспортирует не все HTTP_* имена , и при попытке вызвать некое HTTP_* имя можно получить "Undefined subroutine". Кроме статус-кодов из этой таблицы , апач может иметь дополнительно свои внутренние : OK - говорит о том , что хэндлер был успешным (не путать с HTTP_OK) DECLINED - хэндлер отказывается обрабатывать запрос . DONE - апач немедленно закрывает коннект с клиентом
  Запуск хэндлера
  Perl и C API по-разному запускают хэндлеры . 
 Для C API хэндлер определяется с помошью указателя на его функцию 
 в таблице внутри откомпилированного модуля .
 В Perl API хэндлер запускается с помощью директив конфига 
 или внутри .htaccess
 Для реализации хэндлера в перл нужно написать модуль .pm и добавить в конфиг
 директиву Perl*Handler.
 Всего в Perl API существуют 15 директив : 
 PerlTransHandler,PerlAccessHandler,PerlLogHandler, и т.д.
 В перловом модуле нужно создать подпрограмму с именем handler().
 Apache Perl модули обычно живут внтри Apache::package namespace. 
 Обычно Apache Perl module выглядит так :
 	package Apache::Foo;
 	use strict;
 	use Apache::constants qw(:common);
 	sub handler {
 	my $r = shift;
 	# do something
 	return ;
 	}
 
 Его декларация в конфиге :
 	 Apache::Foo
 
 Можно написать целый список :
 	Apache::Foo Apache::Bar Apache::Baz
 	Apache::Wiz Apache::Waz
 
 Функция хэндлера не обязана называться handler(), 
 если она например называется do_something(), то:
 	 Apache::Foo::do_something
  
 Perl*Handler не обеспечивает автоматическую загрузку хэндлера .
 Нужно использовать директиву PerlModule в конфиге :
 	PerlModule Apache::Foo
 	Apache::Foo::do_something
 Если модуль не загружается ,  возникает ошибка , которую можно найти в логе .
 
 С помощью Perl*Handlers можно использовать анонимные процедуры :
 	PerlChildInitHandler "sub { warn qq(child $$ starting\n) }"
 
 
 Perl API Configuration Directives 
 
 Здесь представлен список конфигурационных директив Perl API . 
 	 PerlRequire 
 	 PerlModule 
  Эти директивы используются для загрузки модулей с диска .	
 На перле аналогом является оператор require . 
 Конфиг-строка
 	PerlModule Apache::Plotter
 соответствует коду на перл :
 	require Apache::Plotter;
 	use Apache::Plotter ();
 Для директивы  PerlRequire нужно указывать абсолютный путь :
 	PerlRequire /opt/www/lib/directory_colorizer.pl
 	PerlRequire scripts/delete_temporary_files.pl
 и то же самое на перле:
 	require '/opt/www/lib/directory_colorizer.pl';
 	require 'scripts/delete_temporary_files.pl';
 Обе этих директивы возможны со списком модулей :
 	PerlModule CGI LWP::Simple Apache::Plotter
 	PerlRequire scripts/startup.pl scripts/config.pl
 	
 Старт апача с рутовыми правами , доступ к конфигам и скриптам таит в себе опасность .
 Директива PerlOpmask и PERL_ OPMASK_DEFAULT предназначена 
 для снижения возможного риска .
 
 PerlChildInitHandler 
   Этот хэндлер срабатывает каждый раз , когда на апаче форкается дочерний процесс .
 Пример : 
 	PerlChildInitHandler Apache::DBLogin
 Эта директива может находиться в конфиге внутри секции виртуального хоста , 
 но не внутри <Directory>, <Location>,или <Files> 
 или .htaccess . 
 
 PerlPostReadRequestHandler 
   Этот хэндлер срабатывает каждый раз , когда апач получает запрос .
 Удобное место для обработки старта транзакции .  
 Пример :
 	PerlPostReadRequestHandler Apache::StartTimer
 Порядок размещения этой директивы аналогично предыдущей .
  
 PerlTransHandler 
    Срабатывает тогда , когда происходит перевод URI в имя файла 
 Пример :
 	PerlTransHandler Apache::AdBlocker
 
 Хэндлеры :
 PerlHeaderParserHandler 
 PerlAccessHandler 
 PerlAuthenHandler 
 PerlAuthzHandler 
 PerlTypeHandler 
 PerlFixupHandler 
 PerlHandler 
 PerlLogHandler 
 PerlCleanupHandler 
 PerlChildExitHandler 
 PerlFreshRestart 
 PerlDispatchHandler 
 PerlRestartHandler 
 
 
Оставьте свой комментарий !

Ваше имя:
Комментарий:
Оба поля являются обязательными

 Автор  Комментарий к данной статье