Mercurial > pub > Impl
view lib/IMPL/Web/Handler/RestController.pm @ 417:3ed0c58e9da3 ref20150831
working on di container, tests
author | cin |
---|---|
date | Mon, 02 Nov 2015 01:56:53 +0300 |
parents | c6e90e02dd17 |
children |
line wrap: on
line source
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