Hi, thanks for the response.

To my knowledge (which is about a weeks worth) you don't need or indeed see
an end_of_stream bucket in a connection filter till the connection is closed
and then only in the output filter.

Conveniently the request headers seem to be passed from the core filter one
brigade at a time which makes my code quite easy, no need for buffering
buckets between calls.  As I said the code works fine until I append the
'data=test' to the end of the headers which should be my request body.

It's been driving me crazy all day and I can't understand why its doing what
it is doing! It's just frustrating because it sounds like something I should
be able to do.


James.



2010/8/26 Torsten Förtsch <torsten.foert...@gmx.net>

> On Thursday, August 26, 2010 18:28:47 James Lee wrote:
>
> A few comments below.
>
> The goal of the code is to fill up $bb. Nothing is copied there unless you
> do.
> The way you do it is to start with an empty brigade.
>
> > sub forward_get_as_post :FilterConnectionHandler
> > {
> >     my ($f, $bb, $mode, $block, $readbytes) = @_;
> >     my $ctx = $f->ctx || { 'state' => 'waiting_for_request_line' };
> >
> >     warn "state = ".$ctx->{'state'}."\r\n";
> >
> >     # check whether we need to process this request.
> >     return Apache2::Const::DECLINED if ($ctx->{'state'} eq 'ignore');
> >
> >     # read into a tmp brigade.
> >     my $connection = $f->c;
> >     my $tmp_bb = APR::Brigade->new($connection->pool,
> > $connection->bucket_alloc);
> >     my $rv = $f->next->get_brigade($tmp_bb, $mode, $block, $readbytes);
> >
> >     return $rv unless $rv == APR::Const::SUCCESS;
> >
> >     while (!$tmp_bb->is_empty)
> >     {
> >         # pop buckets from this brigade.
> >         my $bucket = $tmp_bb->first;
> >         $bucket->remove();
> >
> >         if ($ctx->{'state'} eq 'waiting_for_request_line')
> >         {
> >             # assumes request line is first bucket.
> >             $bucket->read(my $request_line);
> >             my ($method, $uri, $version) = ($request_line =~ m|^(.*?)
> (.*?)
> > HTTP/(.*?)\r\n$|);
> >
> >             if (defined ($method) and $method eq "GET" and $uri =~
> > m|^/echo|)
> >             {
> >                 my $new_uri = 'POST '.$uri.' HTTP/'.$version."\r\n";
> >                 my $new_uri_bucket =
> > APR::Bucket->new($connection->bucket_alloc, $new_uri);
> >
> >                 $bb->insert_tail($new_uri_bucket);
> >
> >                 my $bucket2 = APR::Bucket->new($connection->bucket_alloc,
> > "Content-Type: application/x-www-form-urlencoded\r\n");
> >                 $bb->insert_tail($bucket2);
> >
> >                 my $bucket3 = APR::Bucket->new($connection->bucket_alloc,
> > "Content-Length: 9\r\n");
> >                 $bb->insert_tail($bucket3);
>
> by now you have inserted these lines:
>
> POST /echo HTTP/1.1
> Content-Type: application/x-www-form-urlencoded
> Content-Length: 9
>
> You have read the 1st bucket of the input. That bucket may (or may not)
> contain the whole request including the empty line that signals end-of-
> headers. So, you have to check also the rest of the bucket.
>
> >
> >                 $ctx->{'state'} = 'waiting_for_end_of_headers';
> >             }
> >             else
> >             {
> >                 $bb->insert_tail($bucket);
> >                 $ctx->{'state'} = 'ignore';
> >             }
> >         }
> >         elsif ($ctx->{'state'} eq 'waiting_for_end_of_headers')
> >         {
> >             $bucket->read(my $header);
> >             warn "received header ... ".$header."\r\n";
> >
> >             if ($header =~ m|^\r\n$|)
> >             {
> >                 warn "detected end_of_headers\r\n";
> >
> >                 my $post_data = &get_post_data();
> >
> >
> >                 ### as soon as I add 'data=test' to this bucket the
> request
> > appears to hang.
> >                 ############################################
> >
> >
> >                 my $end_of_headers_bucket =
> > APR::Bucket->new($connection->bucket_alloc, "\r\ndata=test");
> >
> >                 $bb->insert_tail($end_of_headers_bucket);
>
> by now you have sent
>
> POST /echo HTTP/1.1
> Content-Type: application/x-www-form-urlencoded
> Content-Length: 9
>
> data=test
>
> Correct me if I am wrong but don't you have to insert an EOS marker?
> Haven't
> tried connection input filter yet. But normally a stream is closed with a
>
> $bb->insert_tail(APR::Bucket::eos_create $connection->bucket_alloc);
>
> >                 $ctx->{'state'} = 'finished';
> >             }
> >             else
> >             {
> >                 $bb->insert_tail($bucket);
> >             }
> >         }
> >     }
> >
> >     # set context.
> >     $f->ctx($ctx);
> >
> >     return Apache2::Const::OK;
> > }
>
> If it works with the EOS bucket it will probably work for most of the
> requests. But RFC2616 doesn't forbid GET requests to have a request body.
> That
> means you should read the input until EOS. Don't know if your code does
> that
> actually. Otherwise your client may still send the request while your
> handler
> is already done with the response.
>
> Torsten Förtsch
>
> --
> Need professional modperl support? Hire me! (http://foertsch.name)
>
> Like fantasy? http://kabatinte.net
>

Reply via email to