[Catalyst] RFC: Catalyst::Plugin::AutoValidate
Markus Holzer
holli.holzer at googlemail.com
Wed Apr 9 10:06:04 BST 2008
Hello fellows, please bear with me, as this is my first contribution to
Catalyst.
From the pod: This Plugin validates request parameters against a
specification in a file that directly relates to the requests path (like
the .fb files when using Formbuilder).
I'm curiuos of your opinions.
Thank you,
Holli
_______________________________________________________
package Catalyst::Plugin::AutoValidate;
use warnings;
use strict;
use YAML qw( LoadFile );
use Catalyst::Request;
use Config::Validate;
use Data::Dumper;
use NEXT;
our $VERSION = 0.01;
sub prepare {
my $class = shift;
my $c = $class->NEXT::prepare( @_ );
my ( $config, $rpath, $spec_root, $spec_file, $validation_spec,
$validator );
# config for this package
$config = $c->config->{'Catalyst::Plugin::AutoValidate'};
# the request path
$rpath = $c->request->path || $config->{index_spec} || 'index';
# root dir to look for specifications
$spec_root = $config->{spec_root} || "$c->{home}/cvspec";
# spec file, deduced from path
$spec_file = "$spec_root/${rpath}.".($config->{spec_extension}||"cvs");
# check if there are custom types configured
if ( $config->{types} )
{
# add to the validation module
if ( ref( $config->{types} ) eq "ARRAY" )
{
for ( @{$config->{types}} )
{
Config::Validate::add_default_type(%$_);
}
}
else
{
Config::Validate->add_default_type(%{$config->{types}});
}
# move the types, so they won't get reprocessed another time
$config->{xtypes} = delete $config->{types};
}
# there is no matching spec file
unless ( -e $spec_file )
{
# that's ok or not, depending if we are paranoid
$c->request->{validated} = $config->{paranoid} ? 0 : 1;
}
else
{
# load spec and validate the request against it
$validation_spec = LoadFile( $spec_file );
$validator = Config::Validate->new( schema =>
$validation_spec );
# will die if validation fails
eval { $validator->validate( config => $c->request->{parameters}
) };
unless ( $@ )
{
$c->request->{validated} = 1;
}
else
{
$_ = "$@"; s/^.+?validate\(\): //; s/instead.+//;
$c->request->{validation_error} = "$_";
$c->request->{validated} = 0;
}
}
return $c;
}
1;
__DATA__
=head1 NAME
Catalyst::Plugin::AutoValidate - Catalyst-Plugin for easy automatic
validation of Request-Parameters
=head1 VERSION
Version 0.01
=head1 SYNOPSIS
This Plugin validates request parameters against a specification in a
file that directly
relates to the requests path (like the .fb files when using Formbuilder).
For the "heavy lifting" it uses
L<http://search.cpan.org/~cmo/Config-Validate-0.2.6/lib/Config/Validate.pm>;
All validation options from that module are supported, as they get
simply passed through.
# application code
package MyApp;
use strict;
use warnings;
use Catalyst qw(AutoValidate);
# MyApp::Controller::Root.pm
# check parameters and display error message when
# appropriate. Does NOT RUN THE CONTROLLER in that case,
# otherwise proceed with controller
sub begin : Private
{
my ($self, $c) = @_;
$c->response->body( $c->request->{validation_error} ),
$c->detach
unless $c->request->{validated};
}
# $c->{home}/cvspec/math/multiply.cvs (YAML)
a:
type: integer
b:
type: integer
# MyApp::Controller::Math.pm
sub multiply : Local
{
my ($self, $c) = @_;
# this is safe because Autovalidate ensures both are integers
$s->stash->{result} = $c->req->param('a') / $c->req->param('a')
}
=head1 CONFIGURATION
__PACKAGE__->config(
'Catalyst::Plugin::AutoValidate' =>
{
# root dir for looking up specifications
spec_root => '',
# when set, all requests without specification die
paranoid => 0,
# the name of the index spec (for empty paths)
index_spec => 'index',
# extension for spec-files
spec_extension => 'cvs',
# custom types
types =>
[
# generator sub that generates a closure, could come in handy
for lookups
{
name => 'custom',
validate => sub {
my $lookup = { exists => 1 };
return sub { die "Not in lookup table!" unless
$lookup->{$_[1]} };
}->()
},
# or easier
sub { die "Doesnt match!" unless $_[1] =~ /[abc]/ };
]
}
);
=cut
=head1 AUTHOR
Markus Holzer, C<< <holli.holzer at googlemmail.com> >>
=head1 BUGS
Please report any bugs or feature requests to
C<bug-catalyst-plugin-AutoValidate at rt.cpan.org>, or through
the web interface at
L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Catalyst-Plugin-AutoValidate>.
I will be notified, and then you'll
automatically be notified of progress on your bug as I make changes.
=head1 SUPPORT
You can find documentation for this module with the perldoc command.
perldoc Catalyst::Plugin::AutoValidate
You can also look for information at:
=over 4
=item * RT: CPAN's request tracker
L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Catalyst-Plugin-AutoValidate>
=item * AnnoCPAN: Annotated CPAN documentation
L<http://annocpan.org/dist/Catalyst-Plugin-AutoValidate>
=item * CPAN Ratings
L<http://cpanratings.perl.org/d/Catalyst-Plugin-AutoValidate>
=item * Search CPAN
L<http://search.cpan.org/dist/Catalyst-Plugin-AutoValidate>
=back
=head1 ACKNOWLEDGEMENTS
=head1 COPYRIGHT & LICENSE
Copyright 2008 Markus Holzer, all rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.
=cut
More information about the Catalyst
mailing list