package TestFilter::out_str_buffer;

# in this test we want to buffer the data, modify the length of the
# response, set the c-l header and make sure that the client sees the
# right thing
#
# notice that a bucket brigades based filter must be used. The streaming
# API lets FLUSH buckets through which causes an early flush of HTTP
# response headers

use strict;
use warnings FATAL => 'all';

use Apache2::RequestRec ();
use Apache2::RequestIO ();

use APR::Table ();
use APR::Bucket ();
use APR::Brigade ();

use TestCommon::Utils ();

use base qw(Apache2::Filter);

use Apache2::Const -compile => qw(OK M_POST);
use APR::Const     -compile => ':common';

sub flatten_bb {
    my ($bb) = shift;

    my $seen_eos = 0;

    my @data;
    for (my $b = $bb->first; $b; $b = $bb->next($b)) {
        $seen_eos++, last if $b->is_eos;
        $b->read(my $bdata);
        push @data, $bdata;
    }
    return (join('', @data), $seen_eos);
}

sub handler {
    my ($filter, $bb) = @_;

    my $ctx = $filter->ctx;

    # no need to unset the C-L header, since this filter makes sure to
    # correct it before any headers go out.
    #unless ($ctx) {
    #    $filter->r->headers_out->unset('Content-Length');
    #}

    my $data = exists $ctx->{data} ? $ctx->{data} : '';
    $ctx->{invoked}++;
    my ($bdata, $seen_eos) = flatten_bb($bb);
    $bdata =~ s/-//g;
    $data .= $bdata if $bdata;

    if ($seen_eos) {
        my $len = length $data;
        $filter->r->headers_out->set('Content-Length', $len);
        $filter->print($data) if $data;
    }
    else {
        # store context for all but the last invocation
        $ctx->{data} = $data;
        $filter->ctx($ctx);
    }

    return Apache2::Const::OK;
}

sub response {
    my $r = shift;

    $r->content_type('text/plain');

    my $data = '';
    if ($r->method_number == Apache2::Const::M_POST) {
        $data = TestCommon::Utils::read_post($r);
        $r->headers_out->set('Content-Length' => length $data);
    }

    for my $chunk (split /0/, $data) {
        $r->print($chunk);
        $r->rflush; # so the filter reads a chunk at a time
    }

    return Apache2::Const::OK;
}

1;
__DATA__

SetHandler modperl
PerlModule          TestFilter::out_str_buffer
PerlResponseHandler TestFilter::out_str_buffer::response

