Mercurial > pub > Impl
comparison Lib/IMPL/Web/Application/RestResource.pm @ 197:6b1dda998839
Added IMPL::declare, IMPL::require, to simplify module definitions
IMPL::Transform now admires object inheritance while searching for the transformation
Added HTTP some exceptions
IMPL::Web::Application::RestResource almost implemented
author | sergey |
---|---|
date | Thu, 19 Apr 2012 02:10:02 +0400 |
parents | a705e848dcc7 |
children | 2ffe6f661605 |
comparison
equal
deleted
inserted
replaced
196:a705e848dcc7 | 197:6b1dda998839 |
---|---|
1 package IMPL::Web::Application::RestResource; | 1 package IMPL::Web::Application::RestResource; |
2 use strict; | 2 use strict; |
3 | 3 |
4 use IMPL::lang qw(:declare :constants); | |
5 use IMPL::declare { | |
6 require => { | |
7 ForbiddenException => 'IMPL::Web::ForbiddenException' | |
8 }, | |
9 base => { | |
10 'IMPL::Object' => undef | |
11 } | |
12 }; | |
13 | |
14 BEGIN { | |
15 public property target => PROP_GET | PROP_OWNERSET; | |
16 public property methods => PROP_GET | PROP_OWNERSET; | |
17 public property childRegex => PROP_GET | PROP_OWNERSET; | |
18 public property list => PROP_GET | PROP_OWNERSET; | |
19 public property fetch => PROP_GET | PROP_OWNERSET; | |
20 public property insert => PROP_GET | PROP_OWNERSET; | |
21 public property update => PROP_GET | PROP_OWNERSET; | |
22 public property delete => PROP_GET | PROP_OWNERSET; | |
23 } | |
24 | |
25 sub GetHttpImpl { | |
26 my($this,$method) = @_; | |
27 | |
28 my %map = ( | |
29 GET => 'GetImpl', | |
30 PUT => 'PutImpl', | |
31 POST => 'PostImpl', | |
32 DELETE => 'DeleteImpl' | |
33 ); | |
34 | |
35 return $map{$method}; | |
36 } | |
37 | |
38 sub InvokeHttpMethod { | |
39 my ($this,$method,$child,$action) = @_; | |
40 | |
41 my $impl = $this->GetHttpImpl($method) || 'FallbackImpl'; | |
42 | |
43 return $this->$impl($child,$action); | |
44 } | |
45 | |
46 sub GetImpl { | |
47 my ($this,$id,$action) = @_; | |
48 | |
49 my $rx; | |
50 my $method; | |
51 if (length $id == 0) { | |
52 $method = $this->list; | |
53 } elsif ($method = $this->methods->{$id}) { | |
54 if (ref $method eq 'HASH' and not $method->{allowGet}) { | |
55 die ForbiddenException->new(); | |
56 } | |
57 } elsif($rx = $this->childRegex and $id =~ m/$rx/ ) { | |
58 $method = $this->fetch or die ForbiddenException->new(); | |
59 | |
60 $method = { | |
61 method => $method, | |
62 parameters => [qw(id)] | |
63 } unless ref $method; | |
64 | |
65 } else { | |
66 die ForbiddenException->new(); | |
67 } | |
68 | |
69 return $this->InvokeMember($method,$id,$action); | |
70 } | |
71 | |
72 sub PutImpl { | |
73 my ($this,$id,$action) = @_; | |
74 | |
75 my $rx = $this->childRegex; | |
76 if ( $rx and $id =~ m/$rx/ and $this->update ) { | |
77 my $method = $this->update or die ForbiddenException->new(); | |
78 | |
79 $method = { | |
80 method => $method, | |
81 parameters => [qw(id query)] | |
82 } unless ref $method; | |
83 | |
84 return $this->InvokeMember($method,$id,$action); | |
85 } else { | |
86 die ForbiddenException->new(); | |
87 } | |
88 } | |
89 | |
90 sub PostImpl { | |
91 my ($this,$id,$action) = @_; | |
92 | |
93 my $method; | |
94 | |
95 if (length $id == 0) { | |
96 $method = $this->insert or die ForbiddenException->new(); | |
97 | |
98 $method = { | |
99 method => $method, | |
100 parameters => [qw(query)] | |
101 } unless ref $method; | |
102 } elsif ($method = $this->methods->{$id}) { | |
103 die ForbiddenException->new() unless ref $method and $method->{allowPost}; | |
104 } else { | |
105 die ForbiddenException->new(); | |
106 } | |
107 | |
108 return $this->InvokeMemeber($method,$id,$action); | |
109 } | |
110 | |
111 sub DeleteImpl { | |
112 my ($this,$id,$action) = @_; | |
113 | |
114 my $rx = $this->childRegex; | |
115 if ($rx and $id =~ m/$rx/ and my $method = $this->delete) { | |
116 | |
117 $method = { | |
118 method => $method, | |
119 parameters => [qw(id)] | |
120 } unless ref $method; | |
121 | |
122 return $this->InvokeMember($method,$id,$action); | |
123 } else { | |
124 die ForbiddenException->new(); | |
125 } | |
126 } | |
127 | |
128 sub HttpFallbackImpl { | |
129 die ForbiddenException->new(); | |
130 } | |
131 | |
132 sub InvokeMember { | |
133 my ($this,$method,$id,$action) = @_; | |
134 } | |
135 | |
136 | |
4 1; | 137 1; |
5 | 138 |
6 __END__ | 139 __END__ |
7 | 140 |
8 =pod | 141 =pod |
9 | 142 |
10 =head1 NAME | 143 =head1 NAME |
11 | 144 |
12 C<IMPL::Web::Application::RestResource> - ресурс Rest вебсервиса. | 145 C<IMPL::Web::Application::RestResource> - ресурс Rest вебсервиса. |
13 | 146 |
147 =head1 SYNOPSIS | |
148 | |
149 =begin text | |
150 | |
151 [REQUEST] | |
152 GET /artists | |
153 | |
154 [RESPONSE] | |
155 <artists> | |
156 <artist id="1"> | |
157 <name>The Beatles <name/> | |
158 </atrist> | |
159 <artist id="2"> | |
160 <name>Bonobo</name> | |
161 </artist> | |
162 </artists> | |
163 | |
164 [REQUEST] | |
165 GET /artists/1/cds?title='Live at BBC' | |
166 | |
167 [RESPONSE] | |
168 <cds> | |
169 <cd id="14"> | |
170 <title>Live at BBC 1</title> | |
171 </cd> | |
172 <cd id="15"> | |
173 <title>Live at BBC 2</title> | |
174 </cd> | |
175 </cds> | |
176 | |
177 [REQUEST] | |
178 GET /cds/15 | |
179 | |
180 [RESPONSE] | |
181 <cd id="15"> | |
182 <title>Live at BBC 2</title> | |
183 </cd> | |
184 | |
185 =end text | |
186 | |
187 =begin code | |
188 | |
189 use IMPL::require { | |
190 TRes => 'IMPL::Web:Application::RestResource', | |
191 DataContext => 'My::App::DataContext' | |
192 }; | |
193 | |
194 my $cds = TRes->new( | |
195 DataContext->Default, | |
196 { | |
197 methods => { | |
198 get => { | |
199 | |
200 }, | |
201 post => { | |
202 | |
203 } | |
204 } | |
205 get => 'search', | |
206 | |
207 | |
208 } | |
209 ); | |
210 | |
211 =end code | |
212 | |
14 =head1 DESCRIPTION | 213 =head1 DESCRIPTION |
15 | 214 |
215 Каждый ресурс представляет собой коллекцию и реализует методы C<HTTP> C<GET,POST,PUT,DELETE>. | |
216 | |
217 =head2 HTTP METHODS | |
218 | |
219 =head3 C<GET> | |
220 | |
221 Возвращает коллекцию дочерних ресурсов. | |
222 | |
223 =head3 C<GET {id}> | |
224 | |
225 Возвращает дочерний объект с идентификатором C<id> | |
226 | |
227 =head3 C<GET {method}> | |
228 | |
229 Вызывает метод C<method> и возвращает его результаты. При публикации методов доступных | |
230 через C<GET> данные методы не должны вносить изменений в предметную область. | |
231 | |
232 =head3 C<PUT {id}> | |
233 | |
234 Обновляет дочерний ресурс с указанным идентификатором. | |
235 | |
236 =head3 C<DELETE {id}> | |
237 | |
238 Удаляет дочерний ресурс с указанным идентификатором. | |
239 | |
240 =head3 C<POST> | |
241 | |
242 Добавляет новый дочерний ресурс в коллекцию. | |
243 | |
244 =head2 HTTP METHOD MAPPING | |
245 | |
246 =head3 C<POST {method}> | |
247 | |
248 Вызывает метод C<method>, в отличии от C<GET> методы опубликованные через C<POST> могут вносить | |
249 изменения в объекты. | |
250 | |
251 =head1 MEMBERS | |
252 | |
253 =head2 C<[get]target> | |
254 | |
255 Объект (также может быть и класс), обеспечивающий функционал ресурса. | |
256 | |
257 =head2 C<[get]methods> | |
258 | |
259 =head2 C<[get]childRegex> | |
260 | |
261 =head2 C<[get]fetch> | |
262 | |
263 =head2 C<[get]list> | |
264 | |
265 =head2 C<[get]insert> | |
266 | |
267 =head2 C<[get]update> | |
268 | |
269 =head2 C<[get]delete> | |
270 | |
271 =head2 C<GetImpl($child,$action)> | |
272 | |
273 =head2 C<PutImpl($child,$action)> | |
274 | |
275 =head2 C<PostImpl($child,$action)> | |
276 | |
277 =head2 C<DeleteImpl($child,$action)> | |
278 | |
279 =head2 C<InvokeMember($memberInfo,$child,$action)> | |
280 | |
16 =cut | 281 =cut |