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