PAGI-Tools

 view release on metacpan or  search on metacpan

t/request/11-multipart-handler.t  view on Meta::CPAN

        { name => 'f3', filename => '3.txt', data => 'c' },
    );

    my $receive = mock_receive($body);
    my $handler = PAGI::Request::MultiPartHandler->new(
        boundary  => $boundary,
        receive   => $receive,
        max_files => 2,
    );

    like(
        dies { (async sub { await $handler->parse })->()->get },
        qr/Too many files/,
        'dies when exceeding max_files'
    );
};

subtest 'enforce max_fields limit' => sub {
    my $boundary = '----MaxFields';
    my $body = build_multipart($boundary,
        { name => 'f1', data => 'a' },
        { name => 'f2', data => 'b' },
        { name => 'f3', data => 'c' },
    );

    my $receive = mock_receive($body);
    my $handler = PAGI::Request::MultiPartHandler->new(
        boundary   => $boundary,
        receive    => $receive,
        max_fields => 2,
    );

    like(
        dies { (async sub { await $handler->parse })->()->get },
        qr/Too many fields/,
        'dies when exceeding max_fields'
    );
};

subtest 'enforce max_field_size limit' => sub {
    my $boundary = '----MaxSize';
    my $large_data = 'x' x (100 * 1024);  # 100KB form field (no filename = not a file)
    my $body = build_multipart($boundary,
        { name => 'big_field', data => $large_data },
    );

    my $receive = mock_receive($body);
    my $handler = PAGI::Request::MultiPartHandler->new(
        boundary       => $boundary,
        receive        => $receive,
        max_field_size => 50 * 1024,  # 50KB limit for form fields
    );

    like(
        dies { (async sub { await $handler->parse })->()->get },
        qr/Form field too large/,
        'dies when exceeding max_field_size'
    );
};

subtest 'chunked input streaming' => sub {
    my $boundary = '----Chunked';
    my $full_body = build_multipart($boundary,
        { name => 'title', data => 'Hello' },
        { name => 'doc', filename => 'test.txt', content_type => 'text/plain', data => 'file content here' },
    );

    # Split body into chunks
    my @chunks;
    my $chunk_size = 30;
    for (my $i = 0; $i < length($full_body); $i += $chunk_size) {
        push @chunks, substr($full_body, $i, $chunk_size);
    }

    my $index = 0;
    my $receive = async sub {
        if ($index >= @chunks) {
            return { type => 'http.disconnect' };
        }
        my $chunk = $chunks[$index++];
        return {
            type => 'http.request',
            body => $chunk,
            more => $index < @chunks,
        };
    };

    my $handler = PAGI::Request::MultiPartHandler->new(
        boundary => $boundary,
        receive  => $receive,
    );

    my ($form, $uploads) = (async sub { await $handler->parse })->()->get;

    is($form->get('title'), 'Hello', 'form field from chunked input');
    my $upload = $uploads->get('doc');
    is($upload->slurp, 'file content here', 'file content from chunked input');
};

done_testing;



( run in 1.311 second using v1.01-cache-2.11-cpan-6aa56a78535 )