[cgiapp] Proposal: CGI::Application::Plugin::ValidateQuery
Mark Stosberg
mark at summersault.com
Fri Apr 10 18:13:59 EDT 2009
I'm considering producing a CGI::Application plugin for light weight query
validation using Params::Validate. I've drafted the POD for it, and
that's below.
The implementation would include one novel technical concept that I
haven't notice in use before in a CGI::Application project.
We wanted to clean up the API, so that instead of this:
my $err_page = $self->validate_query;
return $err_page if $err_page
We could just do this:
$self->validate_query;
This means we had to find some other way to interrupt the flow and
return our error page. The solution is to write a suicide note and then
pull the trigger. Or rather, in validate_query(), if validation fails,
we do a just-in-time setting of error_mode(), and then die, which
interrupts the flow and triggers the error_mode to be called.
The solution seems reasonable, as a general error_mode() would still
remain in effect, and if some reason you don't want interrupt the flow,
just trap the exception the usual way:
eval { $self->validate_query; }
I hadn't considered it until now, but perhaps we could also use
Exception::Class so users could easily distinquish between
death-by-validation failure and unexpected-death.
Now that I've thought of this approach, it makes me want to apply to to
the ::ValidateRM interface. Anyone see a reason not to take this
approach for this plugin, or ValidateRM?
####
=head1 NAME
CGI::Application::Plugin::ValidateQuery
=head1 SYNOPSIS
sub setup {
my $self = shift;
$self->validate_query_config(
# define a page to show for invalid queries, or default to
# serving a plain, internal page
error_mode => 'my_invalid_query_run_mode',
log_level => 'notice',
);
}
sub my_run_mode {
my $self = shift;
# validate the query and return a standard error page on failure.
$self->validate_query(
pet_id => SCALAR,
direction => { type => SCALAR, default => 'up' },
);
# go on with life...
}
=head1 DESCRIPTION
This plugin is for small query validation tasks. For example, perhaps
you link to a page where a "pet_id" is required, and you need to reality
check that this exists or return essentially a generic error message to
the user.
Even if your application generates the link, it may become altered
through tampering, malware, or other unanticipated events.
This plugin uses <Params::Validate> to validate the query string. You
can define your own error page to return on failure, or we'll supply a
plain default one internally.
You may also define a C<log_level>, if you do, we will also log each
validation failure at the chosen level like this:
$self->log->$loglevel("Query validation failed: $@");
L<CGI::Application::Plugin::LogDispatch> is one plugin which implements
this logging API.
=head2 validate_query
$self->validate_query(
pet_id => SCALAR,
type => { type => SCALAR, default => 'food' },
log_level => 'critical', # optional
);
Validates C<< $self->query >> using L<Params::Validate>. If any required
query param is missing or invalid, the run mode defined with C<<
validate_query_config >> will be used, or a plain internal page will be
returned by default. C<< validate_query_config >> is usually called in
C<< setup() >>, or a in a project super-class.
If <log_level> is defined, it will override the the log file provided in
C<< validate_query_config >> and log a validation failure at that log
evel
If you set a default, the query will be modified with the new value.
=cut
sub validate_query {
}
=head2 IMPLENTATION NOTES
We set "local $Params::Validate::NO_VALIDATION = 0;" to be sure that
Params::Validate works for us, even if is globally disabled.
To alter the application flow when validation fails, we set
'error_mode()' at the last minute, and then die, so the error mode is
triggered. Other uses of error_mode() should continue to work as normal.
This module is intended to be use for simple query validation tasks,
such as a link with query string with a small number of arguments. For
larger validation tasks, especially for processing for submissions using
L< Data::FormValidator > is recommended, along with L<
CGI::Application::ValidateRM > if you using CGI::Application.
=head2 FUTURE
This concept could be extended to all check values set through
$self->param(), or through $ENV{PATH_INFO} .
This plugin does handle file upload validations, and won't in the
future.
Providing untainting is not a goal of this module, but if it's easy and
someone else provides a patch, perhaps support will be added.
=head1 AUTHOR
Mark Stosberg C<< mark at summersault.com >>
More information about the cgiapp
mailing list