Mercurial > pub > Impl
diff lib/IMPL/Web/Handler/RestController.pm @ 407:c6e90e02dd17 ref20150831
renamed Lib->lib
author | cin |
---|---|
date | Fri, 04 Sep 2015 19:40:23 +0300 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/IMPL/Web/Handler/RestController.pm Fri Sep 04 19:40:23 2015 +0300 @@ -0,0 +1,148 @@ +package IMPL::Web::Handler::RestController; +use strict; + +use IMPL::Const qw(:prop); +use IMPL::declare { + require => { + Locator => 'IMPL::Web::AutoLocator', + ResourceInterface => 'IMPL::Web::Application::ResourceInterface', + Exception => 'IMPL::Exception', + ArgumentExecption => '-IMPL::InvalidArgumentException', + NotFoundException => 'IMPL::Web::NotFoundException', + Loader => 'IMPL::Code::Loader' + }, + base => { + 'IMPL::Object' => undef, + 'IMPL::Object::Autofill' => '@_', + 'IMPL::Object::Serializable' => undef + }, + props => [ + resourceFactory => PROP_RO, + trailingSlash => PROP_RO + ] +}; + +sub CTOR { + my ($this) = @_; + + die ArgumentException->new(resourceFactory => "A web-resource is required") + unless $this->resourceFactory; + #unless eval { $this->resourceFacotry->isa(ResourceInterface) }; + +} + +sub GetResourcePath { + my ($this,$action) = @_; + + my $pathInfo = $action->pathInfo; + my @segments; + + if (length $pathInfo) { + + @segments = split(/\//, $pathInfo, $this->trailingSlash ? -1 : 0); + + # remove first segment if it is empty + shift @segments if @segments && length($segments[0]) == 0; + } + + return @segments; +} + + +sub Invoke { + my ($this,$request) = @_; + + my $method = $request->requestMethod; + + my @segments = $this->GetResourcePath($request); + + my $factory = $this->resourceFactory; + + $factory = Loader->default->Require($factory) + unless ref($factory) || eval { $factory->can('new') }; + + my $res = $factory->new( + id => 'root', + request => $request, + location => Locator->new(base => $request->application->baseUrl), + ); + + while(@segments) { + my $id = shift @segments; + $res = $res->FetchChildResource($id); + } + + $res = $res->InvokeHttpVerb($method); +} + +1; + +__END__ + +=pod + +=head1 NAME + +C<IMPL::Web::Handler::RestController> - Обрабатывает C<HTTP> запрос передавая +его соответствующему ресурсу. + +=head1 SYNOPSIS + +Используется в конфигурации приложения как элемент цепочки обработчиков. +Как правило располагается на самом верхнем уровне. + +=begin code xml + + <handlers type="ARRAY"> + <item type="IMPL::Web::Handler::RestController"> + <resourceFactory>My::App::Web::RootResource</resourceFactory> + </item> + <item type="IMPL::Web::Handler::JSONView" /> + <item type="IMPL::Web::Handler::SecureCookie" /> + <item type="IMPL::Web::Handler::ErrorHandler" /> + </handlers> + +=end code xml + + +=head1 DESCRIPTION + +Использует C<PATH_INFO> для определения нужного ресурса, затем предает +найденному ресурсу управление для обработки запроса. + +Если ресурс не найден, то возникает исключение C<IMPL::Web::NotFoundException>. + +Для определения нужного ресурса контроллер разбивает C<PATH_INFO> на фрагменты +и использует каждый фрагмент для получения дочернего ресурса начиная с корневого. +Для чего используется метод +C<< IMPL::Web::Application::ResourceInterface->FetchChildResource($childId) >>. + +Дерево ресурсов сущестувет независимо от обрабатываемого запроса, однако оно +может полностью или частично загружаться в начале обработки запроса и +освобождаться по окончании обработки запроса. Поэтому при получении дочерних +ресурсов не участвует C<HTTP> запрос, он адресуется только последнему ресурсу. + +=begin text + +/music/audio.mp3 -> ['music','audio.mp3'] + +=end text + +=head1 MEMEBERS + +=head2 C<[get]resourceFactory> + +Фабрика для создания корневого ресурса приложения, полученный ресурс должен +реализовывать интерфейс C<IMPL::Web::Application::ResourceInterface>. + +Фабрика может сохранять ссылку на корневой ресурс и каждый раз не создавать +его, а возвращать уже существующий. Это вполне оправдано, если хранение +дерева ресурсов требует меньше ресурсов, чем его создание и при этом приложение +остается в памяти между C<HTTP> запросами. + +=head2 C<[get]trailingSlash> + +Если данная переменная имеет значение C<true>, то слеш в конце пути к ресурсу +будет интерпретироваться, как дочерний ресурс с пустым идентификатором. + +=cut \ No newline at end of file