FU: Add JSON reading & writing methods
This commit is contained in:
parent
17176738a0
commit
70c5199df4
1 changed files with 34 additions and 9 deletions
43
FU.pm
43
FU.pm
|
|
@ -637,7 +637,10 @@ sub headers { $FU::REQ->{hdr} }
|
||||||
sub ip { $FU::REQ->{ip} }
|
sub ip { $FU::REQ->{ip} }
|
||||||
|
|
||||||
sub _getfield($data, @a) {
|
sub _getfield($data, @a) {
|
||||||
return $data->{$a[0]} if @a == 1 && !ref $a[0];
|
if (@a == 1 && !ref $a[0]) {
|
||||||
|
fu->error(400, "Expected top-level to be a hash") if ref $data ne 'HASH';
|
||||||
|
return $data->{$a[0]};
|
||||||
|
}
|
||||||
require FU::Validate;
|
require FU::Validate;
|
||||||
my $schema = FU::Validate->compile(@a > 1 ? { keys => {@a} } : $a[0]);
|
my $schema = FU::Validate->compile(@a > 1 ? { keys => {@a} } : $a[0]);
|
||||||
my $res = eval { $schema->validate($data) };
|
my $res = eval { $schema->validate($data) };
|
||||||
|
|
@ -652,6 +655,15 @@ sub query {
|
||||||
_getfield $FU::REQ->{qs_parsed}, @_;
|
_getfield $FU::REQ->{qs_parsed}, @_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub json {
|
||||||
|
shift;
|
||||||
|
$FU::REQ->{json} ||= eval {
|
||||||
|
FU::Util::json_parse($FU::REQ->{data}, utf8 => 1)
|
||||||
|
} || fu->error(400, "JSON parse error: $@");
|
||||||
|
return $FU::REQ->{json} if !@_;
|
||||||
|
_getfield $FU::REQ->{json}, @_;
|
||||||
|
}
|
||||||
|
|
||||||
sub formdata {
|
sub formdata {
|
||||||
shift;
|
shift;
|
||||||
$FU::REQ->{formdata} ||= eval {
|
$FU::REQ->{formdata} ||= eval {
|
||||||
|
|
@ -715,6 +727,12 @@ sub set_header($, $hdr, $val=undef) {
|
||||||
$FU::REQ->{reshdr}{ lc $hdr } = $val;
|
$FU::REQ->{reshdr}{ lc $hdr } = $val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub send_json($, $data) {
|
||||||
|
fu->set_header('content-type', 'application/json');
|
||||||
|
fu->set_body(FU::Util::json_format($data, canonical => 1, utf8 => 1));
|
||||||
|
fu->done;
|
||||||
|
}
|
||||||
|
|
||||||
sub send_file($, $root, $path) {
|
sub send_file($, $root, $path) {
|
||||||
# This also catches files with '..' somewhere in the middle of the name.
|
# This also catches files with '..' somewhere in the middle of the name.
|
||||||
# Let's just disallow that to simplify this check, I'd err on the side of
|
# Let's just disallow that to simplify this check, I'd err on the side of
|
||||||
|
|
@ -1242,9 +1260,12 @@ Parse, validate and return multiple query parameters.
|
||||||
# Or, more concisely:
|
# Or, more concisely:
|
||||||
my $data = fu->query(a => {anybool => 1}, b => {});
|
my $data = fu->query(a => {anybool => 1}, b => {});
|
||||||
|
|
||||||
=item fu->formdata($name)
|
=item fu->json(@args)
|
||||||
|
|
||||||
=item fu->formdata($schema)
|
Like C<< fu->query() >> but parses the request body as JSON. Returns the
|
||||||
|
decoded JSON value if C<@args> is empty.
|
||||||
|
|
||||||
|
=item fu->formdata(@args)
|
||||||
|
|
||||||
Like C<< fu->query() >> but returns data from the POST request body. This
|
Like C<< fu->query() >> but returns data from the POST request body. This
|
||||||
method only supports form data encoded as C<application/x-www-form-urlencoded>,
|
method only supports form data encoded as C<application/x-www-form-urlencoded>,
|
||||||
|
|
@ -1253,13 +1274,11 @@ use C<< fu->multipart >> instead.
|
||||||
|
|
||||||
=item fu->multipart
|
=item fu->multipart
|
||||||
|
|
||||||
Parse the request body as C<multipart/form-data> and return an array of fields.
|
Parse the request body as C<multipart/form-data> and return an array of field
|
||||||
Refer to L<FU::MultipartFormData> for more information.
|
objects. Refer to L<FU::MultipartFormData> for more information.
|
||||||
|
|
||||||
=back
|
=back
|
||||||
|
|
||||||
I<TODO:> Support JSON bodies.
|
|
||||||
|
|
||||||
I<TODO:> Cookie parsing.
|
I<TODO:> Cookie parsing.
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1321,6 +1340,14 @@ templating system or L<FU::XMLWriter>:
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
=item fu->send_json($data)
|
||||||
|
|
||||||
|
Encode C<$data> as JSON (using C<json_format> in L<FU::Util>), set an
|
||||||
|
appropriate C<Content-Type> header and send it to the client. Calls C<<
|
||||||
|
fu->done >>.
|
||||||
|
|
||||||
|
I<TODO:> Support schema-based normalization.
|
||||||
|
|
||||||
=item fu->send_file($root, $path)
|
=item fu->send_file($root, $path)
|
||||||
|
|
||||||
If a file identified by C<"$root/$path"> exists, set that as response and call
|
If a file identified by C<"$root/$path"> exists, set that as response and call
|
||||||
|
|
@ -1374,8 +1401,6 @@ one of the following status codes or an alias:
|
||||||
|
|
||||||
I<TODO:> Setting cookies.
|
I<TODO:> Setting cookies.
|
||||||
|
|
||||||
I<TODO:> JSON output.
|
|
||||||
|
|
||||||
|
|
||||||
=head2 Running the Site
|
=head2 Running the Site
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue