Mercurial > pub > Impl
view 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 |
line wrap: on
line source
package IMPL::Web::Application::RestResource; use strict; use IMPL::lang qw(:declare :constants); use IMPL::declare { require => { ForbiddenException => 'IMPL::Web::ForbiddenException' }, base => { 'IMPL::Object' => undef } }; BEGIN { public property target => PROP_GET | PROP_OWNERSET; public property methods => PROP_GET | PROP_OWNERSET; public property childRegex => PROP_GET | PROP_OWNERSET; public property list => PROP_GET | PROP_OWNERSET; public property fetch => PROP_GET | PROP_OWNERSET; public property insert => PROP_GET | PROP_OWNERSET; public property update => PROP_GET | PROP_OWNERSET; public property delete => PROP_GET | PROP_OWNERSET; } sub GetHttpImpl { my($this,$method) = @_; my %map = ( GET => 'GetImpl', PUT => 'PutImpl', POST => 'PostImpl', DELETE => 'DeleteImpl' ); return $map{$method}; } sub InvokeHttpMethod { my ($this,$method,$child,$action) = @_; my $impl = $this->GetHttpImpl($method) || 'FallbackImpl'; return $this->$impl($child,$action); } sub GetImpl { my ($this,$id,$action) = @_; my $rx; my $method; if (length $id == 0) { $method = $this->list; } elsif ($method = $this->methods->{$id}) { if (ref $method eq 'HASH' and not $method->{allowGet}) { die ForbiddenException->new(); } } elsif($rx = $this->childRegex and $id =~ m/$rx/ ) { $method = $this->fetch or die ForbiddenException->new(); $method = { method => $method, parameters => [qw(id)] } unless ref $method; } else { die ForbiddenException->new(); } return $this->InvokeMember($method,$id,$action); } sub PutImpl { my ($this,$id,$action) = @_; my $rx = $this->childRegex; if ( $rx and $id =~ m/$rx/ and $this->update ) { my $method = $this->update or die ForbiddenException->new(); $method = { method => $method, parameters => [qw(id query)] } unless ref $method; return $this->InvokeMember($method,$id,$action); } else { die ForbiddenException->new(); } } sub PostImpl { my ($this,$id,$action) = @_; my $method; if (length $id == 0) { $method = $this->insert or die ForbiddenException->new(); $method = { method => $method, parameters => [qw(query)] } unless ref $method; } elsif ($method = $this->methods->{$id}) { die ForbiddenException->new() unless ref $method and $method->{allowPost}; } else { die ForbiddenException->new(); } return $this->InvokeMemeber($method,$id,$action); } sub DeleteImpl { my ($this,$id,$action) = @_; my $rx = $this->childRegex; if ($rx and $id =~ m/$rx/ and my $method = $this->delete) { $method = { method => $method, parameters => [qw(id)] } unless ref $method; return $this->InvokeMember($method,$id,$action); } else { die ForbiddenException->new(); } } sub HttpFallbackImpl { die ForbiddenException->new(); } sub InvokeMember { my ($this,$method,$id,$action) = @_; } 1; __END__ =pod =head1 NAME C<IMPL::Web::Application::RestResource> - ресурс Rest вебсервиса. =head1 SYNOPSIS =begin text [REQUEST] GET /artists [RESPONSE] <artists> <artist id="1"> <name>The Beatles <name/> </atrist> <artist id="2"> <name>Bonobo</name> </artist> </artists> [REQUEST] GET /artists/1/cds?title='Live at BBC' [RESPONSE] <cds> <cd id="14"> <title>Live at BBC 1</title> </cd> <cd id="15"> <title>Live at BBC 2</title> </cd> </cds> [REQUEST] GET /cds/15 [RESPONSE] <cd id="15"> <title>Live at BBC 2</title> </cd> =end text =begin code use IMPL::require { TRes => 'IMPL::Web:Application::RestResource', DataContext => 'My::App::DataContext' }; my $cds = TRes->new( DataContext->Default, { methods => { get => { }, post => { } } get => 'search', } ); =end code =head1 DESCRIPTION Каждый ресурс представляет собой коллекцию и реализует методы C<HTTP> C<GET,POST,PUT,DELETE>. =head2 HTTP METHODS =head3 C<GET> Возвращает коллекцию дочерних ресурсов. =head3 C<GET {id}> Возвращает дочерний объект с идентификатором C<id> =head3 C<GET {method}> Вызывает метод C<method> и возвращает его результаты. При публикации методов доступных через C<GET> данные методы не должны вносить изменений в предметную область. =head3 C<PUT {id}> Обновляет дочерний ресурс с указанным идентификатором. =head3 C<DELETE {id}> Удаляет дочерний ресурс с указанным идентификатором. =head3 C<POST> Добавляет новый дочерний ресурс в коллекцию. =head2 HTTP METHOD MAPPING =head3 C<POST {method}> Вызывает метод C<method>, в отличии от C<GET> методы опубликованные через C<POST> могут вносить изменения в объекты. =head1 MEMBERS =head2 C<[get]target> Объект (также может быть и класс), обеспечивающий функционал ресурса. =head2 C<[get]methods> =head2 C<[get]childRegex> =head2 C<[get]fetch> =head2 C<[get]list> =head2 C<[get]insert> =head2 C<[get]update> =head2 C<[get]delete> =head2 C<GetImpl($child,$action)> =head2 C<PutImpl($child,$action)> =head2 C<PostImpl($child,$action)> =head2 C<DeleteImpl($child,$action)> =head2 C<InvokeMember($memberInfo,$child,$action)> =cut