FU::Validate: Add module + integrate with FU

Copied from TUWF::Validate with a few small changes. I have a few more
features planned, but let's see how this goes first.

It's been an incredibly useful module in the past, I'm not sure right
now if I had ideas for potential improvements at some point, will need
to check notes.
This commit is contained in:
Yorhel 2025-02-25 14:27:47 +01:00
parent c7a3415485
commit 69262992ca
6 changed files with 1228 additions and 7 deletions

43
FU.pm
View file

@ -604,14 +604,24 @@ sub header($, $h) { $FU::REQ->{hdr}{ lc $h } }
sub headers { $FU::REQ->{hdr} }
sub ip { $FU::REQ->{ip} }
sub _getfield($data, @a) {
return $data->{$a[0]} if @a == 1 && !ref $a[0];
require FU::Validate;
my $schema = FU::Validate->compile(@a > 1 ? { keys => {@a} } : $a[0]);
my $res = $schema->validate($data);
fu->error(400, "Input validation failed") if !$res; # TODO: More detailed error message
return @a == 2 ? $res->data->{$a[0]} : $res->data;
}
sub query {
return $FU::REQ->{qs} if @_ == 1;
shift;
return $FU::REQ->{qs} if !@_;
$FU::REQ->{qs_parsed} ||= eval { FU::Util::query_decode($FU::REQ->{qs}) } || fu->error(400, $@);
# TODO: Also accept schema validation thing.
$FU::REQ->{qs_parsed}{$_[1]};
_getfield $FU::REQ->{qs_parsed}, @_;
}
sub formdata {
shift;
$FU::REQ->{formdata} ||= eval {
# TODO: Support multipart encoding
confess "Invalid content type for form data"
@ -619,7 +629,7 @@ sub formdata {
FU::Util::query_decode($FU::REQ->{data});
} || fu->error(400, $@);
# TODO: Accept schema validation thing.
$FU::REQ->{formdata}{$_[1]};
_getfield $FU::REQ->{formdata}, @_;
}
@ -849,6 +859,8 @@ standalone and can be used independently of the framework:
=item * L<FU::SQL> - Small and safe query builder.
=item * L<FU::Validate> - Input validation through a schema.
=item * L<FU::XMLWriter> - Dynamic XML generation, easy and fast.
=item * L<FU::Log> - Global logger.
@ -1142,11 +1154,30 @@ C<https://example.com/some/path?query> this returns C<query>.
=item fu->query($name)
Parses the raw query string with C<query_decode> in L<FU::Util> and returns the
value with the given $name.
value with the given $name. Beware: multiple values are returned as an array.
Prefer to use the C<$schema>-based validation methods below to reliably handle
all sorts of query strings.
=item fu->query($name => $schema)
Parse, validate and return the query parameter identified by C<$name> with the
given L<FU::Validate> schema. Calls C<< fu->error(400) >> with a useful error
message if validation fails.
=item fu->query($schema)
I<TODO>
=item fu->query($name1 => $schema1, $name2 => $schema2, ..)
Parse, validate and return multiple query parameters.
state $schema = FU::Validate->compile({
keys => { a => {anybool => 1}, b => {} }
});
my $data = fu->query($schema);
# $data = { a => .., b => .. }
# Or, more concisely:
my $data = fu->query(a => {anybool => 1}, b => {});
=item fu->formdata($name)