mod_perl

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN


Apache::RequestIO: print(), printf(), puts(), write(), rflush() throw
an exception on failure [Stas]

Apache::SubRequest: run() throw an exception on failure [Stas]

Apache::Filter: [Stas]
  - remove unneeded methods: remove_input_filter() and
    remove_output_filter(), fputs()
  - frec() accessor is made read-only
  - fflush(), get_brigade() and pass_brigade() now throw exceptions if
    called in the void context
  - read, print() and puts() throw an exception on failure

Apache::FilterRec: [Stas]
  - remove the next() accessor since it's not used by Apache at the
    moment
  - name() is made read-only

APR::URI: [Stas]
  - removed accessors

docs/api/Apache2/Const.pod  view on Meta::CPAN






=head2 C<:input_mode>

  use Apache2::Const -compile => qw(:input_mode);

The C<:input_mode> group is used by
C<L<get_brigade|docs::2.0::api::Apache2::Filter/C_get_brigade_>>.






=head3 C<Apache2::Const::MODE_EATCRLF>

=over

=item since: 2.0.00

=back

See
C<L<Apache2::Filter::get_brigade()|docs::2.0::api::Apache2::Filter/C_get_brigade_>>.






=head3 C<Apache2::Const::MODE_EXHAUSTIVE>

=over

=item since: 2.0.00

=back

See
C<L<Apache2::Filter::get_brigade()|docs::2.0::api::Apache2::Filter/C_get_brigade_>>.





=head3 C<Apache2::Const::MODE_GETLINE>

=over

=item since: 2.0.00

=back

See
C<L<Apache2::Filter::get_brigade()|docs::2.0::api::Apache2::Filter/C_get_brigade_>>.





=head3 C<Apache2::Const::MODE_INIT>

=over

=item since: 2.0.00

=back

See
C<L<Apache2::Filter::get_brigade()|docs::2.0::api::Apache2::Filter/C_get_brigade_>>.





=head3 C<Apache2::Const::MODE_READBYTES>

=over

=item since: 2.0.00

=back

See
C<L<Apache2::Filter::get_brigade()|docs::2.0::api::Apache2::Filter/C_get_brigade_>>.





=head3 C<Apache2::Const::MODE_SPECULATIVE>

=over

=item since: 2.0.00

=back

See
C<L<Apache2::Filter::get_brigade()|docs::2.0::api::Apache2::Filter/C_get_brigade_>>.









=head2 C<:log>

docs/api/Apache2/Filter.pod  view on Meta::CPAN

  # filter attributes
  my $c = $f->c;
  my $r = $f->r;
  my $frec = $f->frec();
  my $next_f = $f->next;
  
  my $ctx = $f->ctx;
  $f->ctx($ctx);
  
  # bucket brigade filtering API
  $rc = $f->next->get_brigade($bb, $mode, $block, $readbytes);
  $rc = $f->next->pass_brigade($bb);
  $rc = $f->fflush($bb);
  
  # streaming filtering API
  while ($filter->read(my $buffer, $wanted)) {
      # transform $buffer here
      $filter->print($buffer);
  }
  if ($f->seen_eos) {
      $filter->print("filter signature");

docs/user/handlers/filters.pod  view on Meta::CPAN

  package MyApache2::FilterTransparent;
  
  use Apache2::Filter ();
  
  use Apache2::Const -compile => qw(OK);
  use APR::Const     -compile => ':common';
  
  sub in {
      my ($f, $bb, $mode, $block, $readbytes) = @_;
  
      my $rv = $f->next->get_brigade($bb, $mode, $block, $readbytes);
      return $rv unless $rv == APR::Const::SUCCESS;
  
      return Apache2::Const::OK;
  }

When the input filter I<in()> is invoked, it first asks the upstream
filter for the next bucket brigade (using the C<get_brigade()>
call). That upstream filter is in turn going to ask for the bucket
brigade from the next upstream filter and so on up the chain, until
the last filter (called C<core_in>), the one that reads from the
network, is reached. The C<core_in> filter reads, using a socket, a
portion of the incoming data from the network, processes it, and sends
it to its downstream filter. That filter processes the data and send
it to its downstream filter, etc., until it reaches the first filter
that requested the data. (In reality some other handler triggers the
request for the bucket brigade, such as an HTTP response handler or a
protocol module, but for this discussion it's sufficient to assume
that it's the first filter that issues the C<get_brigade()> call.)

The following diagram depicts a typical input filter data flow
in addition to the program control flow.

=for html
<img src="in_filter_stream.gif" width="659" height="275" 
 align="middle" alt="input filter data flow"><br><br>

The black- and white-headed arrows show when the control is passed
from one filter to another. In addition, the black-headed arrows show
the actual data flow. The diagram includes some pseudo-code, in Perl
for the mod_perl filters and in C for the internal Apache filters. You
don't have to understand C to understand this diagram. What's
important to understand is that when input filters are invoked, they
first call each other via the C<get_brigade()> call and then block
(notice the brick wall on the diagram), waiting for the call to
return. When this call returns, all upstream filters have already
completed their filtering task on the bucket brigade.

As mentioned earlier, the streaming interface hides the details,
but the first C<$f-E<gt>read()> call will block as the layer under it
performs the C<get_brigade()> call.

The diagram shows only part of the actual input filter chain for an
HTTP request. The C<...> indicates that there are more filters in
between the mod_perl filter and C<http_in>.

Now let's look at what happens in the output filters chain. Here the
first filter acquires the bucket brigades containing the response data
from the content handler (or another protocol handler if we aren't
talking HTTP). It may then make some modification and pass the data to
the next filter (using the C<pass_brigade()> call), which in turn

docs/user/handlers/protocols.pod  view on Meta::CPAN

  sub handler {
      my $c = shift;
  
      $c->client_socket->opt_set(APR::Const::SO_NONBLOCK => 0);
  
      my $bb_in  = APR::Brigade->new($c->pool, $c->bucket_alloc);
      my $bb_out = APR::Brigade->new($c->pool, $c->bucket_alloc);
  
      my $last = 0;
      while (1) {
          my $rc = $c->input_filters->get_brigade($bb_in,
                                                  Apache2::Const::MODE_GETLINE);
          last if APR::Status::is_EOF($rc);
          die APR::Error::strerror($rc) unless $rc == APR::Const::SUCCESS;
  
          while (!$bb_in->is_empty) {
              my $b = $bb_in->first;
  
              $b->remove;
  
              if ($b->is_eos) {

lib/Apache2/compat.pm  view on Meta::CPAN


sub content {
    my $r = shift;

    my $bb = APR::Brigade->new($r->pool,
                               $r->connection->bucket_alloc);

    my $data = '';
    my $seen_eos = 0;
    do {
        $r->input_filters->get_brigade($bb, Apache2::Const::MODE_READBYTES,
                                       APR::Const::BLOCK_READ, IOBUFSIZE);
        while (!$bb->is_empty) {
            my $b = $bb->first;

            if ($b->is_eos) {
                $seen_eos++;
                last;
            }

            if ($b->read(my $buf)) {

lib/ModPerl/MethodLookup.pm  view on Meta::CPAN

               'APR::Table',
               undef
             ]
           ],
  'get_basic_auth_pw' => [
                           [
                             'Apache2::Access',
                             undef
                           ]
                         ],
  'get_brigade' => [
                     [
                       'Apache2::Filter',
                       'Apache2::Filter'
                     ]
                   ],
  'get_client_block' => [
                          [
                            'Apache2::RequestIO',
                            'Apache2::RequestRec'
                          ]

src/modules/perl/modperl_filter.c  view on Meta::CPAN

    apr_size_t len = 0;

    if (!filter->bb_in) {
        /* This should be read only once per handler invocation! */
        filter->bb_in = apr_brigade_create(filter->pool,
                                           filter->f->c->bucket_alloc);
        MP_TRACE_f(MP_FUNC, MP_FILTER_NAME_FORMAT
                   "retrieving bb: 0x%lx",
                   MP_FILTER_NAME(filter->f),
                   (unsigned long)(filter->bb_in));
        MP_RUN_CROAK(ap_get_brigade(filter->f->next, filter->bb_in,
                                    filter->input_mode, filter->block,
                                    filter->readbytes),
                     "Apache2::Filter::read");
    }

    len = modperl_filter_read(aTHX_ filter, buffer, wanted);

    if (filter->flush && len == 0) {
        /* if len > 0 then $filter->write will flush */
        apr_status_t rc = modperl_input_filter_flush(filter);

t/filter/TestFilter/both_str_con_add.pm  view on Meta::CPAN

sub handler {
    my Apache2::Connection $c = shift;

    # starting from Apache 2.0.49 several platforms require you to set
    # the socket to a blocking IO mode
    $c->client_socket->opt_set(APR::Const::SO_NONBLOCK, 0);

    my $bb = APR::Brigade->new($c->pool, $c->bucket_alloc);

    for (;;) {
        $c->input_filters->get_brigade($bb, Apache2::Const::MODE_GETLINE);
        last if $bb->is_empty;

        my $b = APR::Bucket::flush_create($c->bucket_alloc);
        $bb->insert_tail($b);
        $c->output_filters->pass_brigade($bb);
        # fflush is the equivalent of the previous 3 lines of code:
        # but it's tested elsewhere, here testing flush_create
        # $c->output_filters->fflush($bb);
    }

t/filter/TestFilter/in_bbs_body.pm  view on Meta::CPAN

use APR::Bucket ();

use TestCommon::Utils ();

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

sub handler : FilterRequestHandler {
    my ($filter, $bb, $mode, $block, $readbytes) = @_;

    $filter->next->get_brigade($bb, $mode, $block, $readbytes);

    for (my $b = $bb->first; $b; $b = $bb->next($b)) {

        last if $b->is_eos;

        if ($b->read(my $data)) {
            #warn"[$data]\n";
            my $nb = APR::Bucket->new($bb->bucket_alloc, scalar reverse $data);
            $b->insert_before($nb);
            $b->delete;

t/filter/TestFilter/in_bbs_consume.pm  view on Meta::CPAN

sub handler {
    my ($filter, $bb, $mode, $block, $readbytes) = @_;
    my $ba = $filter->r->connection->bucket_alloc;
    my $seen_eos = 0;
    my $satisfied = 0;
    my $buffer = '';
    debug_sub "filter called";

    until ($satisfied) {
        my $tbb = APR::Brigade->new($filter->r->pool, $ba);
        $filter->next->get_brigade($tbb, $mode, $block, READ_SIZE);
        debug "asking for a bb of " . READ_SIZE . " bytes\n";
        my $data;
        ($data, $seen_eos) = bb_data_n_eos($tbb);
        $tbb->destroy;
        $buffer .= $data;
        length($buffer) < READ_SIZE ? redo : $satisfied++;
    }

    # consume all the remaining input
    do {
        my $tbb = APR::Brigade->new($filter->r->pool, $ba);
        $filter->next->get_brigade($tbb, $mode, $block, $readbytes);
        debug "discarding the next bb";
        $seen_eos = bb_data_n_eos($tbb, 1); # only scan
        $tbb->destroy;
    } while (!$seen_eos);

    if ($seen_eos) {
        # flush the remainder
        $bb->insert_tail(APR::Bucket->new($ba, $buffer));
        $bb->insert_tail(APR::Bucket::eos_create($ba));
        debug "seen eos, sending: " . length($buffer) . " bytes";

t/filter/TestFilter/in_bbs_inject_header.pm  view on Meta::CPAN

        # the brigade unmodified
        debug "passing the body through unmodified";
        return Apache2::Const::DECLINED;
    }

    # any custom HTTP header buckets to inject?
    return Apache2::Const::OK if inject_header_bucket($bb, $ctx);

    # normal HTTP headers processing
    my $ctx_bb = APR::Brigade->new($c->pool, $c->bucket_alloc);
    my $rv = $filter->next->get_brigade($ctx_bb, $mode, $block, $readbytes);
    return $rv unless $rv == APR::Const::SUCCESS;

    while (!$ctx_bb->is_empty) {
        my $b = $ctx_bb->first;

        if ($b->is_eos) {
            debug "EOS!!!";
            $b->remove;
            $bb->insert_tail($b);
            last;

t/filter/TestFilter/in_bbs_underrun.pm  view on Meta::CPAN

    my $buffer = defined $ctx ? $ctx : '';
    $ctx = '';  # reset
    my $seen_eos = 0;
    my $data;
    debug_sub "filter called";

    # fetch and consume bucket brigades untill we have at least SIZE
    # bytes to work with
    do {
        my $tbb = APR::Brigade->new($filter->r->pool, $ba);
        $filter->next->get_brigade($tbb, $mode, $block, $readbytes);
        debug "asking for a bb";
        ($data, $seen_eos) = flatten_bb($tbb);
        $tbb->destroy;
        $buffer .= $data;
    } while (!$seen_eos && length($buffer) < SIZE);

    # now create a bucket per chunk of SIZE size and put the remainder
    # in ctx
    for (split_buffer($buffer)) {
        if (length($_) == SIZE) {

t/filter/TestFilter/in_init_basic.pm  view on Meta::CPAN

sub transparent : FilterRequestHandler
                  FilterHasInitHandler(\&transparent_init)
    {
    my ($filter, $bb, $mode, $block, $readbytes) = @_;

    my $ctx = $filter->ctx;
    $ctx->{run}++;
    $filter->r->notes->set(run => $ctx->{run});
    $filter->ctx($ctx);

    $filter->next->get_brigade($bb, $mode, $block, $readbytes);

    return Apache2::Const::OK;
}



# this filter is not supposed to get a chance to run, since its init
# handler immediately removes it
sub suicide_init : FilterInitHandler { shift->remove(); Apache2::Const::OK }
sub suicide      : FilterHasInitHandler(\&suicide_init) {

t/lib/TestCommon/FilterDebug.pm  view on Meta::CPAN

sub snoop {
    my $type = shift;
    my ($filter, $bb, $mode, $block, $readbytes) = @_; # filter args

    # $mode, $block, $readbytes are passed only for input filters
    my $stream = defined $mode ? "input" : "output";

    # read the data and pass-through the bucket brigades unchanged
    if (defined $mode) {
        # input filter
        my $rv = $filter->next->get_brigade($bb, $mode, $block, $readbytes);
        return $rv unless $rv == APR::Const::SUCCESS;
        bb_dump($type, $stream, $bb);
    }
    else {
        # output filter
        bb_dump($type, $stream, $bb);
        my $rv = $filter->next->pass_brigade($bb);
        return $rv unless $rv == APR::Const::SUCCESS;
    }
    #if ($bb->is_empty) {

t/lib/TestCommon/Utils.pm  view on Meta::CPAN

    my $r = shift;
    my $debug = shift || 0;

    my $bb = APR::Brigade->new($r->pool,
                               $r->connection->bucket_alloc);

    my $data = '';
    my $seen_eos = 0;
    my $count = 0;
    do {
        $r->input_filters->get_brigade($bb, Apache2::Const::MODE_READBYTES,
                                       APR::Const::BLOCK_READ, IOBUFSIZE);

        $count++;

        warn "read_post: bb $count\n" if $debug;

        while (!$bb->is_empty) {
            my $b = $bb->first;

            if ($b->is_eos) {

t/protocol/TestProtocol/echo_bbs.pm  view on Meta::CPAN

    my $c = shift;

    # starting from Apache 2.0.49 several platforms require you to set
    # the socket to a blocking IO mode
    $c->client_socket->opt_set(APR::Const::SO_NONBLOCK, 0);

    my $bb = APR::Brigade->new($c->pool, $c->bucket_alloc);

    while (1) {
        debug "asking new line";
        my $rc = $c->input_filters->get_brigade($bb, Apache2::Const::MODE_GETLINE);
        last if APR::Status::is_EOF($rc);
        die APR::Error::strerror($rc) unless $rc == APR::Const::SUCCESS;

        for (my $b = $bb->first; $b; $b = $bb->next($b)) {

            last if $b->is_eos;

            debug "processing new line";

            if ($b->read(my $data)) {

t/protocol/TestProtocol/echo_bbs2.pm  view on Meta::CPAN


    # starting from Apache 2.0.49 several platforms require you to set
    # the socket to a blocking IO mode
    $c->client_socket->opt_set(APR::Const::SO_NONBLOCK, 0);

    my $bb_in  = APR::Brigade->new($c->pool, $c->bucket_alloc);
    my $bb_out = APR::Brigade->new($c->pool, $c->bucket_alloc);

    my $last = 0;
    while (1) {
        my $rc = $c->input_filters->get_brigade($bb_in,
                                                Apache2::Const::MODE_GETLINE);
        last if APR::Status::is_EOF($rc);
        die APR::Error::strerror($rc) unless $rc == APR::Const::SUCCESS;

        next unless $bb_in->flatten(my $data);
        #warn "read: [$data]\n";
        last if $data =~ /^[\r\n]+$/;

        # transform data here
        my $bucket = APR::Bucket->new($bb_in->bucket_alloc, uc $data);

t/protocol/TestProtocol/echo_filter.pm  view on Meta::CPAN

sub handler {
    my $c = shift;

    # starting from Apache 2.0.49 several platforms require you to set
    # the socket to a blocking IO mode
    $c->client_socket->opt_set(APR::Const::SO_NONBLOCK, 0);

    my $bb = APR::Brigade->new($c->pool, $c->bucket_alloc);

    while (1) {
        my $rc = $c->input_filters->get_brigade($bb, Apache2::Const::MODE_GETLINE);
        last if APR::Status::is_EOF($rc);
        die APR::Error::strerror($rc) unless $rc == APR::Const::SUCCESS;

        # fflush is the equivalent of the following 3 lines of code:
        #
        # my $b = APR::Bucket::flush_create($c->bucket_alloc);
        # $bb->insert_tail($b);
        # $c->output_filters->pass_brigade($bb);
        $c->output_filters->fflush($bb);
    }

t/response/TestAPI/in_out_filters.pm  view on Meta::CPAN

sub read_request_body {
    my $r = shift;

    my $bb = APR::Brigade->new($r->pool,
                               $r->connection->bucket_alloc);

    my $data = '';
    my $seen_eos = 0;
    my $count = 0;
    do {
        $r->input_filters->get_brigade($bb, Apache2::Const::MODE_READBYTES,
                                       APR::Const::BLOCK_READ, IOBUFSIZE);

        $count++;

        for (my $b = $bb->first; $b; $b = $bb->next($b)) {
            if ($b->is_eos) {
                $seen_eos++;
                last;
            }

t/response/TestApache/discard_rbody.pm  view on Meta::CPAN


    if ($test eq 'none') {
        # don't read the request body
    }
    elsif ($test eq 'partial') {
        # read some of request POSTed data (IOBUFSIZE bytes),
        # but not all of it
        my $filters = $r->input_filters();
        my $ba = $r->connection->bucket_alloc;
        my $bb = APR::Brigade->new($r->pool, $ba);
        $filters->get_brigade($bb, Apache2::Const::MODE_READBYTES,
                              APR::Const::BLOCK_READ, IOBUFSIZE);
    }
    elsif ($test eq 'all') {
        # consume all of the request body
        my $data = TestCommon::Utils::read_post($r);
        die "failed to consume all the data" unless length($data) == 100000;
    }

    # now get rid of the rest of the input data should work, no matter
    # how little or how much of the body was read

xs/APR/Brigade/APR__Brigade.h  view on Meta::CPAN

SV *mpxs_apr_brigade_create(pTHX_ SV *CLASS, SV *p_sv,
                            apr_bucket_alloc_t *ba)
{
    apr_pool_t *p = mp_xs_sv2_APR__Pool(p_sv);
    apr_bucket_brigade *bb = apr_brigade_create(p, ba);
    SV *bb_sv = sv_setref_pv(newSV(0), "APR::Brigade", (void*)bb);
    mpxs_add_pool_magic(bb_sv, p_sv);
    return bb_sv;
}

#define get_brigade(brigade, fetch) \
(fetch(brigade) == APR_BRIGADE_SENTINEL(brigade) ? \
 NULL : fetch(brigade))

static MP_INLINE
apr_bucket *mpxs_APR__Brigade_first(apr_bucket_brigade *brigade)
{
    return get_brigade(brigade, APR_BRIGADE_FIRST);
}

static MP_INLINE
apr_bucket *mpxs_APR__Brigade_last(apr_bucket_brigade *brigade)
{
    return get_brigade(brigade, APR_BRIGADE_LAST);
}

#define get_bucket(brigade, bucket, fetch) \
(fetch(bucket) == APR_BRIGADE_SENTINEL(brigade) ? \
 NULL : fetch(bucket))

static MP_INLINE
apr_bucket *mpxs_APR__Brigade_next(apr_bucket_brigade *brigade,
                                    apr_bucket *bucket)
{

xs/Apache2/Filter/Apache2__Filter.h  view on Meta::CPAN

    /* if users don't bother to check the success, do it on their
     * behalf */
    if (GIMME_V == G_VOID && rc != APR_SUCCESS) {
        modperl_croak(aTHX_ rc, "Apache2::Filter::fflush");
    }

    return rc;
}

static MP_INLINE
apr_status_t mpxs_Apache2__Filter_get_brigade(pTHX_
                                             ap_filter_t *f,
                                             apr_bucket_brigade *bb,
                                             ap_input_mode_t mode,
                                             apr_read_type_e block,
                                             apr_off_t readbytes)
{
    apr_status_t rc = ap_get_brigade(f, bb, mode, block, readbytes);
    /* if users don't bother to check the success, do it on their
     * behalf */
    if (GIMME_V == G_VOID && rc != APR_SUCCESS) {
        modperl_croak(aTHX_ rc, "Apache2::Filter::get_brigade");
    }

    return rc;
}

static MP_INLINE
apr_status_t mpxs_Apache2__Filter_pass_brigade(pTHX_ ap_filter_t *f,
                                              apr_bucket_brigade *bb)
{
    apr_status_t rc = ap_pass_brigade(f, bb);

xs/maps/apache2_functions.map  view on Meta::CPAN

>ap_process_config_tree

MODULE=Apache2::Filter PACKAGE=guess
~ap_add_output_filter
~ap_add_input_filter
-ap_add_input_filter_handle
-ap_get_input_filter_handle
-ap_add_output_filter_handle
-ap_get_output_filter_handle
>ap_add_ouput_filters_by_type
~ap_get_brigade
 mpxs_Apache2__Filter_get_brigade | | \
               f, bb, mode=AP_MODE_READBYTES, \
               block=APR_BLOCK_READ, \
               readbytes=8192
~ap_pass_brigade
 mpxs_Apache2__Filter_pass_brigade
!ap_register_input_filter
!ap_register_output_filter
-ap_remove_output_filter
-ap_remove_input_filter
!ap_save_brigade

xs/tables/current/Apache2/FunctionTable.pm  view on Meta::CPAN

        'name' => 'r'
      },
      {
        'type' => 'const char **',
        'name' => 'pw'
      }
    ]
  },
  {
    'return_type' => 'apr_status_t',
    'name' => 'ap_get_brigade',
    'args' => [
      {
        'type' => 'ap_filter_t *',
        'name' => 'filter'
      },
      {
        'type' => 'apr_bucket_brigade *',
        'name' => 'bucket'
      },
      {

 view all matches for this distribution
 view release on metacpan -  search on metacpan

( run in 4.664 seconds using v1.00-cache-2.02-grep-82fe00e-cpan-3b7f77b76a6c )