Для недавнего проекта я написал собственный обработчик конфигурации, в котором реализован новый параметр конфигурации ResourceURI. Это позволило мне поместить строки конфигурации в httpd.conf следующим образом:
ResourceURI SomeResource GET,POST,DELETE "^/...$"
Три аргумента - это имя класса моего ресурса, список методов HTTP, на которые ресурс может ответить, и регулярное выражение, соответствующее URI для ресурса.
Пользовательский класс конфигурации заменяет каждую из этих строк следующим блоком:
PerlModule Handler::{resource class}
PerlModule Resource::{resource class}
<Location ~ "{uri regex}">
Order allow,deny
Allow from all
<LimitExcept {allowed methods}>
Order deny,allow
Deny from all
</LimitExcept>
SetHandler modperl
PerlHandler Handler
PerlSetVar Resource {resource class}
</Location>
Это заботится о загрузке моих классов, позволяет Apache отклонять недопустимые методы, устанавливает флаг, указывающий, к какому ресурсу направить, и передает все запросы через мою функцию Handler :: handler ().
package Handler;
sub handler {
my $r = shift;
my $resource_class = 'Resource::' . $r->dir_config('Resource');
my $handler_class = 'Handler::' . $r->dir_config('Resource');
my $resource = $resource_class->new($r, $r->uri);
return Apache2::Const::HTTP_NOT_FOUND unless $resource;
my $method = $r->method();
return Apache2::Const::HTTP_NOT_IMPLEMENTED
unless $handler_class->can($method);
return $handler_class->$method($r, $resource);
}
Теперь вам просто нужно реализовать классы Resource :: * с помощью логики ресурсов (включая способ форматирования представлений) и классы Handler :: * с методами с именами GET, HEAD, POST и т. Д., Чтобы они использовали $ r и $ ресурс для обработки запросов.
Для каждого нового ресурса, который вам нужен, вы добавляете одну строку конфигурации, реализуете один класс Handler (который, как я обнаружил, часто может быть почти пустым модулем, унаследованным от базового базового класса), и реализуете один класс Resource, который содержит основная часть кода. Я также обнаружил, что мне часто нужно создавать один объект ресурса в контексте обработки запроса на другой ресурс; Вот почему мои конструкторы ресурсов принимают отдельный аргумент для URI вместо того, чтобы просто получить URI из $ r. Если я нахожусь в Resource :: Foo и мне нужен объект Resource :: Bar, я могу сказать, что мой $ bar = Resource :: Bar-> new ($ r, '/ bars / 1234'); который создает объект Bar, используя тот же URI, который использовал бы клиент.