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 >