FU: Support multipart file uploads + some doc fixes

API is not super convenient and implementation is lousy, but uploading
files is not a super common operation so that should be fine.

At least it supports large files with only a single in-memory copy.
This commit is contained in:
Yorhel 2025-03-08 14:02:51 +01:00
parent e5755ddd80
commit 17176738a0
6 changed files with 280 additions and 13 deletions

25
FU.pm
View file

@ -253,8 +253,9 @@ sub _read_req_http($sock, $req) {
$req->{body} = '';
while ($len > 0) {
my $r = $sock->read($req->{body}, $len, -1);
fu->error(400, 'Client disconnect before request was read') if !$r
my $r = $sock->read($req->{body}, $len, length $req->{body});
fu->error(400, 'Client disconnect before request was read') if !$r;
$len -= $r;
}
}
@ -654,7 +655,6 @@ sub query {
sub formdata {
shift;
$FU::REQ->{formdata} ||= eval {
# TODO: Support multipart encoding
confess "Invalid content type for form data"
if (fu->header('content-type')||'') ne 'application/x-www-form-urlencoded';
FU::Util::query_decode($FU::REQ->{data});
@ -662,6 +662,13 @@ sub formdata {
_getfield $FU::REQ->{formdata}, @_;
}
sub multipart {
require FU::MultipartFormData;
$FU::REQ->{multipart} ||= eval {
FU::MultipartFormData->parse(fu->header('content-type')||'', $FU::REQ->{body})
} || fu->error(400, $@);
}
@ -1239,12 +1246,18 @@ Parse, validate and return multiple query parameters.
=item fu->formdata($schema)
Like C<< fu->query() >> but returns data from the POST request body.
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>,
which is the default for HTML C<< <form> >>s. To handle multipart form data,
use C<< fu->multipart >> instead.
=item fu->multipart
Parse the request body as C<multipart/form-data> and return an array of fields.
Refer to L<FU::MultipartFormData> for more information.
=back
I<TODO:> Support C<multipart/form-data> and file uploads.
I<TODO:> Support JSON bodies.
I<TODO:> Cookie parsing.