view Lib/IMPL/Web/Handler/RestController.pm @ 213:d6e2ea24af08

sync
author sergey
date Fri, 03 Aug 2012 01:15:15 +0400
parents 292226770180
children 47f77e6409f7
line wrap: on
line source

package IMPL::Web::Handler::RestController;
use strict;

use IMPL::lang qw(:declare :constants);


use IMPL::declare {
	require => {
		Exception => 'IMPL::Exception',
		ArgumentExecption => '-IMPL::InvalidArgumentException',
		HttpException => 'IMPL::Web::Exception',
        NotFoundException => 'IMPL::Web::NotFoundException'
	},
	base => {
		'IMPL::Object' => undef,
		'IMPL::Object::Autofill' => '@_',
		'IMPL::Object::Serializable' => undef
	}	
};

BEGIN {
	public property root => PROP_GET | PROP_OWNERSET;
	public property contract => PROP_GET | PROP_OWNERSET;
}

sub CTOR {
	my ($this) = @_;
	
	die ArgumentException->new("root") unless $this->root;
	die ArgumentException->new("contract") unless $this->contract;
}

sub Invoke {
	my ($this,$action) = @_;
	
	my $query = $action->query;
	
	my $method = $query->request_method;
	
	#TODO: path_info is broken for IIS
	my $pathInfo = $query->path_info;
	my @segments;
	
	if (length $pathInfo) {
	
		@segments = split /\//, $pathInfo, -1; # keep trailing empty string if present
		
		# remove first segment since it's always empty
		shift @segments;
		
		my ($obj,$view) = (pop(@segments) =~ m/(.*?)(?:\.(\w+))?$/);
		push @segments, $obj;
	
	}
	
	
	my $res = $this->contract->Transform($this->root, { id => '' } );
	
	while(@segments) {
		my $id = shift @segments;
		
		$res = $res->FetchChildResource($id,$action);
		
		die NotFoundException->new($pathInfo,$id) unless $res;
	}
	
	$res = $res->InvokeHttpMethod($method,$action);
}

1;

__END__

=pod

=head1 NAME

C<IMPL::Web::Handler::RestController> - Транслирует запросы к ресурсам в вызовы методов.

=head1 SYNOPSIS

Использует контракты для преобразования стандартных C<REST> запросов в вызовы методов объектов.
C<$ENV{PATH_INFO}> используется как путь к нужному ресурсу у которого будет вызван метод указанный в запросе.

=head1 DESCRIPTION

=head2 Resource model

Ресурсы имеют иерархическую структуру, аналогичную файлам и каталогам, которая описывается контрактом, также
контрак описывает то, как должны обрабатываться методы C<HTTP> запроса, такие как C<GET> и C<POST>.

За корректность реализации данных методов отвечает разработчик.

Каждый ресурс представляет собой коллкецию вложенных ресурсов, путь указанный в C<HTTP> запросе разбивается на
части, затем каждый сегмент последовательно используется для поиска дочернего ресурса. При обработки
первого сегмента используется корневой ресурс. Корневой ресурс должен существовать всегда.

=head2 Contract

Контрактом может быть любое преобразование которое определяет соответсвие между объектами приложения и
ресурсами, доступными через протокол C<HTTP>.




=cut