+# once this is called, all data we read is passed to the
+# to the PublicInbox::HTTP instance ($http) via $ofh->write
+# $ofh is typically PublicInbox::HTTP::{Chunked,Identity}, but
+# may be PublicInbox::GzipFilter or $PublicInbox::Qspawn::qx_fh
+sub async_pass {
+ my ($self, $http, $ofh, $bref) = @_;
+ delete @$self{qw(cb arg)};
+ # In case the client HTTP connection ($http) dies, it
+ # will automatically close this ($self) object.
+ $http->{forward} = $self;
+
+ # write anything we overread when we were reading headers.
+ # This is typically PublicInbox:HTTP::{chunked,identity}_wcb,
+ # but may be PublicInbox::GzipFilter::write. PSGI requires
+ # *_wcb methods respond to ->write (and ->close), not ->print
+ $ofh->write($$bref);
+
+ $self->{http} = $http;
+ $self->{ofh} = $ofh;
+}
+
+# may be called as $forward->close in PublicInbox::HTTP or EOF (event_step)
+sub close {
+ my $self = $_[0];
+ $self->SUPER::close; # DS::close
+ delete @$self{qw(cb arg)};
+
+ # we defer this to the next timer loop since close is deferred
+ if (my $end_obj = delete $self->{end_obj}) {
+ # this calls $end_obj->event_step
+ # (likely PublicInbox::Qspawn::event_step,
+ # NOT PublicInbox::HTTPD::Async::event_step)
+ PublicInbox::DS::requeue($end_obj);
+ }
+}