NAME

MojoX::Dispatcher::FilterChain - Intercepting filter manager

SYNOPSIS

use MojoX::Dispatcher::FilterChain;

my $chain = MojoX::Dispatcher::FilterChain->new();
$chain->add(LanguageDetect->new);
$chain->add(Authorization->new);
$chain->add(RenderView->new);

...

$chain->process($c);

DESCRIPTION

MojoX::Dispatcher::FilterChain is a intercepting filter manager pattern implementation.

Standart dispatch process can look like this:

sub dispatch {
    my ($self, $c) = @_;

    # Try to find a static file
    $self->static->dispatch($c);

    # Use routes if we don't have a response code yet
    $self->routes->dispatch($c) unless $c->res->code;

    # Nothing found, serve static file "public/404.html"
    unless ($c->res->code) {
       #$self->static->serve($c, '/404.html');
       #$c->res->code(404);
    }
}

Problem is that we have repetitive code that is checking whether to go to the next dispatcher or stop.

What we want to have is a list of independent filters that are called in specific order and one of them can intercept the chain.

Now we can rewrite our dispatch example.

__PACKAGE__->attr('chain', 
    default => sub { MojoX::Dispatcher::FilterChain->new } );

sub dispatch {
    my ($self, $c) = @_;

    # run filter chain
    $self->chain->process($c);
}

sub startup {
    my $self = shift;

    my $chain = $self->chain;

    $chain->add(MyApp::FilterChain::StaticDispatch->new($c));
    $chain->add(MyApp::FilterChain::RoutesDispatch->new($c));
    $chain->add(MyApp::FilterChain::RenderView->new($c));
}

Filter itself inherits MojoX::FilterChain::Base and has method run that is called when chain is processed. MojoX::FilterChain::Constants module exports two self explaining constants NEXT and LAST. Depending on which value is returned after running current filter, chain proceeds or stops.

Regular filter can look like this:

package MyApp::FilterChain::Routes;

use strict;
use warnings;

use base 'MojoX::FilterChain::Base';

# export LAST and NEXT constants
use MojoX::FilterChain::Constants;

sub run {
    my ( $self, $c ) = @_;

    $c->app->routes->dispatch($c);

    return $c->res->code ? LAST : NEXT;
}

1;

METHODS

MojoX::Dispatcher::FilterChain inherits all methods from Mojo::Base and implements the following the ones.

new

my $chain = MojoX::Dispatcher::FilterChain->new;

add

Add filter instance to filter chain.

my $chain->add(Filter->new);

process

Run filter chain. Parameters provided will be passed on to every filter.

$chain->process($c);

COPYRIGHT & LICENSE

Copyright 2008 Viacheslav Tikhanovskii, all rights reserved.

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.