Mercurial > pub > Impl
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 |