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