view lib/IMPL/Web/Handler/ErrorHandler.pm @ 413:af8d359ee4cc ref20150831

working on di container
author cin
date Thu, 24 Sep 2015 12:19:30 +0300
parents c6e90e02dd17
children
line wrap: on
line source

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

use IMPL::Const qw(:prop);
use IMPL::Exception();
use IMPL::declare {
	require => {
		WebException => 'IMPL::Web::Exception',
		ArgumentException => '-IMPL::InvalidArgumentException',
		IOException => '-IMPL::IOException',
		HttpResponse => 'IMPL::Web::HttpResponse',
		Security => 'IMPL::Security'
	},
	base => {
		'IMPL::Object' => undef,
		'IMPL::Object::Autofill' => '@_',
		'IMPL::Object::Serializable' => undef
	},
	props => [
        errors => PROP_RW,
        view => PROP_RW,
        fallback => PROP_RW,
        contentType => PROP_RW
	]
};

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

sub Invoke {
	my ($this,$action,$next) = @_;
	
	undef $@;
	my $result;
	eval {
        $result = $next ? $next->($action) : undef;
	};
	
	if (my $err = $@) {
	    
		my $vars = {
			error => $err,
			result      => $result,
	        request     => sub { $action },
	        app         => $action->application,
	        location    => $action->context->{resourceLocation},
	        resource    => $action->context->{resource},
	        document    => {},
	        session     => sub { Security->context },
	        user        => sub { Security->principal },
	        security    => sub { $action->security }
		};
		
		my $status = "500 Internal Server Error";
		
		if (eval { $err->isa(WebException) }) {
			$status = $err->status;
		}
		
		my ($code) = ($status =~ m/^(\d+)/);
		
        my $text = $this->view->display(
        	$err,
        	$this->errors->{$code} || $this->fallback,
        	$vars
		);
        
        $result = HttpResponse->new(
            status => $status,
            type => $this->contentType,
            charset => 'utf-8',
            headers => eval{ $err->headers } || {},
            body => $text
        );
	}
	
	return $result;
}

1;

__END__

=pod

=head1 NAME

C<IMPL::Web::Handler::ErrorHandler> - обертка для обработки исключений.

=head1 SYNOPSIS

Используется в цеопчке обработчиков приложения.

=begin code xml

    <handlers type="ARRAY">
        <item type="IMPL::Web::Handler::ErrorHandler">
            <contentType>text/html</contentType>
            <loader refid="tt-loader"/>
            <errors type="HASH">
                <error extname="500">errors/500</error>
                <error extname="404">errors/404</error>
                <error extname="403">errors/403</error>
            </errors>
            <fallback>errors/500</fallback>
        </item>
    </handlers>

=end code xml

=head1 DESCRIPTION

Позволяет создать представление для ресурса в случае ошибки, для этого
используется соответствие представлений и кодов ошибок.

В результате обработчик либо прозрачно передает результат вышестоящего
обработчика нижестоящему, либо создает C<IMPL::Web::HttpResponse> с
соответствующим статусом и содержанием. 

=cut