comparison 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
comparison
equal deleted inserted replaced
406:f23fcb19d3c1 407:c6e90e02dd17
1 package IMPL::Web::Handler::RestController;
2 use strict;
3
4 use IMPL::Const qw(:prop);
5 use IMPL::declare {
6 require => {
7 Locator => 'IMPL::Web::AutoLocator',
8 ResourceInterface => 'IMPL::Web::Application::ResourceInterface',
9 Exception => 'IMPL::Exception',
10 ArgumentExecption => '-IMPL::InvalidArgumentException',
11 NotFoundException => 'IMPL::Web::NotFoundException',
12 Loader => 'IMPL::Code::Loader'
13 },
14 base => {
15 'IMPL::Object' => undef,
16 'IMPL::Object::Autofill' => '@_',
17 'IMPL::Object::Serializable' => undef
18 },
19 props => [
20 resourceFactory => PROP_RO,
21 trailingSlash => PROP_RO
22 ]
23 };
24
25 sub CTOR {
26 my ($this) = @_;
27
28 die ArgumentException->new(resourceFactory => "A web-resource is required")
29 unless $this->resourceFactory;
30 #unless eval { $this->resourceFacotry->isa(ResourceInterface) };
31
32 }
33
34 sub GetResourcePath {
35 my ($this,$action) = @_;
36
37 my $pathInfo = $action->pathInfo;
38 my @segments;
39
40 if (length $pathInfo) {
41
42 @segments = split(/\//, $pathInfo, $this->trailingSlash ? -1 : 0);
43
44 # remove first segment if it is empty
45 shift @segments if @segments && length($segments[0]) == 0;
46 }
47
48 return @segments;
49 }
50
51
52 sub Invoke {
53 my ($this,$request) = @_;
54
55 my $method = $request->requestMethod;
56
57 my @segments = $this->GetResourcePath($request);
58
59 my $factory = $this->resourceFactory;
60
61 $factory = Loader->default->Require($factory)
62 unless ref($factory) || eval { $factory->can('new') };
63
64 my $res = $factory->new(
65 id => 'root',
66 request => $request,
67 location => Locator->new(base => $request->application->baseUrl),
68 );
69
70 while(@segments) {
71 my $id = shift @segments;
72 $res = $res->FetchChildResource($id);
73 }
74
75 $res = $res->InvokeHttpVerb($method);
76 }
77
78 1;
79
80 __END__
81
82 =pod
83
84 =head1 NAME
85
86 C<IMPL::Web::Handler::RestController> - Обрабатывает C<HTTP> запрос передавая
87 его соответствующему ресурсу.
88
89 =head1 SYNOPSIS
90
91 Используется в конфигурации приложения как элемент цепочки обработчиков.
92 Как правило располагается на самом верхнем уровне.
93
94 =begin code xml
95
96 <handlers type="ARRAY">
97 <item type="IMPL::Web::Handler::RestController">
98 <resourceFactory>My::App::Web::RootResource</resourceFactory>
99 </item>
100 <item type="IMPL::Web::Handler::JSONView" />
101 <item type="IMPL::Web::Handler::SecureCookie" />
102 <item type="IMPL::Web::Handler::ErrorHandler" />
103 </handlers>
104
105 =end code xml
106
107
108 =head1 DESCRIPTION
109
110 Использует C<PATH_INFO> для определения нужного ресурса, затем предает
111 найденному ресурсу управление для обработки запроса.
112
113 Если ресурс не найден, то возникает исключение C<IMPL::Web::NotFoundException>.
114
115 Для определения нужного ресурса контроллер разбивает C<PATH_INFO> на фрагменты
116 и использует каждый фрагмент для получения дочернего ресурса начиная с корневого.
117 Для чего используется метод
118 C<< IMPL::Web::Application::ResourceInterface->FetchChildResource($childId) >>.
119
120 Дерево ресурсов сущестувет независимо от обрабатываемого запроса, однако оно
121 может полностью или частично загружаться в начале обработки запроса и
122 освобождаться по окончании обработки запроса. Поэтому при получении дочерних
123 ресурсов не участвует C<HTTP> запрос, он адресуется только последнему ресурсу.
124
125 =begin text
126
127 /music/audio.mp3 -> ['music','audio.mp3']
128
129 =end text
130
131 =head1 MEMEBERS
132
133 =head2 C<[get]resourceFactory>
134
135 Фабрика для создания корневого ресурса приложения, полученный ресурс должен
136 реализовывать интерфейс C<IMPL::Web::Application::ResourceInterface>.
137
138 Фабрика может сохранять ссылку на корневой ресурс и каждый раз не создавать
139 его, а возвращать уже существующий. Это вполне оправдано, если хранение
140 дерева ресурсов требует меньше ресурсов, чем его создание и при этом приложение
141 остается в памяти между C<HTTP> запросами.
142
143 =head2 C<[get]trailingSlash>
144
145 Если данная переменная имеет значение C<true>, то слеш в конце пути к ресурсу
146 будет интерпретироваться, как дочерний ресурс с пустым идентификатором.
147
148 =cut